[root-system] 01/06: Imported Upstream version 5.34.10

Lifeng Sun lifengsun-guest at alioth.debian.org
Wed Sep 4 01:19:12 UTC 2013


This is an automated email from the git hooks/post-receive script.

lifengsun-guest pushed a commit to branch master
in repository root-system.

commit 6d8c78cb79a3accb09d3bead51066d8611d601b1
Author: Lifeng Sun <lifongsun at gmail.com>
Date:   Fri Aug 30 07:35:26 2013 +0800

    Imported Upstream version 5.34.10
---
 .gitignore                                         |    3 +
 Makefile                                           |    6 +-
 README/CREDITS                                     |    4 +
 bindings/pyroot/ROOT.py                            |   11 +-
 bindings/pyroot/src/Pythonize.cxx                  |   44 +
 .../package/common/root-plugin-sql-sqlite.control  |   15 +
 build/version_number                               |    2 +-
 cint/cint/src/func.cxx                             |    2 +-
 cint/cint/src/sizeof.cxx                           |    2 +-
 cint/cintex/src/CINTTypedefBuilder.cxx             |    2 +
 cint/cintex/src/Cintex.cxx                         |    8 +-
 cint/reflex/python/genreflex/genreflex.py          |    5 +-
 cmake/modules/FindPythia6.cmake                    |    4 +-
 cmake/modules/FindROOTInternal.cmake               |  258 +--
 cmake/modules/FindSqlite.cmake                     |   50 +
 cmake/modules/RootBuildOptions.cmake               |    1 +
 cmake/modules/RootConfiguration.cmake              |    5 +
 cmake/modules/RootNewMacros.cmake                  |    8 +-
 cmake/modules/SearchInstalledSoftware.cmake        |   14 +
 config/Makefile.depend                             |    4 +
 config/Makefile.in                                 |    5 +
 config/html.C.in                                   |    2 +
 config/rootrc.in                                   |   41 +-
 configure                                          |   50 +
 core/base/inc/MessageTypes.h                       |    4 +-
 core/base/inc/RVersion.h                           |   10 +-
 core/base/inc/TAttFill.h                           |   11 +-
 core/base/inc/TAttText.h                           |    3 +
 core/base/inc/TStyle.h                             |    6 +-
 core/base/inc/TVirtualPS.h                         |    2 +-
 core/base/src/TAttText.cxx                         |   10 +
 core/base/src/TContextMenu.cxx                     |    7 +-
 core/base/src/TFileCollection.cxx                  |    7 +-
 core/base/src/TStorage.cxx                         |    6 +-
 core/base/src/TStyle.cxx                           |    3 +
 core/base/src/TTimer.cxx                           |    3 +-
 core/base/src/TVirtualPS.cxx                       |    8 +-
 core/cont/inc/TBits.h                              |    2 +
 core/cont/src/TBits.cxx                            |   78 +
 core/macosx/inc/CocoaUtils.h                       |    6 +-
 core/macosx/inc/TMacOSXSystem.h                    |    4 +
 core/macosx/src/CocoaUtils.mm                      |   13 +-
 core/macosx/src/TMacOSXSystem.mm                   |  271 +--
 core/meta/inc/LinkDef.h                            |    1 +
 core/meta/inc/TCint.h                              |    2 +-
 core/meta/inc/TClass.h                             |   11 +
 core/meta/inc/TClassAttributeMap.h                 |   60 +
 core/meta/inc/TInterpreter.h                       |    2 +-
 core/meta/inc/TStreamerElement.h                   |    5 +-
 core/meta/src/TCint.cxx                            |   35 +-
 core/meta/src/TClass.cxx                           |   27 +-
 core/meta/src/TClassAttributeMap.cxx               |  164 ++
 core/meta/src/TStreamerElement.cxx                 |   94 +-
 core/unix/src/TUnixSystem.cxx                      |    1 +
 core/utils/src/rootcint.cxx                        |   14 +
 core/winnt/src/Win32Splash.cxx                     |    5 +-
 doc/v534/index.html                                |    2 +-
 etc/HistFactorySchema.dtd                          |    4 +
 etc/plugins/TSQLServer/P060_TSQLiteServer.C        |    5 +
 etc/plugins/TVirtualPS/P050_TTeXDump.C             |    5 +
 geom/gdml/src/TGDMLParse.cxx                       |  260 +--
 geom/geom/inc/TGeoArb8.h                           |   41 +-
 geom/geom/inc/TGeoBBox.h                           |   17 +-
 geom/geom/inc/TGeoBoolNode.h                       |   40 +-
 geom/geom/inc/TGeoCompositeShape.h                 |   15 +-
 geom/geom/inc/TGeoCone.h                           |   51 +-
 geom/geom/inc/TGeoEltu.h                           |   15 +-
 geom/geom/inc/TGeoExtension.h                      |    8 +-
 geom/geom/inc/TGeoHalfSpace.h                      |   15 +-
 geom/geom/inc/TGeoHype.h                           |   19 +-
 geom/geom/inc/TGeoManager.h                        |    2 +
 geom/geom/inc/TGeoMatrix.h                         |    1 +
 geom/geom/inc/TGeoNode.h                           |    4 +-
 geom/geom/inc/TGeoPara.h                           |   15 +-
 geom/geom/inc/TGeoParaboloid.h                     |   17 +-
 geom/geom/inc/TGeoPatternFinder.h                  |    3 +
 geom/geom/inc/TGeoPcon.h                           |   19 +-
 geom/geom/inc/TGeoPgon.h                           |   33 +-
 geom/geom/inc/TGeoPolygon.h                        |    6 +-
 geom/geom/inc/TGeoScaledShape.h                    |   15 +-
 geom/geom/inc/TGeoShape.h                          |   29 +-
 geom/geom/inc/TGeoShapeAssembly.h                  |   15 +-
 geom/geom/inc/TGeoSphere.h                         |   22 +-
 geom/geom/inc/TGeoTorus.h                          |   23 +-
 geom/geom/inc/TGeoTrd1.h                           |   19 +-
 geom/geom/inc/TGeoTrd2.h                           |   19 +-
 geom/geom/inc/TGeoTube.h                           |   61 +-
 geom/geom/inc/TGeoVolume.h                         |    4 +-
 geom/geom/inc/TGeoVoxelFinder.h                    |   16 +-
 geom/geom/inc/TGeoXtru.h                           |   21 +-
 geom/geom/inc/TVirtualGeoTrack.h                   |    2 +-
 geom/geom/src/TGeoArb8.cxx                         |  115 +-
 geom/geom/src/TGeoBBox.cxx                         |   56 +-
 geom/geom/src/TGeoBoolNode.cxx                     |   33 +-
 geom/geom/src/TGeoBranchArray.cxx                  |    2 -
 geom/geom/src/TGeoCache.cxx                        |    3 +-
 geom/geom/src/TGeoCompositeShape.cxx               |   51 +-
 geom/geom/src/TGeoCone.cxx                         |  122 +-
 geom/geom/src/TGeoElement.cxx                      |    1 +
 geom/geom/src/TGeoEltu.cxx                         |   51 +-
 geom/geom/src/TGeoHalfSpace.cxx                    |   51 +-
 geom/geom/src/TGeoHype.cxx                         |   55 +-
 geom/geom/src/TGeoManager.cxx                      |   28 +-
 geom/geom/src/TGeoMaterial.cxx                     |   14 +-
 geom/geom/src/TGeoMatrix.cxx                       |   23 +-
 geom/geom/src/TGeoNavigator.cxx                    |   12 +-
 geom/geom/src/TGeoNode.cxx                         |  101 +-
 geom/geom/src/TGeoPara.cxx                         |   50 +-
 geom/geom/src/TGeoParaboloid.cxx                   |   53 +-
 geom/geom/src/TGeoPcon.cxx                         |   55 +-
 geom/geom/src/TGeoPgon.cxx                         |   69 +-
 geom/geom/src/TGeoPhysicalNode.cxx                 |    2 +-
 geom/geom/src/TGeoPolygon.cxx                      |    6 +-
 geom/geom/src/TGeoScaledShape.cxx                  |   51 +-
 geom/geom/src/TGeoShape.cxx                        |   24 +-
 geom/geom/src/TGeoShapeAssembly.cxx                |   52 +-
 geom/geom/src/TGeoSphere.cxx                       |   83 +-
 geom/geom/src/TGeoStateInfo.cxx                    |   16 +
 geom/geom/src/TGeoTorus.cxx                        |   58 +-
 geom/geom/src/TGeoTrd1.cxx                         |   55 +-
 geom/geom/src/TGeoTrd2.cxx                         |   54 +-
 geom/geom/src/TGeoTube.cxx                         |  169 +-
 geom/geom/src/TGeoVolume.cxx                       |   72 +-
 geom/geom/src/TGeoVoxelFinder.cxx                  |   16 +-
 geom/geom/src/TGeoXtru.cxx                         |  172 +-
 geom/geom/src/TVirtualGeoTrack.cxx                 |   12 +
 graf2d/asimage/src/TASImage.cxx                    |    9 +-
 graf2d/asimage/src/libAfterImage/libpng/LICENSE    |    8 +-
 graf2d/asimage/src/libAfterImage/libpng/png.c      |  784 +++++---
 graf2d/asimage/src/libAfterImage/libpng/png.h      | 1590 +++++++++-------
 graf2d/asimage/src/libAfterImage/libpng/pngconf.h  |  410 ++--
 graf2d/asimage/src/libAfterImage/libpng/pngerror.c |  195 +-
 graf2d/asimage/src/libAfterImage/libpng/pngget.c   |  341 ++--
 graf2d/asimage/src/libAfterImage/libpng/pngmem.c   |  155 +-
 graf2d/asimage/src/libAfterImage/libpng/pngpread.c |  931 +++------
 graf2d/asimage/src/libAfterImage/libpng/pngread.c  |  801 ++++----
 graf2d/asimage/src/libAfterImage/libpng/pngrio.c   |   87 +-
 graf2d/asimage/src/libAfterImage/libpng/pngrtran.c | 1008 ++++++----
 graf2d/asimage/src/libAfterImage/libpng/pngrutil.c | 1380 ++++++++------
 graf2d/asimage/src/libAfterImage/libpng/pngset.c   |  979 +++++-----
 graf2d/asimage/src/libAfterImage/libpng/pngtrans.c |  149 +-
 graf2d/asimage/src/libAfterImage/libpng/pngwio.c   |  156 +-
 graf2d/asimage/src/libAfterImage/libpng/pngwrite.c |  729 ++++----
 graf2d/asimage/src/libAfterImage/libpng/pngwtran.c |   86 +-
 graf2d/asimage/src/libAfterImage/libpng/pngwutil.c | 1076 +++++------
 graf2d/cocoa/inc/CocoaPrivate.h                    |    5 +-
 graf2d/cocoa/inc/MenuLoader.h                      |    2 +-
 graf2d/cocoa/inc/QuartzPixmap.h                    |   14 +-
 graf2d/cocoa/inc/QuartzWindow.h                    |   14 +-
 graf2d/cocoa/inc/ROOTApplicationDelegate.h         |    2 +-
 graf2d/cocoa/inc/ROOTOpenGLView.h                  |    4 +-
 graf2d/cocoa/inc/X11Drawable.h                     |   14 +-
 graf2d/cocoa/src/QuartzPixmap.mm                   |   26 +-
 graf2d/cocoa/src/QuartzWindow.mm                   |   38 +-
 graf2d/cocoa/src/ROOTApplicationDelegate.mm        |    4 +-
 graf2d/cocoa/src/ROOTOpenGLView.mm                 |    8 +-
 graf2d/cocoa/src/TGCocoa.mm                        |   13 +
 graf2d/cocoa/src/TGQuartz.mm                       |   46 +-
 graf2d/gpad/src/TCanvas.cxx                        |   11 +-
 graf2d/gpad/src/TPad.cxx                           |   83 +-
 graf2d/graf/inc/TTF.h                              |    1 -
 graf2d/graf/src/TLatex.cxx                         |   25 +-
 graf2d/graf/src/TLegend.cxx                        |   64 +-
 graf2d/graf/src/TMathText.cxx                      |    6 +-
 graf2d/gviz/doc/index.txt                          |    5 +
 graf2d/mathtext/src/mathrenderstyle.cxx            |    6 +-
 graf2d/postscript/inc/LinkDef.h                    |    1 +
 graf2d/postscript/inc/TPDF.h                       |    2 +-
 graf2d/postscript/inc/TTeXDump.h                   |   90 +
 graf2d/postscript/src/TPDF.cxx                     |   13 +-
 graf2d/postscript/src/TPostScript.cxx              |    2 +-
 graf2d/postscript/src/TSVG.cxx                     |    2 +-
 graf2d/postscript/src/TTeXDump.cxx                 |  923 +++++++++
 graf2d/qt/src/TQtTimer.cxx                         |    2 +-
 graf3d/eve/inc/TEveBrowser.h                       |    5 +-
 graf3d/eve/src/TEveBrowser.cxx                     |   28 +-
 graf3d/eve/src/TEveTrackPropagator.cxx             |   13 +-
 gui/gui/src/HelpText.cxx                           |    1 +
 gui/gui/src/TGFontDialog.cxx                       |    6 +-
 gui/gui/src/TGListTree.cxx                         |    3 +-
 gui/gui/src/TRootBrowserLite.cxx                   |    1 -
 gui/gui/src/TRootCanvas.cxx                        |    2 +
 gui/gui/src/TRootContextMenu.cxx                   |    5 +-
 gui/sessionviewer/inc/TProofProgressLog.h          |    8 +-
 gui/sessionviewer/src/TProofProgressLog.cxx        |  130 +-
 hist/hist/inc/TGraph2D.h                           |    2 +
 hist/hist/inc/TH2Poly.h                            |    1 +
 hist/hist/inc/TMultiGraph.h                        |    8 +-
 hist/hist/src/TAxis.cxx                            |    6 +-
 hist/hist/src/TFormula.cxx                         |   28 +-
 hist/hist/src/TGraph.cxx                           |    9 +
 hist/hist/src/TGraph2D.cxx                         |    2 +-
 hist/hist/src/TGraphDelaunay.cxx                   |    2 +-
 hist/hist/src/TH1.cxx                              |    5 +-
 hist/hist/src/TH2Poly.cxx                          |    8 +
 hist/hist/src/TH3.cxx                              |    2 +-
 hist/hist/src/TMultiGraph.cxx                      |  108 +-
 hist/histpainter/inc/TPainter3dAlgorithms.h        |    5 +
 hist/histpainter/src/TGraph2DPainter.cxx           |   12 +-
 hist/histpainter/src/THistPainter.cxx              |  465 +++--
 hist/histpainter/src/TPainter3dAlgorithms.cxx      |  249 ++-
 io/io/src/TDirectoryFile.cxx                       |    4 +-
 io/io/src/TGenCollectionProxy.cxx                  |    2 +-
 io/io/src/TStreamerInfo.cxx                        |  190 +-
 io/io/src/TStreamerInfoActions.cxx                 |   53 +-
 io/io/src/TStreamerInfoReadBuffer.cxx              |    2 +
 io/xml/src/TXMLEngine.cxx                          |    7 +-
 math/mathcore/inc/Math/OneDimFunctionAdapter.h     |    7 +-
 math/minuit/src/TMinuitMinimizer.cxx               |    7 +
 math/smatrix/inc/Math/CholeskyDecomp.h             |  224 ++-
 net/netx/Module.mk                                 |    2 +-
 proof/afdsmgrd/afdsmgrd-v1.0.6.tar.gz              |  Bin 1437421 -> 0 bytes
 proof/afdsmgrd/afdsmgrd-v1.1.0.tar.gz              |  Bin 0 -> 1438597 bytes
 proof/doc/confman/ConfigProofPoD.md                |  194 ++
 proof/doc/confman/DatasetStager.md                 |  183 ++
 proof/doc/confman/DeployVirtualAnalysisFacility.md |  220 +++
 proof/doc/confman/Makefile                         |   54 +
 proof/doc/confman/TDataSetManagerAliEn.md          |  429 +++++
 proof/doc/confman/UsingVirtualAnalysisFacility.md  |  379 ++++
 proof/doc/confman/css/github.css                   |  300 +++
 proof/doc/confman/img/sshcertauth-web.png          |  Bin 0 -> 65357 bytes
 proof/proof/inc/TDSet.h                            |    6 +-
 proof/proof/inc/TDataSetManagerAliEn.h             |    4 +-
 proof/proof/inc/TProof.h                           |   31 +-
 proof/proof/inc/TProofLog.h                        |    4 +-
 proof/proof/inc/TSlave.h                           |    3 +
 proof/proof/inc/TVirtualProofPlayer.h              |    1 +
 proof/proof/src/TDSet.cxx                          |   10 +-
 proof/proof/src/TDataSetManagerAliEn.cxx           |   42 +-
 proof/proof/src/TProof.cxx                         |  513 ++++-
 proof/proof/src/TProofLite.cxx                     |    3 +
 proof/proof/src/TProofLog.cxx                      |   44 +-
 proof/proof/src/TProofServ.cxx                     |  288 ++-
 proof/proofbench/inc/TProofPerfAnalysis.h          |   30 +-
 proof/proofbench/src/TProofPerfAnalysis.cxx        |  808 +++++++-
 proof/proofd/inc/XrdProofdProofServMgr.h           |    8 +-
 proof/proofd/src/XrdProofSched.cxx                 |    6 +-
 proof/proofd/src/XrdProofdAdmin.cxx                |   18 +-
 proof/proofd/src/XrdProofdNetMgr.cxx               |   10 +-
 proof/proofd/src/XrdProofdProofServMgr.cxx         |   43 +-
 proof/proofplayer/inc/TPacketizerUnit.h            |    9 +-
 proof/proofplayer/inc/TProofPlayer.h               |   14 +-
 proof/proofplayer/inc/TVirtualPacketizer.h         |    1 +
 proof/proofplayer/src/TPacketizerUnit.cxx          |  140 +-
 proof/proofplayer/src/TProofDraw.cxx               |    5 +-
 proof/proofplayer/src/TProofPlayer.cxx             |  154 +-
 proof/proofplayer/src/TVirtualPacketizer.cxx       |   11 +
 proof/proofx/src/TXProofMgr.cxx                    |   24 +-
 proof/proofx/src/TXProofServ.cxx                   |    9 +-
 roofit/CMakeLists.txt                              |    1 +
 roofit/histfactory/inc/LinkDef.h                   |    1 +
 .../histfactory/inc/RooStats/HistFactory/Channel.h |   18 +-
 roofit/histfactory/inc/RooStats/HistFactory/Data.h |    2 +-
 .../RooStats/HistFactory/HistFactoryNavigation.h   |   44 +-
 .../HistFactory/MakeModelAndMeasurementsFast.h     |    3 +-
 .../inc/RooStats/HistFactory/Measurement.h         |   25 +-
 .../inc/RooStats/HistFactory/ParamHistFunc.h       |   11 +-
 .../inc/RooStats/HistFactory/PreprocessFunction.h  |    1 +
 .../histfactory/inc/RooStats/HistFactory/Sample.h  |   19 +-
 .../inc/RooStats/HistFactory/Systematics.h         |  101 +-
 roofit/histfactory/src/Asimov.cxx                  |   18 +
 roofit/histfactory/src/Channel.cxx                 |   90 +-
 roofit/histfactory/src/ConfigParser.cxx            |   60 +-
 roofit/histfactory/src/Data.cxx                    |   28 +
 roofit/histfactory/src/HistFactoryNavigation.cxx   |  440 +++--
 .../src/HistoToWorkspaceFactoryFast.cxx            |  173 +-
 .../src/MakeModelAndMeasurementsFast.cxx           |  516 +++--
 roofit/histfactory/src/Measurement.cxx             |  173 +-
 roofit/histfactory/src/ParamHistFunc.cxx           |  367 ++--
 roofit/histfactory/src/PreprocessFunction.cxx      |   25 +
 roofit/histfactory/src/RooBarlowBeestonLL.cxx      |   19 +-
 roofit/histfactory/src/Sample.cxx                  |   87 +-
 roofit/histfactory/src/Systematics.cxx             |  168 +-
 roofit/histfactory/src/hist2workspace.cxx          |   90 +-
 roofit/roofit/inc/RooChebychev.h                   |    1 +
 roofit/roofit/inc/RooGExpModel.h                   |   32 +-
 roofit/roofit/inc/RooGaussModel.h                  |   27 +-
 roofit/roofit/inc/RooKeysPdf.h                     |    6 +
 roofit/roofit/src/RooChebychev.cxx                 |   99 +-
 roofit/roofit/src/RooGExpModel.cxx                 |   72 +-
 roofit/roofit/src/RooGaussModel.cxx                |  111 +-
 roofit/roofit/src/RooKeysPdf.cxx                   |   64 +-
 roofit/roofit/src/RooVoigtian.cxx                  |   15 +-
 roofit/roofitcore/Module.mk                        |    2 +-
 roofit/roofitcore/inc/LinkDef1.h                   |    2 +-
 roofit/roofitcore/inc/RooAbsArg.h                  |   11 +-
 roofit/roofitcore/inc/RooAbsPdf.h                  |    2 +-
 roofit/roofitcore/inc/RooAbsReal.h                 |   19 +-
 roofit/roofitcore/inc/RooAbsTestStatistic.h        |    4 +
 roofit/roofitcore/inc/RooBinning.h                 |   91 +-
 roofit/roofitcore/inc/RooComplex.h                 |   17 +-
 roofit/roofitcore/inc/RooMath.h                    |  113 +-
 roofit/roofitcore/inc/RooMinimizer.h               |   26 +-
 roofit/roofitcore/inc/RooNLLVar.h                  |    4 +-
 roofit/roofitcore/inc/RooRealMPFE.h                |   13 +-
 roofit/roofitcore/inc/RooSimultaneous.h            |    2 +-
 roofit/roofitcore/src/BidirMMapPipe.cxx            | 1967 ++++++++++++++++++++
 roofit/roofitcore/src/BidirMMapPipe.h              |  974 ++++++++++
 roofit/roofitcore/src/RooAbsArg.cxx                |  160 +-
 roofit/roofitcore/src/RooAbsData.cxx               |   22 +-
 roofit/roofitcore/src/RooAbsOptTestStatistic.cxx   |   15 +-
 roofit/roofitcore/src/RooAbsPdf.cxx                |   87 +-
 roofit/roofitcore/src/RooAbsReal.cxx               |   32 +-
 roofit/roofitcore/src/RooAbsTestStatistic.cxx      |  391 ++--
 roofit/roofitcore/src/RooBanner.cxx                |    2 +-
 roofit/roofitcore/src/RooBinning.cxx               |  422 ++---
 roofit/roofitcore/src/RooChi2Var.cxx               |    1 +
 roofit/roofitcore/src/RooComplex.cxx               |   10 +-
 roofit/roofitcore/src/RooMath.cxx                  |  133 +-
 roofit/roofitcore/src/RooMinimizer.cxx             |   39 +
 roofit/roofitcore/src/RooNLLVar.cxx                |   39 +-
 roofit/roofitcore/src/RooRealMPFE.cxx              |  400 ++--
 roofit/roofitcore/src/RooSentinel.cxx              |    2 -
 roofit/roofitcore/src/RooTrace.cxx                 |    4 +-
 roofit/roofitcore/src/RooXYChi2Var.cxx             |    1 +
 sql/CMakeLists.txt                                 |    3 +
 sql/pgsql/inc/TPgSQLStatement.h                    |    2 +
 sql/pgsql/src/TPgSQLStatement.cxx                  |  103 +-
 sql/sqlite/CMakeLists.txt                          |   13 +
 sql/sqlite/Module.mk                               |   72 +
 sql/sqlite/inc/LinkDef.h                           |   12 +
 sql/sqlite/inc/TSQLiteResult.h                     |   45 +
 sql/sqlite/inc/TSQLiteRow.h                        |   43 +
 sql/sqlite/inc/TSQLiteServer.h                     |   57 +
 .../inc/TSQLiteStatement.h}                        |   54 +-
 sql/sqlite/src/TSQLiteResult.cxx                   |  111 ++
 sql/sqlite/src/TSQLiteRow.cxx                      |   86 +
 sql/sqlite/src/TSQLiteServer.cxx                   |  369 ++++
 sql/sqlite/src/TSQLiteStatement.cxx                |  590 ++++++
 test/Makefile                                      |   47 +-
 test/sqlitetest.cxx                                |  215 +++
 test/stressGraphics.ref                            |   20 +-
 test/stressProof.cxx                               |  256 ++-
 test/stressRooFit.cxx                              |   20 +-
 tree/tree/inc/TBranchElement.h                     |   16 +-
 tree/tree/src/TBranchBrowsable.cxx                 |   20 +-
 tree/tree/src/TBranchElement.cxx                   |   89 +-
 tree/tree/src/TLeafB.cxx                           |   19 +-
 tree/tree/src/TTree.cxx                            |   11 +-
 tree/treeplayer/src/TTreeFormula.cxx               |   11 +-
 tutorials/hist/th2polyEurope.C                     |   31 +-
 tutorials/hist/th2polyUSA.C                        |    5 +
 tutorials/proof/ProofNtuple.C                      |   17 +-
 tutorials/proof/ProofNtuple.h                      |    3 +-
 344 files changed, 23152 insertions(+), 9063 deletions(-)

diff --git a/.gitignore b/.gitignore
index 9947c62..a199420 100644
--- a/.gitignore
+++ b/.gitignore
@@ -334,6 +334,8 @@ cint/cint/src/loadfile_tmp.cxx
 /test/EventMTDict.h
 /test/EventMTDict.cxx
 /test/event.par
+/test/sqlitetest
+/test/testdb.sqlite
 /test/stress
 /test/stress.exe
 /test/stressEntryList
@@ -452,3 +454,4 @@ cint/cint/src/loadfile_tmp.cxx
 /tutorials/tree/hvector.root
 /tutorials/tree/cernstaff.root
 /tutorials/tree/staff.root
+/tutorials/tree/basic.root
diff --git a/Makefile b/Makefile
index 5316069..5241417 100644
--- a/Makefile
+++ b/Makefile
@@ -137,6 +137,9 @@ endif
 ifeq ($(BUILDPGSQL),yes)
 MODULES      += sql/pgsql
 endif
+ifeq ($(BUILDSQLITE),yes)
+MODULES      += sql/sqlite
+endif
 ifeq ($(BUILDSAPDB),yes)
 MODULES      += sql/sapdb
 endif
@@ -284,7 +287,7 @@ ifneq ($(findstring $(MAKECMDGOALS),distclean maintainer-clean),)
 MODULES      += core/unix core/winnt graf2d/x11 graf2d/x11ttf \
                 graf3d/gl graf3d/ftgl graf3d/glew io/rfio io/castor \
                 montecarlo/pythia6 montecarlo/pythia8 misc/table \
-                sql/mysql sql/pgsql sql/sapdb net/srputils graf3d/x3d \
+                sql/mysql sql/pgsql sql/sqlite sql/sapdb net/srputils graf3d/x3d \
                 rootx net/rootd io/dcache io/chirp hist/hbook graf2d/asimage \
                 net/ldap net/krb5auth net/rpdutils net/globusauth \
                 bindings/pyroot bindings/ruby io/gfal misc/minicern \
@@ -1425,6 +1428,7 @@ showbuild:
 	@echo "GVIZLIB            = $(GVIZLIB)"
 	@echo "GVIZINCDIR         = $(GVIZINCDIR)"
 	@echo "SAPDBINCDIR        = $(SAPDBINCDIR)"
+	@echo "SQLITEINCDIR       = $(SQLITEINCDIR)"
 	@echo "SRPLIBDIR          = $(SRPLIBDIR)"
 	@echo "SRPINCDIR          = $(SRPINCDIR)"
 	@echo "SRPUTILLIB         = $(SRPUTILLIB)"
diff --git a/README/CREDITS b/README/CREDITS
index df301d9..0ba8ee9 100644
--- a/README/CREDITS
+++ b/README/CREDITS
@@ -275,6 +275,10 @@ N: John Frankland
 E: frankland at ganil.fr
 D: TString contributions
 
+N: Oliver Freyermuth
+E: o.f at cern.ch
+D: SQLite plugin
+
 N: Keisuke Fujii
 E: fujiik at jlcuxf.kek.jp
 D: port to MacOS X
diff --git a/bindings/pyroot/ROOT.py b/bindings/pyroot/ROOT.py
index 11e59ed..594d7ca 100755
--- a/bindings/pyroot/ROOT.py
+++ b/bindings/pyroot/ROOT.py
@@ -34,7 +34,7 @@ if sys.version[0:3] == '2.2':
 try:
    import rlcompleter, readline
 
-   class FileNameCompleter( rlcompleter.Completer ):
+   class RootNameCompleter( rlcompleter.Completer ):
       def file_matches( self, text ):
          matches = []
          path, name = os.path.split( text )
@@ -69,11 +69,14 @@ try:
          matches = rlcompleter.Completer.attr_matches( self, text )
          if not matches: matches = []
          b = text.find('.')
-         if 0 <= b and self.namespace[text[:b]].__name__ == 'ROOT':
-            matches += self.root_global_matches( text[b+1:], text[:b+1] )
+         try:
+            if 0 <= b and self.namespace[text[:b]].__name__ == 'ROOT':
+               matches += self.root_global_matches( text[b+1:], text[:b+1] )
+         except AttributeError:    # not all objects have a __name__
+            pass
          return matches
 
-   readline.set_completer( FileNameCompleter().complete )
+   readline.set_completer( RootNameCompleter().complete )
    readline.set_completer_delims(
       readline.get_completer_delims().replace( os.sep , '' ) )
 
diff --git a/bindings/pyroot/src/Pythonize.cxx b/bindings/pyroot/src/Pythonize.cxx
index f2d1ad3..23a31a0 100644
--- a/bindings/pyroot/src/Pythonize.cxx
+++ b/bindings/pyroot/src/Pythonize.cxx
@@ -829,6 +829,44 @@ namespace {
       return CallSelfIndex( self, (PyObject*)index, "_vector__at" );
    }
 
+   PyObject* VectorBoolSetItem( ObjectProxy* self, PyObject* args )
+   {
+   // std::vector<bool> is a special-case in C++, and its return type depends on
+   // the compiler: treat it special here as well
+      int bval = 0; PyObject* idx = 0;
+      if ( ! PyArg_ParseTuple( args, const_cast< char* >( "Oi:__setitem__" ), &idx, &bval ) )
+         return 0;
+
+      if ( ! self->GetObject() ) {
+         PyErr_SetString( PyExc_TypeError, "unsubscriptable object" );
+         return 0;
+      }
+
+      PyObject* pyindex = PyStyleIndex( (PyObject*)self, idx );
+      if ( ! pyindex )
+         return 0;
+      int index = (int)PyLong_AsLong( pyindex );
+      Py_DECREF( pyindex );
+
+      std::string clName = self->ObjectIsA()->GetName();
+      std::string::size_type pos = clName.find( "vector<bool" );
+      if ( pos != 0 && pos != 5 /* following std:: */ ) {
+         PyErr_Format( PyExc_TypeError,
+                       "require object of type std::vector<bool>, but %s given",
+                       self->ObjectIsA()->GetName() );
+         return 0;
+      }
+
+   // get hold of the actual std::vector<bool> (no cast, as vector is never a base)
+      std::vector<bool>* vb = (std::vector<bool>*)self->GetObject();
+
+   // finally, set the value
+      (*vb)[ index ] = (bool)bval;
+
+      Py_INCREF( Py_None );
+      return Py_None;
+   }
+
 //- map behavior as primitives ------------------------------------------------
    PyObject* MapContains( PyObject* self, PyObject* obj )
    {
@@ -2120,6 +2158,12 @@ Bool_t PyROOT::Pythonize( PyObject* pyclass, const std::string& name )
       if ( HasAttrDirect( pyclass, PyStrings::gVectorAt ) )
          Utility::AddToClass( pyclass, "__getitem__", (PyCFunction) VectorGetItem, METH_O );
 
+   // std::vector<bool> is a special case in C++
+      std::string::size_type pos = name.find( "vector<bool" ); // to cover all variations
+      if ( pos == 0 /* at beginning */ || pos == 5 /* after std:: */ ) {
+         Utility::AddToClass( pyclass, "__setitem__", (PyCFunction) VectorBoolSetItem );
+      }
+
       return kTRUE;
    }
 
diff --git a/build/package/common/root-plugin-sql-sqlite.control b/build/package/common/root-plugin-sql-sqlite.control
new file mode 100644
index 0000000..61a2364
--- /dev/null
+++ b/build/package/common/root-plugin-sql-sqlite.control
@@ -0,0 +1,15 @@
+Package: root-plugin-sql-sqlite
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Provides: root-db-client
+Description: SQLite client plugin for ROOT
+ The ROOT system provides a set of OO frameworks with all the
+ functionality needed to handle and analyze large amounts of data
+ efficiently.
+ .
+ This package contains the SQLite plug-in for ROOT.  This plugin
+ provides a thin client (interface) to SQLite database files. Using this
+ client, one can obtain information from a SQLite database into the
+ ROOT environment.
+
+
diff --git a/build/version_number b/build/version_number
index 95a20b9..9511712 100644
--- a/build/version_number
+++ b/build/version_number
@@ -1 +1 @@
-5.34/09
+5.34/10
diff --git a/cint/cint/src/func.cxx b/cint/cint/src/func.cxx
index 51a4324..3cdd1e6 100644
--- a/cint/cint/src/func.cxx
+++ b/cint/cint/src/func.cxx
@@ -3645,7 +3645,7 @@ int G__special_func(G__value* result7, char* funcname, G__param* libp, int hash)
          G__letint(result7, 'u', (long)G__typeid(libp->parameter[0]));
       }
       result7->ref = result7->obj.i;
-      result7->tagnum = *(int*)(result7->ref);
+      if (result7->ref) result7->tagnum = *(int*)(result7->ref);
       return 1;
    }
 #endif // G__TYPEINFO
diff --git a/cint/cint/src/sizeof.cxx b/cint/cint/src/sizeof.cxx
index 2401e83..3d99855 100644
--- a/cint/cint/src/sizeof.cxx
+++ b/cint/cint/src/sizeof.cxx
@@ -404,7 +404,7 @@ long *G__typeid(const char *typenamein)
   * Get type_info tagname
   ***********************************************************************/
   tag_type_info = G__defined_tagname("type_info",1);
-  if(-1==tag_type_info) {
+  if(-1==tag_type_info || G__struct.size[tag_type_info] == 0) {
     G__genericerror("Error: class type_info not defined. <typeinfo.h> must be included");
     return((long*)NULL);
   }
diff --git a/cint/cintex/src/CINTTypedefBuilder.cxx b/cint/cintex/src/CINTTypedefBuilder.cxx
index cb03474..8f6ba76 100644
--- a/cint/cintex/src/CINTTypedefBuilder.cxx
+++ b/cint/cintex/src/CINTTypedefBuilder.cxx
@@ -39,6 +39,8 @@ namespace ROOT {
             static std::set<std::string> exclusionList;
             if (!init) {
                exclusionList.insert("stringstream");
+               exclusionList.insert("Double32_t");
+               exclusionList.insert("Float16_t");
                init = true;
             }
             if ( exclusionList.find(nam) != exclusionList.end() ) {
diff --git a/cint/cintex/src/Cintex.cxx b/cint/cintex/src/Cintex.cxx
index 52ea93d..92f59d2 100644
--- a/cint/cintex/src/Cintex.cxx
+++ b/cint/cintex/src/Cintex.cxx
@@ -37,9 +37,11 @@ namespace {
       Cintex_dict_t() {
          //--Reflex class builder
          //NamespaceBuilder( "ROOT::Cintex" );
-         Type t_void = TypeBuilder("void");
-         Type t_int  = TypeBuilder("int");
-         Type t_bool = TypeBuilder("bool");
+         Type t_void = TypeBuilder(Literal("void"));
+         Type t_int  = TypeBuilder(Literal("int"));
+         Type t_bool = TypeBuilder(Literal("bool"));
+         Type t_double = TypeBuilder(Literal("double"));
+         Type t_double32 = TypedefTypeBuilder(Literal("Double32_t"), t_double);
          ClassBuilderT< Cintex >("Cintex", PUBLIC)
             .AddFunctionMember(FunctionTypeBuilder(t_void), "Enable", Enable, 0, 0, PUBLIC | STATIC)
             .AddFunctionMember(FunctionTypeBuilder(t_void, t_int), "SetDebug", SetDebug, 0, 0, PUBLIC | STATIC)
diff --git a/cint/reflex/python/genreflex/genreflex.py b/cint/reflex/python/genreflex/genreflex.py
index 634f4de..10fd567 100644
--- a/cint/reflex/python/genreflex/genreflex.py
+++ b/cint/reflex/python/genreflex/genreflex.py
@@ -124,10 +124,11 @@ class genreflex:
         break
     #----Process options--------------------------------
     try:
-      opts, args = getopt.getopt(options, 'ho:s:c:I:U:D:PC', \
+      opts, args = getopt.getopt(options, 'ho:s:c:I:U:D:PCl:m:', \
       ['help','debug=', 'output=','selection_file=','pool','dataonly','interpreteronly','deep','gccxmlpath=',
        'capabilities=','rootmap=','rootmap-lib=','comments','iocomments','no_membertypedefs',
-       'fail_on_warnings', 'quiet', 'gccxmlopt=', 'reflex', 'split=','no_templatetypedefs','gccxmlpost='])
+       'fail_on_warnings', 'quiet', 'gccxmlopt=', 'reflex', 'split=','no_templatetypedefs','gccxmlpost=',
+       'library='])
     except getopt.GetoptError, e:
       print "--->> genreflex: ERROR:",e
       self.usage(2)
diff --git a/cmake/modules/FindPythia6.cmake b/cmake/modules/FindPythia6.cmake
index 411b704..6a93270 100644
--- a/cmake/modules/FindPythia6.cmake
+++ b/cmake/modules/FindPythia6.cmake
@@ -9,8 +9,8 @@ set(PYTHIA6_FOUND 0)
 
 
 find_library(PYTHIA6_LIBRARY NAMES pythia6 Pythia6 PATHS
-  $ENV{PYTHIA6_DIR}/lib
-  /cern/pro/lib 
+  ${PYTHIA6_DIR}/lib $ENV{PYTHIA6_DIR}/lib
+  /cern/pro/lib
   /opt/pythia 
   /opt/pythia6
   /usr/lib/pythia
diff --git a/cmake/modules/FindROOTInternal.cmake b/cmake/modules/FindROOTInternal.cmake
index 30b7995..b17cb64 100644
--- a/cmake/modules/FindROOTInternal.cmake
+++ b/cmake/modules/FindROOTInternal.cmake
@@ -18,7 +18,7 @@ macro(check_value_ok _value)
   endforeach(_false ${false_allowed})
   if (true_value OR false_value)
     if (true_value AND false_value)
-       MESSAGE(FATAL_ERROR "check_value_ok: Value for option is true and false. This can never happen. If this error message is plotted something is wrong with the logic of the macro.") 
+       MESSAGE(FATAL_ERROR "check_value_ok: Value for option is true and false. This can never happen. If this error message is plotted something is wrong with the logic of the macro.")
     endif(true_value AND false_value)
   else (true_value OR false_value)
     MESSAGE("check_value_ok: This value for options is not known.")
@@ -62,7 +62,7 @@ macro(get_enabled_root_install_options)
 endmacro(get_enabled_root_install_options)
 
 
-macro(CHANGE_ROOT_INSTALL_OPTIONS _option _value) 
+macro(CHANGE_ROOT_INSTALL_OPTIONS _option _value)
   # get position of option from array ROOT_INSTAL_OPTIONS
   list(FIND ROOT_INSTALL_OPTIONS ${_option} position)
   if (position EQUAL -1)
@@ -72,7 +72,7 @@ macro(CHANGE_ROOT_INSTALL_OPTIONS _option _value)
   #check if the value to be set is okay
   check_value_ok(${_value})
 
-  #Now set the value _value for option _option 
+  #Now set the value _value for option _option
   if (true_value)
     list(INSERT ROOT_INSTALL_OPTIONS_VALUE ${position} TRUE)
     math(EXPR rel_pos ${position}+1)
@@ -83,145 +83,147 @@ macro(CHANGE_ROOT_INSTALL_OPTIONS _option _value)
     math(EXPR rel_pos ${position}+1)
     list(REMOVE_AT ROOT_INSTALL_OPTIONS_VALUE ${rel_pos})
   endif (false_value)
-    
+
   #check if after the operation the length of ROOT_INSTALL_OPTIONS and ROOT_INSTALL_OPTIONS_VALUE
   #is still the same
-  list(LENGTH ROOT_INSTALL_OPTIONS_VALUE length_value)  
-  list(LENGTH ROOT_INSTALL_OPTIONS length_options)  
+  list(LENGTH ROOT_INSTALL_OPTIONS_VALUE length_value)
+  list(LENGTH ROOT_INSTALL_OPTIONS length_options)
   if(NOT ${length_value} EQUAL ${length_options})
     MESSAGE(FATAL_ERROR "CHANGE_ROOT_INSTALL_OPTIONS: After changing the option the length of both arrays is different (${length_value} NEQ ${length_options}). Something is wrong with this operation")
   endif(NOT ${length_value} EQUAL ${length_options})
 
-endmacro(CHANGE_ROOT_INSTALL_OPTIONS _option _value) 
+endmacro(CHANGE_ROOT_INSTALL_OPTIONS _option _value)
 
 
 # define all packages to be build. By default all of them are enabled at start.
 # We switch them off later on during the process of configuration.
 
 set (ROOT_INSTALL_OPTIONS
-   afs                 
-   alien               
-   asimage             
-   astiff              
-   builtin_afterimage  
-   builtin_ftgl        
-   builtin_freetype    
-   builtin_pcre        
-   builtin_zlib        
-   castor              
-   chirp               
-   cint7               
-   cintex              
-   clarens             
-   dcache              
-   exceptions          
-   explicitlink        
-   fftw3               
-   gdml                
-   gfal                
-   g4root              
-   glite               
-   globus              
-   gsl_shared          
-   krb5                
-   ldap                
-   genvector           
-   mathmore            
-   memstat             
-   monalisa            
-   mysql               
-   odbc                
-   opengl              
-   oracle              
-   pch                 
-   peac                
-   pgsql               
-   pythia6             
-   pythia8             
-   python              
-   qt                  
-   qtgsi               
-   reflex              
-   roofit              
-   minuit2             
-   ruby                
-   rfio                
-   rpath               
-   sapdb               
-   shadowpw            
-   shared              
-   soversion           
-   srp                 
-   ssl                 
-   table              
-   unuran              
-   winrtdebug          
-   xft                 
-   xml                 
-   xrootd              
+   afs
+   alien
+   asimage
+   astiff
+   builtin_afterimage
+   builtin_ftgl
+   builtin_freetype
+   builtin_pcre
+   builtin_zlib
+   castor
+   chirp
+   cint7
+   cintex
+   clarens
+   dcache
+   exceptions
+   explicitlink
+   fftw3
+   gdml
+   gfal
+   g4root
+   glite
+   globus
+   gsl_shared
+   krb5
+   ldap
+   genvector
+   mathmore
+   memstat
+   monalisa
+   mysql
+   odbc
+   opengl
+   oracle
+   pch
+   peac
+   pgsql
+   pythia6
+   pythia8
+   python
+   qt
+   qtgsi
+   reflex
+   roofit
+   minuit2
+   ruby
+   rfio
+   rpath
+   sapdb
+   shadowpw
+   shared
+   soversion
+   sqlite
+   srp
+   ssl
+   table
+   unuran
+   winrtdebug
+   xft
+   xml
+   xrootd
 )
 
 set (ROOT_INSTALL_OPTIONS_VALUE
-  TRUE                    
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
-  TRUE   
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
+  TRUE
 )
 
 CHANGE_ROOT_INSTALL_OPTIONS("afs" "enable")
@@ -284,7 +286,7 @@ SET(CMAKE_SKIP_BUILD_RPATH  FALSE)
 
 # when building, don't use the install RPATH already
 # (but later on when installing)
-SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 
+SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
 
 # the RPATH to be used when installing
 SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
diff --git a/cmake/modules/FindSqlite.cmake b/cmake/modules/FindSqlite.cmake
new file mode 100644
index 0000000..c4f2e90
--- /dev/null
+++ b/cmake/modules/FindSqlite.cmake
@@ -0,0 +1,50 @@
+# - Try to find Sqlite
+# Once done this will define
+#
+#  SQLITE_FOUND - system has Sqlite
+#  SQLITE_INCLUDE_DIR - the Sqlite include directory
+#  SQLITE_LIBRARIES - Link these to use Sqlite
+#  SQLITE_DEFINITIONS - Compiler switches required for using Sqlite
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+
+# Copyright (c) 2008, Gilles Caulier, <caulier.gilles at gmail.com>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+if ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
+   # in cache already
+   SET(Sqlite_FIND_QUIETLY TRUE)
+endif ( SQLITE_INCLUDE_DIR AND SQLITE_LIBRARIES )
+
+# use pkg-config to get the directories and then use these values
+# in the FIND_PATH() and FIND_LIBRARY() calls
+if( NOT WIN32 )
+  find_package(PkgConfig)
+
+  pkg_check_modules(PC_SQLITE QUIET sqlite3)
+
+  set(SQLITE_DEFINITIONS ${PC_SQLITE_CFLAGS_OTHER})
+endif( NOT WIN32 )
+
+find_path(SQLITE_INCLUDE_DIR NAMES sqlite3.h
+  PATHS
+  ${PC_SQLITE_INCLUDEDIR}
+  ${PC_SQLITE_INCLUDE_DIRS}
+)
+
+find_library(SQLITE_LIBRARIES NAMES sqlite3
+  PATHS
+  ${PC_SQLITE_LIBDIR}
+  ${PC_SQLITE_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Sqlite DEFAULT_MSG SQLITE_INCLUDE_DIR SQLITE_LIBRARIES )
+
+# show the SQLITE_INCLUDE_DIR and SQLITE_LIBRARIES variables only in the advanced view
+mark_as_advanced(SQLITE_INCLUDE_DIR SQLITE_LIBRARIES )
+
diff --git a/cmake/modules/RootBuildOptions.cmake b/cmake/modules/RootBuildOptions.cmake
index 50fdde9..f2bde7a 100644
--- a/cmake/modules/RootBuildOptions.cmake
+++ b/cmake/modules/RootBuildOptions.cmake
@@ -118,6 +118,7 @@ ROOT_BUILD_OPTION(sapdb ON "MaxDB/SapDB support, requires libsqlod and libsqlrte
 ROOT_BUILD_OPTION(shadowpw ON "Shadow password support")
 ROOT_BUILD_OPTION(shared ON "Use shared 3rd party libraries if possible")
 ROOT_BUILD_OPTION(soversion OFF "Set version number in sonames (recommended)")
+ROOT_BUILD_OPTION(sqlite ON "SQLite support, requires libsqlite3")
 ROOT_BUILD_OPTION(srp ON "SRP support, requires SRP source tree")
 ROOT_BUILD_OPTION(ssl ON "SSL encryption support, requires openssl")
 ROOT_BUILD_OPTION(table OFF "Build libTable contrib library")
diff --git a/cmake/modules/RootConfiguration.cmake b/cmake/modules/RootConfiguration.cmake
index 2df879a..bf19640 100644
--- a/cmake/modules/RootConfiguration.cmake
+++ b/cmake/modules/RootConfiguration.cmake
@@ -89,6 +89,11 @@ set(pgsqllibdir ${PGSQL_LIBRARY_DIR})
 set(pgsqllib ${PGSQL_LIBRARY})
 set(pgsqlincdir ${PGSQL_INCLUDE_DIR})
 
+set(buildsqlite ${value${sqlite}})
+set(sqlitelibdir ${SQLITE_LIBRARY_DIR})
+set(sqlitelib ${SQLITE_LIBRARY})
+set(sqliteincdir ${SQLITE_INCLUDE_DIR})
+
 set(buildsapdb ${value${sapdb}})
 set(sapdblibdir ${SAPDB_LIBRARY_DIR})
 set(sapdblib ${SAPDB_LIBRARY})
diff --git a/cmake/modules/RootNewMacros.cmake b/cmake/modules/RootNewMacros.cmake
index 6ce16d7..dad55ad 100644
--- a/cmake/modules/RootNewMacros.cmake
+++ b/cmake/modules/RootNewMacros.cmake
@@ -536,11 +536,13 @@ endfunction()
 #---ROOT_CHECK_OUT_OF_SOURCE_BUILD( )
 #---------------------------------------------------------------------------------------------------
 macro(ROOT_CHECK_OUT_OF_SOURCE_BUILD)
- string(COMPARE EQUAL ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} insource)
-  if(insource)
+  get_filename_component(bindir_parent ${CMAKE_BINARY_DIR} PATH)
+  if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
      file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Testing)
      file(REMOVE ${CMAKE_SOURCE_DIR}/DartConfiguration.tcl)
-     message(FATAL_ERROR "ROOT should be installed as an out of source build, to keep the source directory clean. Please create a extra build directory and run the command 'cmake <path_to_source_dir>' in this newly created directory. You have also to delete the directory CMakeFiles and the file CMakeCache.txt in the source directory. Otherwise cmake will complain even if you run it from an out-of-source directory.") 
+     message(FATAL_ERROR "ROOT should be built as an out of source build, to keep the source directory clean. Please create a extra build directory and run the command 'cmake <path_to_source_dir>' in this newly created directory. You have also to delete the directory CMakeFiles and the file CMakeCache.txt in the source directory. Otherwise cmake will complain even if you run it from an out-of-source directory.")
+  elseif(IS_SYMLINK ${CMAKE_BINARY_DIR} AND CMAKE_SOURCE_DIR STREQUAL bindir_parent)
+     message(FATAL_ERROR "ROOT cannot be built from a sub-directory of the source tree that is a symlink. This is a current limitation of CMake. Please create a real build directory and run the command 'cmake <path_to_source_dir>' in this newly created directory.")
   endif()
 endmacro()
 
diff --git a/cmake/modules/SearchInstalledSoftware.cmake b/cmake/modules/SearchInstalledSoftware.cmake
index 03b94e3..9f49007 100644
--- a/cmake/modules/SearchInstalledSoftware.cmake
+++ b/cmake/modules/SearchInstalledSoftware.cmake
@@ -446,6 +446,20 @@ if(pgsql)
   endif()
 endif()
 
+#---Check for SQLite-------------------------------------------------------------------
+if(sqlite)
+  message(STATUS "Looking for SQLite")
+  find_package(Sqlite)
+  if(NOT SQLITE_FOUND)
+    if(fail-on-missing)
+      message(FATAL_ERROR "SQLite libraries not found and they are required (sqlite option enabled)")
+    else()
+      message(STATUS "SQLite not found. Switching off sqlite option")
+      set(sqlite OFF CACHE BOOL "" FORCE)
+    endif()
+  endif()
+endif()
+
 #---Check for Pythia6-------------------------------------------------------------------
 if(pythia6)
   message(STATUS "Looking for Pythia6")
diff --git a/config/Makefile.depend b/config/Makefile.depend
index e03c7ce..ef3b560 100644
--- a/config/Makefile.depend
+++ b/config/Makefile.depend
@@ -120,6 +120,7 @@ NETXLIBDEPM            = $(NETLIB) $(IOLIB) $(THREADLIB)
 ORACLELIBDEPM          = $(NETLIB) $(IOLIB)
 CASTORLIBDEPM          = $(NETLIB) $(IOLIB)
 PGSQLLIBDEPM           = $(NETLIB) $(IOLIB)
+SQLITELIBDEPM          = $(NETLIB) $(IOLIB)
 MYSQLLIBDEPM           = $(NETLIB) $(IOLIB)
 GDMLLIBDEPM            = $(GEOMLIB) $(XMLLIB) $(HISTLIB) $(IOLIB)
 UNURANLIBDEPM          = $(HISTLIB) $(MATHCORELIB)
@@ -222,6 +223,7 @@ NETXLIBDEP             = $(NETXLIBDEPM)
 ORACLELIBDEP           = $(ORACLELIBDEPM)
 CASTORLIBDEP           = $(CASTORLIBDEPM)
 PGSQLLIBDEP            = $(PGSQLLIBDEPM)
+SQLITELIBDEP           = $(SQLITELIBDEPM)
 MYSQLLIBDEP            = $(MYSQLLIBDEPM)
 GDMLLIBDEP             = $(GDMLLIBDEPM)
 UNURANLIBDEP           = $(UNURANLIBDEPM)
@@ -387,6 +389,7 @@ NETXLIBEXTRA            = lib/libNet.lib lib/libRIO.lib lib/libThread.lib
 ORACLELIBEXTRA          = lib/libNet.lib lib/libRIO.lib
 CASTORLIBEXTRA          = lib/libNet.lib lib/libRIO.lib
 PGSQLLIBEXTRA           = lib/libNet.lib lib/libRIO.lib
+SQLITELIBEXTRA          = lib/libNet.lib lib/libRIO.lib
 MYSQLLIBEXTRA           = lib/libNet.lib lib/libRIO.lib
 GDMLLIBEXTRA            = lib/libGeom.lib lib/libXMLIO.lib lib/libHist.lib \
                           lib/libRIO.lib
@@ -519,6 +522,7 @@ NETXLIBEXTRA            = -Llib -lNet -lRIO -lThread
 ORACLELIBEXTRA          = -Llib -lNet -lRIO
 CASTORLIBEXTRA          = -Llib -lNet -lRIO
 PGSQLLIBEXTRA           = -Llib -lNet -lRIO
+SQLITELIBEXTRA          = -Llib -lNet -lRIO
 MYSQLLIBEXTRA           = -Llib -lNet -lRIO
 GDMLLIBEXTRA            = -Llib -lGeom -lXMLIO -lHist -lRIO
 UNURANLIBEXTRA          = -Llib -lHist -lMathCore
diff --git a/config/Makefile.in b/config/Makefile.in
index 92e012b..61983a1 100644
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -108,6 +108,11 @@ PGSQLLIBDIR    := @pgsqllibdir@
 PGSQLCLILIB    := @pgsqllib@
 PGSQLINCDIR    := $(filter-out /usr/include, @pgsqlincdir@)
 
+BUILDSQLITE     := @buildsqlite@
+SQLITELIBDIR    := @sqlitelibdir@
+SQLITECLILIB    := @sqlitelib@
+SQLITEINCDIR    := $(filter-out /usr/include, @sqliteincdir@)
+
 BUILDSAPDB     := @buildsapdb@
 SAPDBLIBDIR    := @sapdblibdir@
 SAPDBCLILIB    := @sapdblib@
diff --git a/config/html.C.in b/config/html.C.in
index a5706e1..75f53e6 100644
--- a/config/html.C.in
+++ b/config/html.C.in
@@ -22,6 +22,7 @@ Bool_t enable_rfio              = @enable_rfio@;
 Bool_t enable_sapdb             = @enable_sapdb@;
 Bool_t enable_srp               = @enable_srp@;
 Bool_t enable_ssl               = @enable_ssl@;
+Bool_t enable_sqlite            = @enable_sqlite@;
 Bool_t enable_table             = @enable_table@;
 Bool_t enable_thread            = kTRUE;
 Bool_t enable_xml               = @enable_xml@;
@@ -94,6 +95,7 @@ void html()
    if (enable_ruby)              gSystem->Load("libRuby");
    if (enable_rfio)              gSystem->Load("libRFIO");
    if (enable_sapdb)             gSystem->Load("libSapDB");
+   if (enable_sqlite)            gSystem->Load("libSQLite");
    if (enable_srp)               gSystem->Load("libSRPAuth");
    if (enable_table)             gSystem->Load("libTable");
    if (enable_thread)            gSystem->Load("libThread");
diff --git a/config/rootrc.in b/config/rootrc.in
index 73b9248..9581de6 100644
--- a/config/rootrc.in
+++ b/config/rootrc.in
@@ -152,26 +152,27 @@ Hist.Binning.3D.Profx:      100
 Hist.Binning.3D.Profy:      100
 
 # Default statistics parameters names.
-Hist.Stats.Entries:   Entries
-Hist.Stats.Mean:      Mean
-Hist.Stats.MeanX:     Mean x
-Hist.Stats.MeanY:     Mean y
-Hist.Stats.MeanZ:     Mean z
-Hist.Stats.RMS:       RMS
-Hist.Stats.RMSX:      RMS x
-Hist.Stats.RMSY:      RMS y
-Hist.Stats.RMSZ:      RMS z
-Hist.Stats.Underflow: Underflow
-Hist.Stats.Overflow:  Overflow
-Hist.Stats.Integral:  Integral
-Hist.Stats.Skewness:  Skewness
-Hist.Stats.SkewnessX: Skewness x
-Hist.Stats.SkewnessY: Skewness y
-Hist.Stats.SkewnessZ: Skewness z
-Hist.Stats.Kurtosis:  Kurtosis
-Hist.Stats.KurtosisX: Kurtosis x
-Hist.Stats.KurtosisY: Kurtosis y
-Hist.Stats.KurtosisZ: Kurtosis z
+Hist.Stats.Entries:          Entries
+Hist.Stats.Mean:             Mean
+Hist.Stats.MeanX:            Mean x
+Hist.Stats.MeanY:            Mean y
+Hist.Stats.MeanZ:            Mean z
+Hist.Stats.RMS:              RMS
+Hist.Stats.RMSX:             RMS x
+Hist.Stats.RMSY:             RMS y
+Hist.Stats.RMSZ:             RMS z
+Hist.Stats.Underflow:        Underflow
+Hist.Stats.Overflow:         Overflow
+Hist.Stats.Integral:         Integral
+Hist.Stats.IntegralBinWidth: Integral(w)
+Hist.Stats.Skewness:         Skewness
+Hist.Stats.SkewnessX:        Skewness x
+Hist.Stats.SkewnessY:        Skewness y
+Hist.Stats.SkewnessZ:        Skewness z
+Hist.Stats.Kurtosis:         Kurtosis
+Hist.Stats.KurtosisX:        Kurtosis x
+Hist.Stats.KurtosisY:        Kurtosis y
+Hist.Stats.KurtosisZ:        Kurtosis z
 
 # THtml specific settings (for more see doc of THtml class).
 Root.Html.SourceDir:    .
diff --git a/configure b/configure
index 4381f45..cb9d933 100755
--- a/configure
+++ b/configure
@@ -94,6 +94,7 @@ options="                    \
    enable_shadowpw           \
    enable_shared             \
    enable_soversion          \
+   enable_sqlite             \
    enable_srp                \
    enable_ssl                \
    enable_table              \
@@ -191,6 +192,7 @@ OPENGL           \
 MYSQL            \
 ORACLE           \
 PGSQL            \
+SQLITE           \
 QTDIR            \
 SAPDB            \
 RFIO             \
@@ -1541,6 +1543,7 @@ enable/disable options, prefix with either --enable- or --disable-
   shadowpw           Shadow password support
   shared             Use shared 3rd party libraries if possible
   soversion          Set version number in sonames (recommended)
+  sqlite             SQLite support, requires libsqlite3
   srp                SRP support, requires SRP source tree
   ssl                SSL encryption support, requires openssl
   table              Build libTable contrib library
@@ -1639,6 +1642,8 @@ with options, prefix with --with-, enables corresponding support
   sapdb-libdir       SapDB support, location of libsqlod
   rfio-incdir        RFIO support, location of rfio_api.h
   rfio-libdir        RFIO support, location of librfio, libdpm or libshift
+  sqlite-incdir      SQLite support, location of sqlite3.h
+  sqlite-libdir      SQLite support, location of libsqlite3
   srp                Secure Remote Passwd support, location of SRP distribution
   srp-incdir         SRP support, location header of t_server.h
   srp-libdir         SRP support, location header of libsrp.a
@@ -1982,6 +1987,8 @@ if test $# -gt 0 ; then
       --with-sapdb-libdir=*)   sapdblibdir=$optarg   ; enable_sapdb="yes"   ;;
       --with-rfio-incdir=*)    shiftincdir=$optarg   ; enable_rfio="yes"    ;;
       --with-rfio-libdir=*)    shiftlibdir=$optarg   ; enable_rfio="yes"    ;;
+      --with-sqlite-incdir=*)  sqliteincdir=$optarg  ; enable_sqlite="yes"  ;;
+      --with-sqlite-libdir=*)  sqlitelibdir=$optarg  ; enable_sqlite="yes"  ;;
       --with-srp=*)            srpdir=$optarg        ; enable_srp="yes"     ;;
       --with-srp-incdir=*)     srpincdir=$optarg     ; enable_srp="yes"     ;;
       --with-srp-libdir=*)     srplibdir=$optarg     ; enable_srp="yes"     ;;
@@ -3087,6 +3094,44 @@ check_explicit "$enable_pgsql" "$enable_pgsql_explicit" \
 
 ######################################################################
 #
+### echo %%% SQLite Support - Third party libraries
+#
+# (See sqlite.org)
+#
+# If the user has set the flags "--disable-sqlite", we don't check for
+# SQLite at all.
+#
+if test ! "x$enable_sqlite" = "xno"; then
+    # Check for SQLite include and library
+    check_header "sqlite3.h" "$sqliteincdir" \
+        $SQLITE ${SQLITE:+$SQLITE/include} \
+        ${finkdir:+$finkdir/include} \
+        /usr/include /usr/local/include \
+        /usr/include/sqlite /usr/local/include/sqlite /usr/local/sqlite/include \
+        /usr/include/sqlite3 /usr/local/include/sqlite3 /usr/local/sqlite3/include \
+	/usr/sqlite /opt/sqlite /opt/sqlite3/include \
+	/usr/sqlite3 /opt/sqlite3 /opt/sqlite/include
+    sqliteinc=$found_hdr
+    sqliteincdir=$found_dir
+
+    check_library "libsqlite3" "$enable_shared" "$sqlitelibdir" \
+        $SQLITE ${SQLITE:+$SQLITE/lib} \
+        ${finkdir:+$finkdir/lib} \
+        /usr/local/sqlite/lib /usr/local/lib \
+        /usr/lib/sqlite /usr/local/lib/sqlite /usr/sqlite/lib /usr/lib \
+        /usr/sqlite /usr/local/sqlite /opt/sqlite /opt/sqlite/lib
+    sqlitelib=$found_lib
+    sqlitelibdir=$found_dir
+
+    if test "x$sqliteincdir" = "x" || test "x$sqlitelib" = "x"; then
+        enable_sqlite="no"
+    fi
+fi
+check_explicit "$enable_sqlite" "$enable_sqlite_explicit" \
+     "Explicitly required SQLite dependencies not fulfilled"
+
+######################################################################
+#
 ### echo %%% SapDB/MaxDB Support - Third party libraries
 #
 # (See www.sapdb.org or http://www.mysql.com/products/maxdb)
@@ -6203,6 +6248,7 @@ if test "x$show_pkglist" = "xyes" ; then
     test "x$enable_oracle"   = "xyes" && pl="$pl root-plugin-sql-oracle"
     test "x$enable_pgsql"    = "xyes" && pl="$pl root-plugin-sql-pgsql"
     test "x$enable_sapdb"    = "xyes" && pl="$pl root-plugin-sql-maxdb"
+    test "x$enable_sqlite"   = "xyes" && pl="$pl root-plugin-sql-sqlite"
     test "x$enable_xrootd"   = "xyes" && pl="$pl root-system-xrootd root-plugin-net-netx root-plugin-net-xrootd"
 
     pl="$pl \
@@ -6711,6 +6757,9 @@ sed -e "s|@globusincdir@|$globusincdir|"        \
     -e "s|@pgsqlincdir@|$pgsqlincdir|"          \
     -e "s|@pgsqllib@|$pgsqllib|"                \
     -e "s|@pgsqllibdir@|$pgsqllibdir|"          \
+    -e "s|@sqliteincdir@|$sqliteincdir|"        \
+    -e "s|@sqlitelib@|$sqlitelib|"              \
+    -e "s|@sqlitelibdir@|$sqlitelibdir|"        \
     -e "s|@pythia6lib@|$pythia6lib|"            \
     -e "s|@pythia6libdir@|$pythia6libdir|"      \
     -e "s|@pythia6cppflags@|$pythia6cppflags|"  \
@@ -6785,6 +6834,7 @@ sed -e "s|@srcdir@|$ac_srcdir|"                 \
     -e "s|@buildldap@|$enable_ldap|"            \
     -e "s|@buildmysql@|$enable_mysql|"          \
     -e "s|@buildpgsql@|$enable_pgsql|"          \
+    -e "s|@buildsqlite@|$enable_sqlite|"        \
     -e "s|@buildodbc@|$enable_odbc|"            \
     -e "s|@buildoracle@|$enable_oracle|"        \
     -e "s|@buildsapdb@|$enable_sapdb|"          \
diff --git a/core/base/inc/MessageTypes.h b/core/base/inc/MessageTypes.h
index 5f850b9..5068c28 100644
--- a/core/base/inc/MessageTypes.h
+++ b/core/base/inc/MessageTypes.h
@@ -64,7 +64,7 @@ enum EMessageTypes {
    kPROOF_HOSTAUTH       = 1023,         //HostAuth info follows
    kPROOF_GETSLAVEINFO   = 1024,         //get worker info from master
    kPROOF_GETTREEHEADER  = 1025,         //get tree object
-   kPROOF_GETOUTPUTLIST  = 1026,         //get the output list
+   kPROOF_GETOUTPUTLIST  = 1026,         //get the output list names
    kPROOF_GETSTATS       = 1027,         //get statistics of workers
    kPROOF_GETPARALLEL    = 1028,         //get number of parallel workers
    kPROOF_VALIDATE_DSET  = 1029,         //validate a TDSet
@@ -95,6 +95,8 @@ enum EMessageTypes {
    kPROOF_FORK           = 1054,         //ask the worker to clone itself
    kPROOF_GOASYNC        = 1055,         //switch to asynchronous mode
    kPROOF_SUBMERGER      = 1056,         //sub-merger based approach in finalization
+   kPROOF_ECHO           = 1057,         //object echo request from client
+   kPROOF_SENDOUTPUT     = 1058,         //control output sending
 
    //---- ROOTD message opcodes (2000 - 2099)
    kROOTD_USER           = 2000,         //user id follows
diff --git a/core/base/inc/RVersion.h b/core/base/inc/RVersion.h
index 1f259de..82cc4d2 100644
--- a/core/base/inc/RVersion.h
+++ b/core/base/inc/RVersion.h
@@ -14,13 +14,13 @@
  *
 */
 
-#define ROOT_RELEASE "5.34/09"
-#define ROOT_RELEASE_DATE "Jun 26 2013"
-#define ROOT_RELEASE_TIME "16:38:19"
+#define ROOT_RELEASE "5.34/10"
+#define ROOT_RELEASE_DATE "Aug 29 2013"
+#define ROOT_RELEASE_TIME "16:17:59"
 #define ROOT_SVN_REVISION 49361
-#define ROOT_GIT_COMMIT "v5-34-08-80-g1323c6f"
+#define ROOT_GIT_COMMIT "v5-34-09-278-gdd55a0f"
 #define ROOT_GIT_BRANCH "heads/v5-34-00-patches"
-#define ROOT_VERSION_CODE 336393
+#define ROOT_VERSION_CODE 336394
 #define ROOT_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 
 #endif
diff --git a/core/base/inc/TAttFill.h b/core/base/inc/TAttFill.h
index 6c67b1b..4af45e6 100644
--- a/core/base/inc/TAttFill.h
+++ b/core/base/inc/TAttFill.h
@@ -56,5 +56,14 @@ public:
 inline Bool_t TAttFill::IsTransparent() const
 { return fFillStyle >= 4000 && fFillStyle <= 4100 ? kTRUE : kFALSE; }
 
-#endif
+   enum EFillStyle {kFDotted1  = 3001, kFDotted2    = 3002, kFDotted3  = 3003,
+                    kFHatched1 = 3004, kHatched2    = 3005, kFHatched3 = 3006,
+                    kFHatched4 = 3007, kFWicker     = 3008, kFScales   = 3009,
+                    kFBricks   = 3010, kFSnowflakes = 3011, kFCircles  = 3012,
+                    kFTiles    = 3013, kFMondrian   = 3014, kFDiamonds = 3015,
+                    kFWaves1   = 3016, kFDashed1    = 3017, kFDashed2  = 3018,
+                    kFAlhambra = 3019, kFWaves2     = 3020, kFStars1   = 3021,
+                    kFStars2   = 3022, kFPyramids   = 3023, kFFrieze   = 3024,
+                    kFMetopes  = 3025, kFEmpty      = 0   , kFSolid    = 1};
 
+#endif
diff --git a/core/base/inc/TAttText.h b/core/base/inc/TAttText.h
index 7103b1c..f2223d1 100644
--- a/core/base/inc/TAttText.h
+++ b/core/base/inc/TAttText.h
@@ -62,5 +62,8 @@ public:
    ClassDef(TAttText,1)  //Text attributes
 };
 
+   enum ETextAlign {kHAlignLeft=10, kHAlignCenter=20, kHAlignRight=30,
+                    kVAlignBottom=1, kVAlignCenter=2, kVAlignTop=3};
+
 #endif
 
diff --git a/core/base/inc/TStyle.h b/core/base/inc/TStyle.h
index 5214d7d..98e8d22 100644
--- a/core/base/inc/TStyle.h
+++ b/core/base/inc/TStyle.h
@@ -1,4 +1,4 @@
-// @(#)root/base:$Id$
+// @(#)root/base:$Id: 5214d7dc2746ceb518366bc6c4f4068b652d5241 $
 // Author: Rene Brun   12/12/94
 
 /*************************************************************************
@@ -370,8 +370,8 @@ public:
    void             SetPaintTextFormat(const char *format="g") {fPaintTextFormat = format;}
    void             SetPaperSize(EPaperSize size);
    void             SetPaperSize(Float_t xsize=20, Float_t ysize=26);
-   void             SetStatColor(Int_t color=19) {fStatColor=color;}
-   void             SetStatTextColor(Int_t color=1) {fStatTextColor=color;}
+   void             SetStatColor(Color_t color=19) {fStatColor=color;}
+   void             SetStatTextColor(Color_t color=1) {fStatTextColor=color;}
    void             SetStatStyle(Style_t style=1001) {fStatStyle=style;}
    void             SetStatBorderSize(Width_t size=2) {fStatBorderSize=size;}
    void             SetStatFont(Style_t font=62) {fStatFont=font;}
diff --git a/core/base/inc/TVirtualPS.h b/core/base/inc/TVirtualPS.h
index 3f58c17..a635cf8 100644
--- a/core/base/inc/TVirtualPS.h
+++ b/core/base/inc/TVirtualPS.h
@@ -76,7 +76,7 @@ public:
    virtual void  PrintFast(Int_t nch, const char *string="");
    virtual void  PrintStr(const char *string="");
    virtual void  WriteInteger(Int_t i, Bool_t space=kTRUE);
-   virtual void  WriteReal(Float_t r);
+   virtual void  WriteReal(Float_t r, Bool_t space=kTRUE);
    virtual void  PrintRaw(Int_t len, const char *str);
    virtual void *GetStream() const {  return (void*)fStream; }
    virtual void  SetStream(std::ofstream *os) {  fStream = os; }
diff --git a/core/base/src/TAttText.cxx b/core/base/src/TAttText.cxx
index 154b0a2..f000fc8 100644
--- a/core/base/src/TAttText.cxx
+++ b/core/base/src/TAttText.cxx
@@ -85,6 +85,16 @@ Begin_Macro(source)
 textangle.C
 End_Macro
 
+Mnemonic constants are available:
+<pre>
+kHAlignLeft   = 10, kHAlignCenter = 20, kHAlignRight = 30,
+kVAlignBottom = 1,  kVAlignCenter = 2,  kVAlignTop   = 3
+</pre>
+They allow to write:
+<pre>
+object->SetTextAlign(kHAlignLeft+kVAlignTop);
+</pre>
+
 Begin_Html
 <a name="T3"></a><h3>Text Color</h3>
 The text color is a color index (integer) pointing in the ROOT
diff --git a/core/base/src/TContextMenu.cxx b/core/base/src/TContextMenu.cxx
index 1645083..bbc7992 100644
--- a/core/base/src/TContextMenu.cxx
+++ b/core/base/src/TContextMenu.cxx
@@ -159,7 +159,7 @@ void TContextMenu::Action(TClassMenuItem *menuitem)
 #else
                // It is a workaround of the "Dead lock under Windows
                char *cmd = Form("((TContextMenu *)0x%lx)->Execute((TObject *)0x%lx,"
-                                "(TMethod *)0x%lx,(TObjArray *)0);",
+                                "(TMethod *)0x%lx,\"\");",
                                 (Long_t)this,(Long_t)object,(Long_t)method);
                //Printf("%s", cmd);
                gROOT->ProcessLine(cmd);
@@ -171,8 +171,9 @@ void TContextMenu::Action(TClassMenuItem *menuitem)
 #else
                // It is a workaround of the "Dead lock under Windows
                char *cmd = Form("((TContextMenu *)0x%lx)->Execute((TObject *)0x%lx,"
-                                "(TMethod *)0x%lx,(TObjArray *)0);",
-                                (Long_t)this,(Long_t)object,(Long_t)method);
+                                "(TMethod *)0x%lx,(TObject*)0x%lx);",
+                                (Long_t)this,(Long_t)object,(Long_t)method,
+                                (Long_t)fSelectedObject);
                //Printf("%s", cmd);
                gROOT->ProcessLine(cmd);
                //Execute( object, method, (TObjArray *)NULL );
diff --git a/core/base/src/TFileCollection.cxx b/core/base/src/TFileCollection.cxx
index da3fc7e..bdea16a 100644
--- a/core/base/src/TFileCollection.cxx
+++ b/core/base/src/TFileCollection.cxx
@@ -478,13 +478,14 @@ void TFileCollection::PrintDetailed(TString &showOnly) const
 
          // First line: current URL with all information
          info->ResetUrl();
+         TUrl *curUrl = info->GetCurrentUrl();
+         const char *curUrlStr = curUrl ? curUrl->GetUrl() : "n.a.";
          Printf("\033[1m%4u.\033[m %c%c | %-7s | %6.1lf %s | %s",
            ++countMatch,
            (s ? 'S' : 's'), (c ? 'C' : 'c'),
            ((entries > 0) ? Form("% 7d", entries) : "n.a."),
-           sz, um.Data(),
-           info->GetCurrentUrl()->GetUrl());
-           info->NextUrl();
+           sz, um.Data(), curUrlStr);
+         info->NextUrl();
 
          // Every other URL shown below current one
          while ((url = info->NextUrl())) {
diff --git a/core/base/src/TStorage.cxx b/core/base/src/TStorage.cxx
index fface3a..4ea50e5 100644
--- a/core/base/src/TStorage.cxx
+++ b/core/base/src/TStorage.cxx
@@ -177,11 +177,15 @@ void TStorage::Dealloc(void *ptr)
 //______________________________________________________________________________
 void *TStorage::ReAlloc(void *ovp, size_t size)
 {
-   // Reallocate (i.e. resize) block of memory.
+   // Reallocate (i.e. resize) block of memory. Don't use if size is larger
+   // than old size, use ReAlloc(void *, size_t, size_t) instead.
 
    // Needs to be protected by global mutex
    R__LOCKGUARD(gGlobalMutex);
 
+   ::Obsolete("ReAlloc(void*,size_t)", "v5-34-00", "v6-02-00");
+   ::Info("ReAlloc(void*,size_t)", "please use ReAlloc(void*,size_t,size_t)");
+
    if (fgReAllocHook && fgHasCustomNewDelete && !TROOT::MemCheck())
       return (*fgReAllocHook)(ovp, size);
 
diff --git a/core/base/src/TStyle.cxx b/core/base/src/TStyle.cxx
index f79bbac..55d1e7c 100644
--- a/core/base/src/TStyle.cxx
+++ b/core/base/src/TStyle.cxx
@@ -1263,6 +1263,7 @@ void TStyle::SetOptStat(Int_t mode)
    //    s = 1;  skewness printed
    //    s = 2;  skewness and skewness error printed
    //    i = 1;  integral of bins printed
+   //    i = 2;  integral of bins with option "width" printed
    //    o = 1;  number of overflows printed
    //    u = 1;  number of underflows printed
    //    r = 1;  rms printed
@@ -1305,6 +1306,7 @@ void TStyle::SetOptStat(Option_t *stat)
    //    s :  skewness printed
    //    S :  skewness and skewness error printed
    //    i :  integral of bins printed
+   //    I :  integral of bins with option "width" printed
    //    o :  number of overflows printed
    //    u :  number of underflows printed
    //    r :  rms printed
@@ -1331,6 +1333,7 @@ void TStyle::SetOptStat(Option_t *stat)
    if (opt.Contains("u")) mode+=10000;
    if (opt.Contains("o")) mode+=100000;
    if (opt.Contains("i")) mode+=1000000;
+   if (opt.Contains("I")) mode+=2000000;
    if (opt.Contains("s")) mode+=10000000;
    if (opt.Contains("S")) mode+=20000000;
    if (opt.Contains("k")) mode+=100000000;
diff --git a/core/base/src/TTimer.cxx b/core/base/src/TTimer.cxx
index 0264d66..e878a35 100644
--- a/core/base/src/TTimer.cxx
+++ b/core/base/src/TTimer.cxx
@@ -138,7 +138,8 @@ Bool_t TTimer::CheckTimer(const TTime &now)
 Bool_t TTimer::Notify()
 {
    // Notify when timer times out. The timer is always reset. To stop
-   // the timer call TurnOff().
+   // the timer call TurnOff(). Make sure to call Reset() also in derived
+   // Notify() so timers will keep working repeatedly.
 
    Timeout();       // emit Timeout() signal
    if (fObject) fObject->HandleTimer(this);
diff --git a/core/base/src/TVirtualPS.cxx b/core/base/src/TVirtualPS.cxx
index 3211a6f..46d0b60 100644
--- a/core/base/src/TVirtualPS.cxx
+++ b/core/base/src/TVirtualPS.cxx
@@ -180,12 +180,16 @@ void TVirtualPS::WriteInteger(Int_t n, Bool_t space )
 
 
 //______________________________________________________________________________
-void TVirtualPS::WriteReal(Float_t z)
+void TVirtualPS::WriteReal(Float_t z, Bool_t space)
 {
    // Write a Real number to the file
 
    char str[15];
-   snprintf(str,15," %g", z);
+   if (space) {
+      snprintf(str,15," %g", z);
+   } else {
+      snprintf(str,15,"%g", z);
+   }
    PrintStr(str);
 }
 
diff --git a/core/cont/inc/TBits.h b/core/cont/inc/TBits.h
index cae92b2..26db69a 100644
--- a/core/cont/inc/TBits.h
+++ b/core/cont/inc/TBits.h
@@ -136,6 +136,8 @@ public:
    UInt_t  CountBits(UInt_t startBit=0)     const ;  // return number of bits set to 1
    UInt_t  FirstNullBit(UInt_t startBit=0)  const;
    UInt_t  FirstSetBit(UInt_t startBit=0)   const;
+   UInt_t  LastNullBit(UInt_t startBit=999999999) const;
+   UInt_t  LastSetBit(UInt_t startBit=999999999)  const;
    UInt_t  GetNbits()      const { return fNbits; }
    UInt_t  GetNbytes()     const { return fNbytes; }
 
diff --git a/core/cont/src/TBits.cxx b/core/cont/src/TBits.cxx
index 63b9b2f..50cb66f 100644
--- a/core/cont/src/TBits.cxx
+++ b/core/cont/src/TBits.cxx
@@ -303,6 +303,45 @@ UInt_t TBits::FirstNullBit(UInt_t startBit) const
 }
 
 //______________________________________________________________________________
+UInt_t TBits::LastNullBit(UInt_t startBit) const
+{
+   // Return position of first null bit (starting from position 0 and up)
+
+   static const Int_t fbits[256] = {
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+             5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+             4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+             3,3,3,3,3,3,3,3,2,2,2,2,1,1,0,8};
+
+   UInt_t i;
+   if (startBit>=fNbits) startBit = fNbits-1;
+   UInt_t startByte = startBit/8;
+   UInt_t ibit = startBit%8;
+   if (ibit<7) {
+      for (i=ibit+1;i>0;i--) {
+         if ((fAllBits[startByte] & (1<<(i-1))) == 0) return 8*startByte+i-1;
+      }
+      startByte--;
+   }
+   for(i=startByte+1; i>0; i--) {
+      if (fAllBits[i-1] != 255) return 8*(i-1) + fbits[fAllBits[i-1]];
+   }
+   return fNbits;
+}
+
+//______________________________________________________________________________
 UInt_t TBits::FirstSetBit(UInt_t startBit) const
 {
    // Return position of first non null bit (starting from position 0 and up)
@@ -348,6 +387,45 @@ UInt_t TBits::FirstSetBit(UInt_t startBit) const
 }
 
 //______________________________________________________________________________
+UInt_t TBits::LastSetBit(UInt_t startBit) const
+{
+   // Return position of first non null bit (starting from position 0 and up)
+
+   static const Int_t fbits[256] = {
+             8,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+             4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+             5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+             5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
+
+   UInt_t i;
+   if (startBit>=fNbits) startBit = fNbits-1;
+   UInt_t startByte = startBit/8;
+   UInt_t ibit = startBit%8;
+   if (ibit<7) {
+      for (i=ibit+1;i>0;i--) {
+         if ((fAllBits[startByte] & (1<<(i-1))) != 0) return 8*startByte+i-1;
+      }
+      startByte--;
+   }
+   for(i=startByte+1; i>0; i--) {
+      if (fAllBits[i-1] != 0) return 8*(i-1) + fbits[fAllBits[i-1]];
+   }
+   return fNbits;
+}
+
+//______________________________________________________________________________
 void TBits::Output(ostream &os) const
 {
    // Print the value to the ostream
diff --git a/core/macosx/inc/CocoaUtils.h b/core/macosx/inc/CocoaUtils.h
index 72a1d91..632e179 100644
--- a/core/macosx/inc/CocoaUtils.h
+++ b/core/macosx/inc/CocoaUtils.h
@@ -157,9 +157,13 @@ private:
 
 class AutoreleasePool {
 public:
-   AutoreleasePool();
+   AutoreleasePool(bool delayCreation = false);
    ~AutoreleasePool();
    
+   //Drains the previous pool (if any)
+   //and activates a new one.
+   void Reset();
+   
 private:
    NSAutoreleasePool *fPool;
 
diff --git a/core/macosx/inc/TMacOSXSystem.h b/core/macosx/inc/TMacOSXSystem.h
index b801e4b..dbdb7da 100644
--- a/core/macosx/inc/TMacOSXSystem.h
+++ b/core/macosx/inc/TMacOSXSystem.h
@@ -39,13 +39,16 @@ class MacOSXSystem;
 }
 
 class TMacOSXSystem : public TUnixSystem {
+   friend class TGCocoa;
 public:
    TMacOSXSystem();
    ~TMacOSXSystem();
    
    void DispatchOneEvent(Bool_t pendingOnly);
+   bool CocoaInitialized() const;
 
 private:
+   void InitializeCocoa();
 
    bool ProcessPendingEvents();
    void WaitEvents(Long_t nextto);
@@ -56,6 +59,7 @@ private:
    void ProcessApplicationDefinedEvent(void *event);
 
    std::auto_ptr<ROOT::MacOSX::Detail::MacOSXSystem> fPimpl; //!
+   bool fCocoaInitialized;//!
 
    TMacOSXSystem(const TMacOSXSystem &rhs);
    TMacOSXSystem &operator = (const TMacOSXSystem &rhs);
diff --git a/core/macosx/src/CocoaUtils.mm b/core/macosx/src/CocoaUtils.mm
index 8496d59..92b6843 100644
--- a/core/macosx/src/CocoaUtils.mm
+++ b/core/macosx/src/CocoaUtils.mm
@@ -16,8 +16,8 @@ namespace MacOSX {
 namespace Util {
 
 //______________________________________________________________________________
-AutoreleasePool::AutoreleasePool()
-                  : fPool([[NSAutoreleasePool alloc] init])
+AutoreleasePool::AutoreleasePool(bool delayCreation /* = false*/)
+                  : fPool(delayCreation ? nil : [[NSAutoreleasePool alloc] init])
 {
 }
 
@@ -27,6 +27,15 @@ AutoreleasePool::~AutoreleasePool()
    [fPool release];
 }
 
+//______________________________________________________________________________
+void AutoreleasePool::Reset()
+{
+   if (fPool)
+      [fPool release];
+
+   fPool = [[NSAutoreleasePool alloc] init];
+}
+
 }//Util
 }//MacOSX
 }//ROOT
diff --git a/core/macosx/src/TMacOSXSystem.mm b/core/macosx/src/TMacOSXSystem.mm
index db3cb2b..774f555 100644
--- a/core/macosx/src/TMacOSXSystem.mm
+++ b/core/macosx/src/TMacOSXSystem.mm
@@ -16,7 +16,7 @@
 #include <map>
 #include <set>
 
-#import <Cocoa/Cocoa.h>
+#include <Cocoa/Cocoa.h>
 
 #include "TSeqCollection.h"
 #include "TMacOSXSystem.h"
@@ -107,20 +107,12 @@ namespace ROOT {
 namespace MacOSX {
 namespace Detail {
 
-class NSAppInitializer
-{
-public:
-   NSAppInitializer()
-   {
-      [NSApplication sharedApplication];
-   }
-};
-
 class MacOSXSystem {
 public:
    MacOSXSystem();
    ~MacOSXSystem();
 
+   void InitializeCocoa();
 
    void AddFileHandler(TFileHandler *fh);
    void RemoveFileHandler(TFileHandler *fh);
@@ -146,9 +138,9 @@ public:
    void SetFileDescriptors(const fd_map_type &fdTable, DescriptorType fdType);
 
    std::set<CFFileDescriptorRef> fCFFileDescriptors;
-   
-   NSAppInitializer fAppStarter;
-   const ROOT::MacOSX::Util::AutoreleasePool fPool;
+
+   ROOT::MacOSX::Util::AutoreleasePool fPool;
+   bool fCocoaInitialized;
 
    static MacOSXSystem *fgInstance;
 };
@@ -197,16 +189,28 @@ void TMacOSXSystem_WriteCallback(CFFileDescriptorRef fdref, CFOptionFlags /*call
 
 //______________________________________________________________________________
 MacOSXSystem::MacOSXSystem()
+                : fPool(true), //Delay the pool creation!
+                  fCocoaInitialized(false)
 {
    assert(fgInstance == 0 && "MacOSXSystem, fgInstance was initialized already");
-
    fgInstance = this;
 }
 
 //______________________________________________________________________________
 MacOSXSystem::~MacOSXSystem()
 {
-   CloseFileDescriptors();
+   if (fCocoaInitialized)
+      CloseFileDescriptors();
+}
+
+//______________________________________________________________________________
+void MacOSXSystem::InitializeCocoa()
+{
+   assert(fCocoaInitialized == false && "InitializeCocoa, Cocoa was initialized already");
+   
+   [NSApplication sharedApplication];
+   fPool.Reset();//TODO: test, should it be BEFORE shared application???
+   fCocoaInitialized = true;
 }
 
 //______________________________________________________________________________
@@ -276,6 +280,9 @@ void MacOSXSystem::UnregisterFileDescriptor(CFFileDescriptorRef fd)
 //______________________________________________________________________________
 void MacOSXSystem::CloseFileDescriptors()
 {
+   //While Core Foundation is not Cocoa, it still should not be used if we are not initializing Cocoa.
+   assert(fCocoaInitialized == true && "CloseFileDescriptors, Cocoa was not initialized");
+
    for (std::set<CFFileDescriptorRef>::iterator fdIter = fCFFileDescriptors.begin(), end = fCFFileDescriptors.end(); fdIter != end; ++fdIter) {
       CFFileDescriptorInvalidate(*fdIter);
       CFRelease(*fdIter);
@@ -304,6 +311,9 @@ void MacOSXSystem::RemoveFileDescriptor(fd_map_type &fdTable, int fd)
 //______________________________________________________________________________
 void MacOSXSystem::SetFileDescriptors(const fd_map_type &fdTable, DescriptorType fdType)
 {
+   //While CoreFoundation is not Cocoa, it still should not be used if we are not initializing Cocoa.
+   assert(fCocoaInitialized == true && "SetFileDescriptors, Cocoa was not initialized");
+
    for (const_fd_map_iterator fdIter = fdTable.begin(), end = fdTable.end(); fdIter != end; ++fdIter) {
       const bool read = fdType == kDTRead;
       CFFileDescriptorRef fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fdIter->first, false, read ? TMacOSXSystem_ReadCallback : TMacOSXSystem_WriteCallback, 0);
@@ -337,23 +347,10 @@ ClassImp(TMacOSXSystem)
 
 //______________________________________________________________________________
 TMacOSXSystem::TMacOSXSystem()
-                  : fPimpl(new Private::MacOSXSystem)
+                  : fPimpl(new Private::MacOSXSystem),
+                    fCocoaInitialized(false)
 {
-   //
-
-   const ROOT::MacOSX::Util::AutoreleasePool pool;
-
-   [NSApplication sharedApplication];
-   //Documentation says, that +sharedApplication, initializes the app. But this is not true,
-   //it's still not really initialized, part of initialization is done by -run method.
-
-   //If you call run, it never returns unless app is finished. I have to stop Cocoa's event loop
-   //processing, since we have our own event loop.
-  
-   const ROOT::MacOSX::Util::NSScopeGuard<RunStopper> stopper([[RunStopper alloc] init]);
-
-   [stopper.Get() performSelector : @selector(stopRun) withObject : nil afterDelay : 0.05];//Delay? What it should be?
-   [NSApp run];
+   InitializeCocoa();
 }
 
 //______________________________________________________________________________
@@ -362,93 +359,14 @@ TMacOSXSystem::~TMacOSXSystem()
 }
 
 //______________________________________________________________________________
-void TMacOSXSystem::ProcessApplicationDefinedEvent(void *e)
-{
-   //Right now I have app. defined events only
-   //for file descriptors. This can change in a future.
-   NSEvent *event = (NSEvent *)e;
-
-   assert(event != nil && "ProcessApplicationDefinedEvent, event parameter is nil");
-   assert(event.type == NSApplicationDefined && "ProcessApplicationDefinedEvent, event parameter has wrong type");
-   
-   Private::MacOSXSystem::fd_map_iterator fdIter = fPimpl->fReadFds.find(event.data1);
-   bool descriptorFound = false;
-
-   if (fdIter != fPimpl->fReadFds.end()) {
-      fReadready->Set(event.data1);
-      descriptorFound = true;
-   }
-   
-   fdIter = fPimpl->fWriteFds.find(event.data1);
-   if (fdIter != fPimpl->fWriteFds.end()) {
-      fWriteready->Set(event.data1);
-      descriptorFound = true;
-   }
-   
-   if (!descriptorFound) {
-      Error("ProcessApplicationDefinedEvent", "file descriptor %d was not found", int(event.data1));
-      return;
-   }
-   
-   ++fNfd;
-}
-
-//______________________________________________________________________________
-void TMacOSXSystem::WaitEvents(Long_t nextto)
-{
-   //Wait for GUI/Non-GUI events.
-
-   if (!fPimpl->SetFileDescriptors()) {
-      //I consider this error as fatal.
-      Fatal("WaitForAllEvents", "SetFileDesciptors failed");
-   }
-
-   NSDate *untilDate = nil;
-   if (nextto >= 0)//0 also means non-blocking call.
-      untilDate = [NSDate dateWithTimeIntervalSinceNow : nextto / 1000.];
-   else
-      untilDate = [NSDate distantFuture];
-
-   fReadready->Zero();
-   fWriteready->Zero();
-   fNfd = 0;
-
-   NSEvent *event = [NSApp nextEventMatchingMask : NSAnyEventMask untilDate : untilDate inMode : NSDefaultRunLoopMode dequeue : YES];
-
-   if (event.type == NSApplicationDefined)
-      ProcessApplicationDefinedEvent(event);
-   else
-      [NSApp sendEvent : event];
-
-   while ((event = [NSApp nextEventMatchingMask : NSAnyEventMask untilDate : nil inMode : NSDefaultRunLoopMode dequeue : YES])) {
-      if (event.type == NSApplicationDefined)
-         ProcessApplicationDefinedEvent(event);
-      else
-         [NSApp sendEvent : event];
-   }
-
-   fPimpl->CloseFileDescriptors();
-
-   gVirtualX->Update(2);
-   gVirtualX->Update(3);
-}
-
-//______________________________________________________________________________
-bool TMacOSXSystem::ProcessPendingEvents()
-{
-   bool processed = false;
-   while (NSEvent *event = [NSApp nextEventMatchingMask : NSAnyEventMask untilDate : nil inMode : NSDefaultRunLoopMode dequeue : YES]) {
-      [NSApp sendEvent : event];
-      processed = true;
-   }
-   return processed;
-}
-
-//______________________________________________________________________________
 void TMacOSXSystem::DispatchOneEvent(Bool_t pendingOnly)
 {
    //Here I try to emulate TUnixSystem's behavior, which is quite twisted.
-   //I'm not even sure, I need all this code :)   
+   //I'm not even sure, I need all this code :)
+   
+   if (!fCocoaInitialized)//We are in a batch mode (or 'batch').
+      return TUnixSystem::DispatchOneEvent(pendingOnly);
+   
    Bool_t pollOnce = pendingOnly;
 
    while (true) {
@@ -523,6 +441,94 @@ void TMacOSXSystem::DispatchOneEvent(Bool_t pendingOnly)
 }
 
 //______________________________________________________________________________
+bool TMacOSXSystem::CocoaInitialized() const
+{
+   return fCocoaInitialized;
+}
+
+//______________________________________________________________________________
+void TMacOSXSystem::InitializeCocoa()
+{
+   if (fCocoaInitialized)
+      return;
+   
+   //TODO: add error handling and results check.
+   
+   fPimpl->InitializeCocoa();
+   
+   const ROOT::MacOSX::Util::AutoreleasePool pool;
+
+   //[NSApplication sharedApplication];//TODO: clean-up this mess with pools and sharedApplication
+   //Documentation says, that +sharedApplication, initializes the app. But this is not true,
+   //it's still not really initialized, part of initialization is done by -run method.
+
+   //If you call run, it never returns unless app is finished. I have to stop Cocoa's event loop
+   //processing, since we have our own event loop.
+  
+   const ROOT::MacOSX::Util::NSScopeGuard<RunStopper> stopper([[RunStopper alloc] init]);
+
+   [stopper.Get() performSelector : @selector(stopRun) withObject : nil afterDelay : 0.05];//Delay? What it should be?
+   [NSApp run];
+   
+   fCocoaInitialized = true;
+}
+
+//______________________________________________________________________________
+bool TMacOSXSystem::ProcessPendingEvents()
+{
+   assert(fCocoaInitialized == true && "ProcessPendingEvents, called while Cocoa was not initialized");
+
+   bool processed = false;
+   while (NSEvent *event = [NSApp nextEventMatchingMask : NSAnyEventMask untilDate : nil inMode : NSDefaultRunLoopMode dequeue : YES]) {
+      [NSApp sendEvent : event];
+      processed = true;
+   }
+   return processed;
+}
+
+//______________________________________________________________________________
+void TMacOSXSystem::WaitEvents(Long_t nextto)
+{
+   //Wait for GUI/Non-GUI events.
+   
+   assert(fCocoaInitialized == true && "WaitEvents, called while Cocoa was not initialized");
+
+   if (!fPimpl->SetFileDescriptors()) {
+      //I consider this error as fatal.
+      Fatal("WaitForAllEvents", "SetFileDesciptors failed");
+   }
+
+   NSDate *untilDate = nil;
+   if (nextto >= 0)//0 also means non-blocking call.
+      untilDate = [NSDate dateWithTimeIntervalSinceNow : nextto / 1000.];
+   else
+      untilDate = [NSDate distantFuture];
+
+   fReadready->Zero();
+   fWriteready->Zero();
+   fNfd = 0;
+
+   NSEvent *event = [NSApp nextEventMatchingMask : NSAnyEventMask untilDate : untilDate inMode : NSDefaultRunLoopMode dequeue : YES];
+
+   if (event.type == NSApplicationDefined)
+      ProcessApplicationDefinedEvent(event);
+   else
+      [NSApp sendEvent : event];
+
+   while ((event = [NSApp nextEventMatchingMask : NSAnyEventMask untilDate : nil inMode : NSDefaultRunLoopMode dequeue : YES])) {
+      if (event.type == NSApplicationDefined)
+         ProcessApplicationDefinedEvent(event);
+      else
+         [NSApp sendEvent : event];
+   }
+
+   fPimpl->CloseFileDescriptors();
+
+   gVirtualX->Update(2);
+   gVirtualX->Update(3);
+}
+
+//______________________________________________________________________________
 void TMacOSXSystem::AddFileHandler(TFileHandler *fh)
 {
    fPimpl->AddFileHandler(fh);
@@ -535,3 +541,38 @@ TFileHandler *TMacOSXSystem::RemoveFileHandler(TFileHandler *fh)
    fPimpl->RemoveFileHandler(fh);
    return TUnixSystem::RemoveFileHandler(fh);
 }
+
+//______________________________________________________________________________
+void TMacOSXSystem::ProcessApplicationDefinedEvent(void *e)
+{
+   //Right now I have app. defined events only
+   //for file descriptors. This can change in a future.
+   
+   assert(fCocoaInitialized == true && "ProcessApplicationDefinedEvent, called while Cocoa was not initialized");
+   
+   NSEvent *event = (NSEvent *)e;
+   assert(event != nil && "ProcessApplicationDefinedEvent, event parameter is nil");
+   assert(event.type == NSApplicationDefined && "ProcessApplicationDefinedEvent, event parameter has wrong type");
+   
+   Private::MacOSXSystem::fd_map_iterator fdIter = fPimpl->fReadFds.find(event.data1);
+   bool descriptorFound = false;
+
+   if (fdIter != fPimpl->fReadFds.end()) {
+      fReadready->Set(event.data1);
+      descriptorFound = true;
+   }
+   
+   fdIter = fPimpl->fWriteFds.find(event.data1);
+   if (fdIter != fPimpl->fWriteFds.end()) {
+      fWriteready->Set(event.data1);
+      descriptorFound = true;
+   }
+   
+   if (!descriptorFound) {
+      Error("ProcessApplicationDefinedEvent", "file descriptor %d was not found", int(event.data1));
+      return;
+   }
+   
+   ++fNfd;
+}
+
diff --git a/core/meta/inc/LinkDef.h b/core/meta/inc/LinkDef.h
index 2f78132..ef3d0b6 100644
--- a/core/meta/inc/LinkDef.h
+++ b/core/meta/inc/LinkDef.h
@@ -21,6 +21,7 @@
 #pragma link C++ class TClass;
 #pragma link C++ class TClassStreamer+;
 #pragma link C++ class TMemberStreamer+;
+#pragma link C++ class TClassAttributeMap+;
 #pragma link C++ class TClassRef+;
 #pragma link C++ class TClassGenerator+;
 #pragma link C++ class TDataMember;
diff --git a/core/meta/inc/TCint.h b/core/meta/inc/TCint.h
index a20ba86..e3890bd 100644
--- a/core/meta/inc/TCint.h
+++ b/core/meta/inc/TCint.h
@@ -182,7 +182,7 @@ public:
    virtual void   CallFunc_Delete(void *func) const;
    virtual void   CallFunc_Exec(CallFunc_t *func, void *address) const;
    virtual Long_t    CallFunc_ExecInt(CallFunc_t *func, void *address) const;
-   virtual Long_t    CallFunc_ExecInt64(CallFunc_t *func, void *address) const;
+   virtual Long64_t  CallFunc_ExecInt64(CallFunc_t *func, void *address) const;
    virtual Double_t  CallFunc_ExecDouble(CallFunc_t *func, void *address) const;
    virtual CallFunc_t   *CallFunc_Factory() const;
    virtual CallFunc_t   *CallFunc_FactoryCopy(CallFunc_t *func) const;
diff --git a/core/meta/inc/TClass.h b/core/meta/inc/TClass.h
index 0a1985c..d57f29c 100644
--- a/core/meta/inc/TClass.h
+++ b/core/meta/inc/TClass.h
@@ -39,6 +39,7 @@
 class TBaseClass;
 class TBrowser;
 class TDataMember;
+class TClassAttributeMap;
 class TClassRef;
 class TMethod;
 class TRealData;
@@ -139,6 +140,7 @@ private:
    TClassRef         *fRefStart;        //!List of references to this object
    TVirtualRefProxy  *fRefProxy;        //!Pointer to reference proxy if this class represents a reference
    ROOT::TSchemaRuleSet *fSchemaRules;  //! Schema evolution rules
+   TClassAttributeMap *fAttributeMap;    //pointer to a class attribute map  
 
    typedef void (TClass::*StreamerImpl_t)(void *obj, TBuffer &b, const TClass *onfile_class) const;
    mutable StreamerImpl_t fStreamerImpl;//! Pointer to the function implementing the right streaming behavior for the class represented by this object.
@@ -255,6 +257,7 @@ public:
    TVirtualCollectionProxy *GetCollectionProxy() const;
    TVirtualIsAProxy  *GetIsAProxy() const;
    Version_t          GetClassVersion() const { fVersionUsed = kTRUE; return fClassVersion; }
+   Int_t              GetClassSize() const { return Size(); }
    TDataMember       *GetDataMember(const char *datamember) const;
    Long_t              GetDataMemberOffset(const char *membername) const;
    const char        *GetDeclFileName() const { return fDeclFileName; }
@@ -380,6 +383,14 @@ public:
    void               Destructor(void *obj, Bool_t dtorOnly = kFALSE);
    void              *DynamicCast(const TClass *base, void *obj, Bool_t up = kTRUE);
    Bool_t             IsFolder(void *obj) const;
+   void               CreateAttributeMap();
+   TClassAttributeMap *GetAttributeMap() const
+   {
+      //Get the TClassAttributeMap pointer to be able to add attribute 
+      //pairs key-value to the TClass.
+ 
+      return fAttributeMap;
+   }
    inline void        Streamer(void *obj, TBuffer &b, const TClass *onfile_class = 0) const
    {
       // Inline for performance, skipping one function call.
diff --git a/core/meta/inc/TClassAttributeMap.h b/core/meta/inc/TClassAttributeMap.h
new file mode 100644
index 0000000..c6de1c6
--- /dev/null
+++ b/core/meta/inc/TClassAttributeMap.h
@@ -0,0 +1,60 @@
+// @(#)root/meta:$Id$
+// Author: Bianca-Cristina Cristescu   03/07/13
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TClassAttributeMap
+#define ROOT_TClassAttributeMap
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TClassAttributeMap                                                    //
+//                                                                      //
+// Dictionary of attributes of a TClass.                                //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+
+#ifndef ROOT_TObject
+#include "TObject.h"
+#endif
+#ifndef ROOT_THashTable
+#include "THashTable.h"
+#endif
+
+
+class TClassAttributeMap : public TObject
+{
+public:
+
+   TClassAttributeMap();
+   virtual ~TClassAttributeMap();
+
+   void        AddProperty(const char* key, Int_t value);
+   void        AddProperty(const char* key, const char* value);
+   Bool_t      HasKey(const char* key) const;
+   const char  *GetPropertyAsString(const char* key) const;
+   Int_t       GetPropertyAsInt(const char* key) const;
+   Int_t       GetPropertySize() const;
+   Int_t       RemovePropertyInt(const char* key);
+   TString     RemovePropertyString(const char* key);
+   Bool_t      RemoveProperty(const char* key);
+   void        Clear(Option_t* option = "");
+
+private:
+
+   THashTable     fStringProperty;         //all properties of String type
+   THashTable     fIntProperty;            //all properties of Int type
+
+   ClassDef(TClassAttributeMap,1)  // Container for name/value pairs of TClass attributes
+};
+
+#endif // ROOT_TClassAttributeMap
+
diff --git a/core/meta/inc/TInterpreter.h b/core/meta/inc/TInterpreter.h
index 58e7dc3..b96c49b 100644
--- a/core/meta/inc/TInterpreter.h
+++ b/core/meta/inc/TInterpreter.h
@@ -153,7 +153,7 @@ public:
    virtual void   CallFunc_Delete(void * /* func */) const {;}
    virtual void   CallFunc_Exec(CallFunc_t * /* func */, void * /* address */) const {;}
    virtual Long_t    CallFunc_ExecInt(CallFunc_t * /* func */, void * /* address */) const {return 0;}
-   virtual Long_t    CallFunc_ExecInt64(CallFunc_t * /* func */, void * /* address */) const {return 0;}
+   virtual Long64_t  CallFunc_ExecInt64(CallFunc_t * /* func */, void * /* address */) const {return 0;}
    virtual Double_t  CallFunc_ExecDouble(CallFunc_t * /* func */, void * /* address */) const {return 0;}
    virtual CallFunc_t   *CallFunc_Factory() const {return 0;}
    virtual CallFunc_t   *CallFunc_FactoryCopy(CallFunc_t * /* func */) const {return 0;}
diff --git a/core/meta/inc/TStreamerElement.h b/core/meta/inc/TStreamerElement.h
index e0eac11..1d45066 100644
--- a/core/meta/inc/TStreamerElement.h
+++ b/core/meta/inc/TStreamerElement.h
@@ -1,4 +1,4 @@
-// @(#)root/meta:$Id$
+// @(#)root/meta:$Id: e0eac11e63ad37390c9467c97c5c6849c4ab7d39 $
 // Author: Rene Brun   12/10/2000
 
 /*************************************************************************
@@ -90,6 +90,7 @@ public:
    TClass*          GetNewClass() const { return fNewClass; }
    Int_t            GetType() const {return fType;}
    Int_t            GetOffset() const {return fOffset;}
+   void             GetSequenceType(TString &type) const;
    Int_t            GetTObjectOffset() const { return fTObjectOffset; }
    const char      *GetTypeName() const {return fTypeName.Data();}
    const char      *GetTypeNameBasic() const;
@@ -362,6 +363,8 @@ public:
    TStreamerSTL();
    TStreamerSTL(const char *name, const char *title, Int_t offset, 
                 const char *typeName, const char *trueType, Bool_t dmPointer);
+   TStreamerSTL(const char *name, const char *title, Int_t offset, 
+                const char *typeName, const TVirtualCollectionProxy &proxy , Bool_t dmPointer);
    virtual       ~TStreamerSTL();
    Bool_t         CannotSplit() const;
    Bool_t         IsaPointer() const;
diff --git a/core/meta/src/TCint.cxx b/core/meta/src/TCint.cxx
index 1a4eee1..0259e93 100644
--- a/core/meta/src/TCint.cxx
+++ b/core/meta/src/TCint.cxx
@@ -1387,12 +1387,39 @@ void TCint::Execute(TObject *obj, TClass *cl, TMethod *method, TObjArray *params
    // Check number of actual parameters against of expected formal ones
 
    Int_t nparms = argList->LastIndex()+1;
-   Int_t argc   = params ? params->LastIndex()+1:0;
+   Int_t argc   = params ? params->GetEntries() : 0;
 
-   if (nparms != argc) {
-      Error("Execute","Wrong number of the parameters");
+   if (argc > nparms) {
+      Error("Execute","Too many parameters to call %s, got %d but expected at most %d.",method->GetName(),argc,nparms);
       return;
    }
+   if (nparms != argc) {
+      // Let's see if the 'missing' argument are all defaulted.
+
+      // if nparms==0 then either we stopped earlier either argc is also zero and we can't reach here.
+      assert(nparms > 0);
+
+      TMethodArg *arg = (TMethodArg *) argList->At( 0 );
+      if (arg && arg->GetDefault() && arg->GetDefault()[0]) {
+         // There is a default value for the first missing
+         // argument, so we are fine.
+      } else {
+         Int_t firstDefault = -1;
+         for (Int_t i = 0; i < nparms; i ++) {
+            arg = (TMethodArg *) argList->At( i );
+            if (arg && arg->GetDefault() && arg->GetDefault()[0]) {
+               firstDefault = i;
+               break;
+            }
+         }
+         if (firstDefault >= 0) {
+            Error("Execute","Too few arguments to call %s, got only %d but expected at least %d and at most %d.",method->GetName(),argc,firstDefault,nparms);            
+         } else {
+            Error("Execute","Too few arguments to call %s, got only %d but expected %d.",method->GetName(),argc,nparms);
+         }
+         return;
+      }
+   }
 
    const char *listpar = "";
    TString complete(10);
@@ -2562,7 +2589,7 @@ Long_t  TCint::CallFunc_ExecInt(CallFunc_t *func, void *address) const
    return f->ExecInt(address);
 }
 //______________________________________________________________________________
-Long_t  TCint::CallFunc_ExecInt64(CallFunc_t *func, void *address) const
+Long64_t TCint::CallFunc_ExecInt64(CallFunc_t *func, void *address) const
 {
    // Interface to CINT function
 
diff --git a/core/meta/src/TClass.cxx b/core/meta/src/TClass.cxx
index 67b85d5..12a9dbc 100644
--- a/core/meta/src/TClass.cxx
+++ b/core/meta/src/TClass.cxx
@@ -30,6 +30,7 @@
 #include "TBaseClass.h"
 #include "TBrowser.h"
 #include "TBuffer.h"
+#include "TClassAttributeMap.h"
 #include "TClassGenerator.h"
 #include "TClassEdit.h"
 #include "TClassMenuItem.h"
@@ -772,7 +773,7 @@ TClass::TClass() :
    TDictionary(),
    fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
    fBase(0), fData(0), fMethod(0), fAllPubData(0), fAllPubMethod(0),
-   fClassMenuList(0),
+   fClassMenuList(0), 
    fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
    fInstanceCount(0), fOnHeap(0),
    fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
@@ -783,12 +784,14 @@ TClass::TClass() :
    fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE), 
    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
-   fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
+   fSchemaRules(0), fAttributeMap(0), fStreamerImpl(&TClass::StreamerDefault)
+
 {
    // Default ctor.
 
    R__LOCKGUARD2(gCINTMutex);
    fDeclFileLine   = -2;    // -2 for standalone TClass (checked in dtor)
+   fAttributeMap = 0;
 }
 
 //______________________________________________________________________________
@@ -807,7 +810,7 @@ TClass::TClass(const char *name, Bool_t silent) :
    fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE), 
    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
-   fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
+   fSchemaRules(0), fAttributeMap(0), fStreamerImpl(&TClass::StreamerDefault)
 {
    // Create a TClass object. This object contains the full dictionary
    // of a class. It has list to baseclasses, datamembers and methods.
@@ -857,7 +860,7 @@ TClass::TClass(const char *name, Version_t cversion,
    fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE), 
    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
-   fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
+   fSchemaRules(0), fAttributeMap(0), fStreamerImpl(&TClass::StreamerDefault)
 {
    // Create a TClass object. This object contains the full dictionary
    // of a class. It has list to baseclasses, datamembers and methods.
@@ -886,7 +889,7 @@ TClass::TClass(const char *name, Version_t cversion,
    fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE), 
    fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
    fCurrentInfo(0), fRefStart(0), fRefProxy(0),
-   fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
+   fSchemaRules(0), fAttributeMap(0), fStreamerImpl(&TClass::StreamerDefault)
 {
    // Create a TClass object. This object contains the full dictionary
    // of a class. It has list to baseclasses, datamembers and methods.
@@ -1162,6 +1165,7 @@ TClass::TClass(const TClass& cl) :
   fRefStart(cl.fRefStart),
   fRefProxy(cl.fRefProxy),
   fSchemaRules(cl.fSchemaRules),
+  fAttributeMap(cl.fAttributeMap ? (TClassAttributeMap*)cl.fAttributeMap->Clone() : 0 ),
   fStreamerImpl(cl.fStreamerImpl)
 {
    //copy constructor
@@ -1279,6 +1283,8 @@ TClass::~TClass()
       }
       delete fConversionStreamerInfo;
    }
+
+   delete fAttributeMap;
 }
 
 //------------------------------------------------------------------------------
@@ -2098,6 +2104,16 @@ void TClass::CopyCollectionProxy(const TVirtualCollectionProxy &orig)
 
 
 //______________________________________________________________________________
+void TClass::CreateAttributeMap()
+{
+   //Create a TClassAttributeMap for a TClass to be able to add attribute pairs
+   //key-value to the TClass.
+
+   if (!fAttributeMap)
+      fAttributeMap = new TClassAttributeMap;
+}
+
+//______________________________________________________________________________
 void TClass::Draw(Option_t *option)
 {
    // Draw detailed class inheritance structure.
@@ -5666,4 +5682,3 @@ ROOT::DirAutoAdd_t TClass::GetDirectoryAutoAdd() const
 
    return fDirAutoAdd;
 }
-
diff --git a/core/meta/src/TClassAttributeMap.cxx b/core/meta/src/TClassAttributeMap.cxx
new file mode 100644
index 0000000..c759258
--- /dev/null
+++ b/core/meta/src/TClassAttributeMap.cxx
@@ -0,0 +1,164 @@
+// @(#)root/meta:$Id:$
+// Author: Bianca-Cristina Cristescu   03/07/13
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+//  The ROOT oject has a list of properties which are stored and       //
+//  retrieved using TClassAttributeMap.                                 //
+//  TClassAttributeMap maps the property keys of the object to their		//	
+//  values.															    //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include "TClassAttributeMap.h"
+#include "THashTable.h"
+#include "TNamed.h"
+#include "TParameter.h"
+
+
+ClassImp(TClassAttributeMap)
+
+//_____________________________________________________________________________
+TClassAttributeMap::TClassAttributeMap()
+{
+   //Default constructor.
+   fIntProperty.SetOwner(kTRUE);
+   fStringProperty.SetOwner(kTRUE);
+}
+
+//_____________________________________________________________________________
+TClassAttributeMap::~TClassAttributeMap()
+{
+   //Default destructor.
+}
+
+//_____________________________________________________________________________
+void TClassAttributeMap::AddProperty(const char* key, Int_t value)
+{
+   //Add a property with a Int value to the TClassAttributeMap.
+   //Parameters: key and Int value of the property.
+
+   //Add the property pair name - Int value to the hash table.
+   fIntProperty.Add(new TParameter<int>(key, value));
+}
+
+//_____________________________________________________________________________
+void TClassAttributeMap::AddProperty(const char* key, const char* value)
+{
+   //Add a property with a String value to the TClassAttributeMap.
+   //Parameters: key and char* value of the property.
+
+   //Add the property pair name - Int value to the hash table.
+   fStringProperty.Add(new TNamed(key, value));
+}
+
+//_____________________________________________________________________________
+Bool_t TClassAttributeMap::HasKey(const char* key) const
+{
+
+   //Check whether the class has a property using the key.
+
+   if (fStringProperty.FindObject(key))
+      return true;
+   if (fIntProperty.FindObject(key))
+      return true;
+   return false;
+}
+
+//_____________________________________________________________________________
+Int_t TClassAttributeMap::GetPropertyAsInt(const char* key) const
+{
+   //Access the value of a Int property using the key.
+
+   //Copy object into found to avoid calling the function two times.
+   TObject* found = fIntProperty.FindObject(key);
+   if (found)
+      return ((TParameter<int>*)found)->GetVal();
+   else
+      //Show an error message if the key is not found.
+      Error("GetPropertyAsInt"
+      , "Could not find property with Int value for this key: %s", key);
+   return -1;
+}
+
+//_____________________________________________________________________________
+const char* TClassAttributeMap::GetPropertyAsString(const char* key) const
+{
+   //Access the value of a String property using the key.
+
+   //Copy object into found to avoid calling the function two times.
+   TObject* found = fStringProperty.FindObject(key);
+   if(found)
+      return found->GetTitle();
+   else
+      //Show an error message if the key is not found.
+      Error("GetPropertyAsString"
+      , "Could not find property with String value for this key: %s", key);
+   return 0;
+}
+
+//_____________________________________________________________________________
+Int_t TClassAttributeMap::GetPropertySize() const
+{
+   //Return the number of properties of the class as Int_t.
+
+   return fIntProperty.GetSize() + fStringProperty.GetSize();
+}
+
+//_____________________________________________________________________________
+Int_t TClassAttributeMap::RemovePropertyInt(const char* key)
+{
+   //Remove a Int property from the attribute map.
+   //Returns the Int property removed or NULL if the property does not exist.
+
+   TParameter<int> *property = (TParameter<int>*)fIntProperty.FindObject(key);
+   if (property) {
+     fIntProperty.Remove(property);
+     return property->GetVal();
+   }
+   return -1;
+}
+
+//_____________________________________________________________________________
+TString TClassAttributeMap::RemovePropertyString(const char* key)
+{
+   //Remove a String property from the attribute map specified by the key.
+   //Returns the TString property removed or NULL if the property does not exist.
+
+   TObject *property = fStringProperty.FindObject(key);
+   if (property) {
+      fStringProperty.Remove(property);
+      return property->GetTitle();
+   }
+   return TString(0);
+}
+
+Bool_t TClassAttributeMap::RemoveProperty(const char* key)
+{
+   //Remove a property from the attribute map specified by the key.
+   //Returns true if property exists and was removed, false if property
+   //does not exist.
+
+   if (TObject *property = fStringProperty.FindObject(key)) {
+      fStringProperty.Remove(property);
+      return true;
+   }
+   return false;
+}
+
+//_____________________________________________________________________________
+void TClassAttributeMap::Clear(Option_t* /*option = ""*/)
+{
+   //Deletes all the properties of the class.
+
+   fIntProperty.Delete();
+   fStringProperty.Delete();
+}
diff --git a/core/meta/src/TStreamerElement.cxx b/core/meta/src/TStreamerElement.cxx
index a0f451e..4a3bd91 100644
--- a/core/meta/src/TStreamerElement.cxx
+++ b/core/meta/src/TStreamerElement.cxx
@@ -32,6 +32,7 @@
 #include "TError.h"
 #include "TDataType.h"
 #include "TVirtualMutex.h"
+#include "TVirtualCollectionProxy.h"
 #include <iostream>
 
 #include <string>
@@ -305,6 +306,36 @@ const char *TStreamerElement::GetFullName() const
 }
 
 //______________________________________________________________________________
+void TStreamerElement::GetSequenceType(TString &sequenceType) const
+{
+   // Fill type with the string representation of sequence
+   // information including 'cached','repeat','write' or
+   // 'nodelete'.
+
+   sequenceType.Clear();
+   Bool_t first = kTRUE;
+   if (TestBit(TStreamerElement::kCache)) {
+      first = kFALSE;
+      sequenceType += "cached";
+   }
+   if (TestBit(TStreamerElement::kRepeat)) {
+      if (!first) sequenceType += ",";
+      first = kFALSE;
+      sequenceType += "repeat";
+   }
+   if (TestBit(TStreamerElement::kDoNotDelete)) {
+      if (!first) sequenceType += ",";
+      first = kFALSE;
+      sequenceType += "nodelete";
+   }
+   if (TestBit(TStreamerElement::kWrite)) {
+      if (!first) sequenceType += ",";
+      first = kFALSE;
+      sequenceType += "write";
+   }
+}
+
+//______________________________________________________________________________
 Int_t TStreamerElement::GetSize() const
 {
    // Returns size of this element in bytes.
@@ -374,9 +405,16 @@ void TStreamerElement::ls(Option_t *) const
 
    TString temp(GetTypeName());
    if (IsaPointer() && !fTypeName.Contains("*")) temp += "*";
+
+   TString sequenceType;
+   GetSequenceType(sequenceType);
+   if (sequenceType.Length()) {
+      sequenceType.Prepend(" (");
+      sequenceType += ") ";
+   }
    printf("  %-14s %-15s offset=%3d type=%2d %s%-20s\n",
-      temp.Data(),GetFullName(),fOffset,fType,TestBit(kCache)?"(cached) ":"",
-      GetTitle());
+          temp.Data(),GetFullName(),fOffset,fType,sequenceType.Data(),
+          GetTitle());
 }
 
 //______________________________________________________________________________
@@ -463,6 +501,7 @@ void TStreamerElement::Streamer(TBuffer &R__b)
       R__b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
       
       ResetBit(TStreamerElement::kCache);
+      ResetBit(TStreamerElement::kWrite);
    } else {
       R__b.WriteClassBuffer(TStreamerElement::Class(),this);
    }
@@ -592,7 +631,13 @@ void TStreamerBase::ls(Option_t *) const
 {
    // Print the content of the element.
 
-   printf("  %-14s %-15s offset=%3d type=%2d %s%-20s\n",GetFullName(),GetTypeName(),fOffset,fType,TestBit(kCache)?"(cached) ":"",GetTitle());
+   TString sequenceType;
+   GetSequenceType(sequenceType);
+   if (sequenceType.Length()) {
+      sequenceType.Prepend(" (");
+      sequenceType += ") ";
+   }
+   printf("  %-14s %-15s offset=%3d type=%2d %s%-20s\n",GetFullName(),GetTypeName(),fOffset,fType,sequenceType.Data(),GetTitle());
 }
 
 //______________________________________________________________________________
@@ -1511,6 +1556,37 @@ TStreamerSTL::TStreamerSTL() : fSTLtype(0),fCtype(0)
 
 //______________________________________________________________________________
 TStreamerSTL::TStreamerSTL(const char *name, const char *title, Int_t offset,
+                           const char *typeName, const TVirtualCollectionProxy &proxy, Bool_t dmPointer)
+        : TStreamerElement(name,title,offset,kSTL,typeName)
+{
+   // Create a TStreamerSTL object.
+
+   fTypeName = TClassEdit::ShortType(fTypeName,TClassEdit::kDropStlDefault).c_str();
+
+  if (name==typeName /* intentional pointer comparison */
+      || strcmp(name,typeName)==0) {
+      // We have a base class.
+      fName = fTypeName;
+   }
+   fSTLtype = proxy.GetCollectionType();
+   fCtype   = 0;
+
+   if (dmPointer) fSTLtype += TVirtualStreamerInfo::kOffsetP;
+
+   if (fSTLtype == kSTLbitset) {
+      // Nothing to check
+   } else if (proxy.GetValueClass()) {
+      if (proxy.HasPointers()) fCtype = TVirtualStreamerInfo::kObjectp;
+      else                     fCtype = TVirtualStreamerInfo::kObject;
+   } else {
+      fCtype = proxy.GetType();
+      if (proxy.HasPointers()) fCtype += TVirtualStreamerInfo::kOffsetP;
+   }
+   if (TStreamerSTL::IsaPointer()) fType = TVirtualStreamerInfo::kSTLp;  
+}
+
+//______________________________________________________________________________
+TStreamerSTL::TStreamerSTL(const char *name, const char *title, Int_t offset,
                            const char *typeName, const char *trueType, Bool_t dmPointer)
         : TStreamerElement(name,title,offset,kSTL,typeName)
 {
@@ -1532,7 +1608,7 @@ TStreamerSTL::TStreamerSTL(const char *name, const char *title, Int_t offset,
    strlcpy(s,t,nch+1);
    char *sopen  = strchr(s,'<'); 
    if (sopen == 0) {
-      Fatal("TStreamerSTL","For %s, the type name (%s) is not seemingly not a template (template argument not found)", name, s);
+      Fatal("TStreamerSTL","For %s, the type name (%s) is seemingly not a template (template argument not found)", name, s);
       return;
    }
    *sopen  = 0; sopen++;
@@ -1702,9 +1778,15 @@ void TStreamerSTL::ls(Option_t *) const
       cdim.Form("[%d]",fMaxIndex[i]);
       name += cdim;
    }
+   TString sequenceType;
+   GetSequenceType(sequenceType);
+   if (sequenceType.Length()) {
+      sequenceType.Prepend(" (");
+      sequenceType += ") ";
+   }
    printf("  %-14s %-15s offset=%3d type=%2d %s,stl=%d, ctype=%d, %-20s\n",
-      GetTypeName(),name.Data(),fOffset,fType,TestBit(kCache)?"(cached)":"",
-      fSTLtype,fCtype,GetTitle());
+          GetTypeName(),name.Data(),fOffset,fType,sequenceType.Data(),
+          fSTLtype,fCtype,GetTitle());
 }
 
 //______________________________________________________________________________
diff --git a/core/unix/src/TUnixSystem.cxx b/core/unix/src/TUnixSystem.cxx
index 3a57d63..221dc26 100644
--- a/core/unix/src/TUnixSystem.cxx
+++ b/core/unix/src/TUnixSystem.cxx
@@ -1811,6 +1811,7 @@ char *TUnixSystem::ExpandPathName(const char *path)
    // environment variables in a pathname. If compatibility is not an issue
    // you can use on Unix directly $XXX. The user must delete returned string.
    // Returns the expanded pathname or 0 in case of error.
+   // The user must delete returned string (delete []).
 
    TString patbuf = path;
    if (ExpandPathName(patbuf))
diff --git a/core/utils/src/rootcint.cxx b/core/utils/src/rootcint.cxx
index d01e5cd..d94c228 100644
--- a/core/utils/src/rootcint.cxx
+++ b/core/utils/src/rootcint.cxx
@@ -4254,6 +4254,10 @@ int main(int argc, char **argv)
    } else if (!strcmp(argv[ic], "-v4")) {
       gErrorIgnoreLevel = kInfo; // Display all information (same as -v)
       ic++;
+   } else if (!strcmp(argv[ic], "-s") || !strcmp(argv[ic], "-m")) {
+      // Ignore ROOT 6 arguments about creating pcm and
+      // their dependencies.
+      ic += 2;
    }
    if (ic < argc) {
       if (!strcmp(argv[ic], "-cint")) {
@@ -4282,6 +4286,10 @@ int main(int argc, char **argv)
 
          longheadername = 1;
          ic++;
+      } else if (!strcmp(argv[ic], "-s") || !strcmp(argv[ic], "-m")) {
+         // Ignore ROOT 6 arguments about creating pcm and
+         // their dependencies.
+         ic += 2;
       } else if (!strncmp(argv[ic],libprefix,strlen(libprefix))) {
 
          gLiblistPrefix = argv[ic]+strlen(libprefix);
@@ -4412,6 +4420,12 @@ int main(int argc, char **argv)
       ifl = 0;
    }
 
+   while (!strcmp(argv[ic], "-s") || !strcmp(argv[ic], "-m")) {
+      // Ignore ROOT 6 arguments about creating pcm and
+      // their dependencies.
+      ic += 2;
+   }
+
    // If the user request use of a preprocessor we are going to bundle
    // all the files into one so that cint considers them one compilation
    // unit and so that each file that contains code guard is really
diff --git a/core/winnt/src/Win32Splash.cxx b/core/winnt/src/Win32Splash.cxx
index f37d064..2edfd38 100644
--- a/core/winnt/src/Win32Splash.cxx
+++ b/core/winnt/src/Win32Splash.cxx
@@ -358,10 +358,10 @@ void *OpenGraphic(char *name)
       // get width and height of picture
       hr = Ipic->get_Width(&sizeInHiMetric.cx);
       if (!SUCCEEDED(hr))
-         goto err;
+         return 0;
       Ipic->get_Height(&sizeInHiMetric.cy);
       if (!SUCCEEDED(hr))
-         goto err;
+         return 0;
 
       // convert himetric to pixels
       sizeInPix.cx = (nPixelsPerInchX * sizeInHiMetric.cx +
@@ -374,7 +374,6 @@ void *OpenGraphic(char *name)
       gImageInfo.Path = name;
       return Ipic;
    }
-err:
    return 0;
 }
 
diff --git a/doc/v534/index.html b/doc/v534/index.html
index 55e04a3..0cfa3cd 100644
--- a/doc/v534/index.html
+++ b/doc/v534/index.html
@@ -8,7 +8,7 @@
 <!--                                             -->
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
-<title>ROOT Version 5.34/08 Release Notes</title>
+<title>ROOT Version 5.34/10 Release Notes</title>
 <meta name="rating" content="General" />
 <meta name="objecttype" content="Manual" />
 <meta name="keywords" content="software development, oo, object oriented, unix, x11, windows, c++, html, rene brun, fons rademakers, cern" />
diff --git a/etc/HistFactorySchema.dtd b/etc/HistFactorySchema.dtd
index 99d20ab..452dd50 100644
--- a/etc/HistFactorySchema.dtd
+++ b/etc/HistFactorySchema.dtd
@@ -156,5 +156,9 @@ For this element there is no sublemenents so the setting will only have local ef
 <!ELEMENT ShapeFactor EMPTY>
 <!ATTLIST ShapeFactor
           Name              CDATA            #REQUIRED
+          HistoName         CDATA            #IMPLIED
+          HistoPath         CDATA            #IMPLIED
+          InputFile         CDATA            #IMPLIED
+          Const             CDATA            #IMPLIED
 > 
 
diff --git a/etc/plugins/TSQLServer/P060_TSQLiteServer.C b/etc/plugins/TSQLServer/P060_TSQLiteServer.C
new file mode 100644
index 0000000..569bcf4
--- /dev/null
+++ b/etc/plugins/TSQLServer/P060_TSQLiteServer.C
@@ -0,0 +1,5 @@
+void P060_TSQLiteServer()
+{
+   gPluginMgr->AddHandler("TSQLServer", "^sqlite:", "TSQLiteServer",
+      "SQLite", "TSQLiteServer(const char*,const char*,const char*)");
+}
diff --git a/etc/plugins/TVirtualPS/P050_TTeXDump.C b/etc/plugins/TVirtualPS/P050_TTeXDump.C
new file mode 100644
index 0000000..d46ceae
--- /dev/null
+++ b/etc/plugins/TVirtualPS/P050_TTeXDump.C
@@ -0,0 +1,5 @@
+void P050_TTeXDump()
+{
+   gPluginMgr->AddHandler("TVirtualPS", "tex", "TTeXDump",
+      "Postscript", "TTeXDump()");
+}
diff --git a/geom/gdml/src/TGDMLParse.cxx b/geom/gdml/src/TGDMLParse.cxx
index 3facdc8..3c3a662 100644
--- a/geom/gdml/src/TGDMLParse.cxx
+++ b/geom/gdml/src/TGDMLParse.cxx
@@ -480,9 +480,9 @@ XMLNodePointer_t TGDMLParse::PosProcess(TXMLEngine* gdml, XMLNodePointer_t node,
 
    retunit = GetScale(lunit);
 
-   xline = TString::Format("%s*%s", xpos.Data(), retunit.Data());
-   yline = TString::Format("%s*%s", ypos.Data(), retunit.Data());
-   zline = TString::Format("%s*%s", zpos.Data(), retunit.Data());
+   xline = TString::Format("(%s)*%s", xpos.Data(), retunit.Data());
+   yline = TString::Format("(%s)*%s", ypos.Data(), retunit.Data());
+   zline = TString::Format("(%s)*%s", zpos.Data(), retunit.Data());
 
    TGeoTranslation* pos = new TGeoTranslation(Evaluate(xline),
                                               Evaluate(yline),
@@ -541,9 +541,9 @@ XMLNodePointer_t TGDMLParse::RotProcess(TXMLEngine* gdml, XMLNodePointer_t node,
 
    retunit = GetScale(aunit);
 
-   xline = TString::Format("%s*%s", xpos.Data(), retunit.Data());
-   yline = TString::Format("%s*%s", ypos.Data(), retunit.Data());
-   zline = TString::Format("%s*%s", zpos.Data(), retunit.Data());
+   xline = TString::Format("(%s)*%s", xpos.Data(), retunit.Data());
+   yline = TString::Format("(%s)*%s", ypos.Data(), retunit.Data());
+   zline = TString::Format("(%s)*%s", zpos.Data(), retunit.Data());
 
    TGeoRotation* rot = new TGeoRotation();
 
@@ -1284,8 +1284,8 @@ XMLNodePointer_t TGDMLParse::VolProcess(TXMLEngine* gdml, XMLNodePointer_t node)
          retunit = GetScale(lunit);
 
          numberline = TString::Format("%s", number.Data());
-         widthline = TString::Format("%s*%s", width.Data(), retunit.Data());
-         offsetline = TString::Format("%s*%s", offset.Data(), retunit.Data());
+         widthline = TString::Format("(%s)*%s", width.Data(), retunit.Data());
+         offsetline = TString::Format("(%s)*%s", offset.Data(), retunit.Data());
 
          fVolID = fVolID + 1;
          Double_t xlo, xhi;
@@ -1645,9 +1645,9 @@ XMLNodePointer_t TGDMLParse::Box(TXMLEngine* gdml, XMLNodePointer_t node, XMLAtt
 
    retunit = GetScale(lunit);
 
-   xline = TString::Format("%s*%s", xpos.Data(), retunit.Data());
-   yline = TString::Format("%s*%s", ypos.Data(), retunit.Data());
-   zline = TString::Format("%s*%s", zpos.Data(), retunit.Data());
+   xline = TString::Format("(%s)*%s", xpos.Data(), retunit.Data());
+   yline = TString::Format("(%s)*%s", ypos.Data(), retunit.Data());
+   zline = TString::Format("(%s)*%s", zpos.Data(), retunit.Data());
 
 
    TGeoBBox* box = new TGeoBBox(NameShort(name), Evaluate(xline) / 2,
@@ -1718,9 +1718,9 @@ XMLNodePointer_t TGDMLParse::Ellipsoid(TXMLEngine* gdml, XMLNodePointer_t node,
 
    retunit = GetScale(lunit);
 
-   axline = TString::Format("%s*%s", ax.Data(), retunit.Data());
-   byline = TString::Format("%s*%s", by.Data(), retunit.Data());
-   czline = TString::Format("%s*%s", cz.Data(), retunit.Data());
+   axline = TString::Format("(%s)*%s", ax.Data(), retunit.Data());
+   byline = TString::Format("(%s)*%s", by.Data(), retunit.Data());
+   czline = TString::Format("(%s)*%s", cz.Data(), retunit.Data());
    Double_t radius = Evaluate(czline);
    Double_t dx = Evaluate(axline);
    Double_t dy = Evaluate(byline);
@@ -1732,13 +1732,13 @@ XMLNodePointer_t TGDMLParse::Ellipsoid(TXMLEngine* gdml, XMLNodePointer_t node,
    if (zcut1 == "") {
       z1 = -radius;
    } else {
-      zcut1line = TString::Format("%s*%s", zcut1.Data(), retunit.Data());
+      zcut1line = TString::Format("(%s)*%s", zcut1.Data(), retunit.Data());
       z1 = Evaluate(zcut1line);
    }
    if (zcut2 == "") {
 	   z2 = radius;
    } else {
-	   zcut2line = TString::Format("%s*%s", zcut2.Data(), retunit.Data());
+	   zcut2line = TString::Format("(%s)*%s", zcut2.Data(), retunit.Data());
 	   z2 = Evaluate(zcut2line);
    }
 
@@ -1815,8 +1815,8 @@ XMLNodePointer_t TGDMLParse::ElCone(TXMLEngine* gdml, XMLNodePointer_t node, XML
    //dxline and dyline are without units because they are as a ration
    dxline = TString::Format("%s", dx.Data());
    dyline = TString::Format("%s", dy.Data());
-   zmaxline = TString::Format("%s*%s", zmax.Data(), retunit.Data());
-   zcutline = TString::Format("%s*%s", zcut.Data(), retunit.Data());
+   zmaxline = TString::Format("(%s)*%s", zmax.Data(), retunit.Data());
+   zcutline = TString::Format("(%s)*%s", zcut.Data(), retunit.Data());
 
    Double_t dxratio = Evaluate(dxline);
    Double_t dyratio = Evaluate(dyline);
@@ -1893,9 +1893,9 @@ XMLNodePointer_t TGDMLParse::Paraboloid(TXMLEngine* gdml, XMLNodePointer_t node,
 
    retunit = GetScale(lunit);
 
-   rloline = TString::Format("%s*%s", rlopos.Data(), retunit.Data());
-   rhiline = TString::Format("%s*%s", rhipos.Data(), retunit.Data());
-   dzline = TString::Format("%s*%s", dzpos.Data(), retunit.Data());
+   rloline = TString::Format("(%s)*%s", rlopos.Data(), retunit.Data());
+   rhiline = TString::Format("(%s)*%s", rhipos.Data(), retunit.Data());
+   dzline = TString::Format("(%s)*%s", dzpos.Data(), retunit.Data());
 
    TGeoParaboloid* paraboloid = new TGeoParaboloid(NameShort(name), Evaluate(rloline),
                                                    Evaluate(rhiline),
@@ -2011,23 +2011,23 @@ XMLNodePointer_t TGDMLParse::Arb8(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
 
    retunit = GetScale(lunit);
 
-   v1xline = TString::Format("%s*%s", v1xpos.Data(), retunit.Data());
-   v1yline = TString::Format("%s*%s", v1ypos.Data(), retunit.Data());
-   v2xline = TString::Format("%s*%s", v2xpos.Data(), retunit.Data());
-   v2yline = TString::Format("%s*%s", v2ypos.Data(), retunit.Data());
-   v3xline = TString::Format("%s*%s", v3xpos.Data(), retunit.Data());
-   v3yline = TString::Format("%s*%s", v3ypos.Data(), retunit.Data());
-   v4xline = TString::Format("%s*%s", v4xpos.Data(), retunit.Data());
-   v4yline = TString::Format("%s*%s", v4ypos.Data(), retunit.Data());
-   v5xline = TString::Format("%s*%s", v5xpos.Data(), retunit.Data());
-   v5yline = TString::Format("%s*%s", v5ypos.Data(), retunit.Data());
-   v6xline = TString::Format("%s*%s", v6xpos.Data(), retunit.Data());
-   v6yline = TString::Format("%s*%s", v6ypos.Data(), retunit.Data());
-   v7xline = TString::Format("%s*%s", v7xpos.Data(), retunit.Data());
-   v7yline = TString::Format("%s*%s", v7ypos.Data(), retunit.Data());
-   v8xline = TString::Format("%s*%s", v8xpos.Data(), retunit.Data());
-   v8yline = TString::Format("%s*%s", v8ypos.Data(), retunit.Data());
-   dzline  = TString::Format("%s*%s", dzpos.Data(),  retunit.Data());
+   v1xline = TString::Format("(%s)*%s", v1xpos.Data(), retunit.Data());
+   v1yline = TString::Format("(%s)*%s", v1ypos.Data(), retunit.Data());
+   v2xline = TString::Format("(%s)*%s", v2xpos.Data(), retunit.Data());
+   v2yline = TString::Format("(%s)*%s", v2ypos.Data(), retunit.Data());
+   v3xline = TString::Format("(%s)*%s", v3xpos.Data(), retunit.Data());
+   v3yline = TString::Format("(%s)*%s", v3ypos.Data(), retunit.Data());
+   v4xline = TString::Format("(%s)*%s", v4xpos.Data(), retunit.Data());
+   v4yline = TString::Format("(%s)*%s", v4ypos.Data(), retunit.Data());
+   v5xline = TString::Format("(%s)*%s", v5xpos.Data(), retunit.Data());
+   v5yline = TString::Format("(%s)*%s", v5ypos.Data(), retunit.Data());
+   v6xline = TString::Format("(%s)*%s", v6xpos.Data(), retunit.Data());
+   v6yline = TString::Format("(%s)*%s", v6ypos.Data(), retunit.Data());
+   v7xline = TString::Format("(%s)*%s", v7xpos.Data(), retunit.Data());
+   v7yline = TString::Format("(%s)*%s", v7ypos.Data(), retunit.Data());
+   v8xline = TString::Format("(%s)*%s", v8xpos.Data(), retunit.Data());
+   v8yline = TString::Format("(%s)*%s", v8ypos.Data(), retunit.Data());
+   dzline  = TString::Format("(%s)*%s", dzpos.Data(),  retunit.Data());
 
 
    TGeoArb8* arb8 = new TGeoArb8(NameShort(name), Evaluate(dzline));
@@ -2108,11 +2108,11 @@ XMLNodePointer_t TGDMLParse::Tube(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   rminline = TString::Format("%s*%s", rmin.Data(), retlunit.Data());
-   rmaxline = TString::Format("%s*%s", rmax.Data(), retlunit.Data());
-   zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
-   startphiline = TString::Format("%s*%s", startphi.Data(), retaunit.Data());
-   deltaphiline = TString::Format("(%s*%s) + %s", deltaphi.Data(), retaunit.Data(), startphiline.Data());
+   rminline = TString::Format("(%s)*%s", rmin.Data(), retlunit.Data());
+   rmaxline = TString::Format("(%s)*%s", rmax.Data(), retlunit.Data());
+   zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
+   startphiline = TString::Format("(%s)*%s", startphi.Data(), retaunit.Data());
+   deltaphiline = TString::Format("((%s)*%s) + %s", deltaphi.Data(), retaunit.Data(), startphiline.Data());
 
    TGeoTubeSeg* tube = new TGeoTubeSeg(NameShort(name), Evaluate(rminline),
                                        Evaluate(rmaxline),
@@ -2211,17 +2211,17 @@ XMLNodePointer_t TGDMLParse::CutTube(TXMLEngine* gdml, XMLNodePointer_t node, XM
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   rminline = TString::Format("%s*%s", rmin.Data(), retlunit.Data());
-   rmaxline = TString::Format("%s*%s", rmax.Data(), retlunit.Data());
-   zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
-   startphiline = TString::Format("%s*%s", startphi.Data(), retaunit.Data());
-   deltaphiline = TString::Format("(%s*%s) + %s", deltaphi.Data(), retaunit.Data(), startphiline.Data());
-   lowXline = TString::Format("%s*%s", lowX.Data(), retlunit.Data());
-   lowYline = TString::Format("%s*%s", lowY.Data(), retlunit.Data());
-   lowZline = TString::Format("%s*%s", lowZ.Data(), retlunit.Data());
-   highXline = TString::Format("%s*%s", highX.Data(), retlunit.Data());
-   highYline = TString::Format("%s*%s", highY.Data(), retlunit.Data());
-   highZline = TString::Format("%s*%s", highZ.Data(), retlunit.Data());
+   rminline = TString::Format("(%s)*%s", rmin.Data(), retlunit.Data());
+   rmaxline = TString::Format("(%s)*%s", rmax.Data(), retlunit.Data());
+   zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
+   startphiline = TString::Format("(%s)*%s", startphi.Data(), retaunit.Data());
+   deltaphiline = TString::Format("((%s)*%s) + %s", deltaphi.Data(), retaunit.Data(), startphiline.Data());
+   lowXline = TString::Format("(%s)*%s", lowX.Data(), retlunit.Data());
+   lowYline = TString::Format("(%s)*%s", lowY.Data(), retlunit.Data());
+   lowZline = TString::Format("(%s)*%s", lowZ.Data(), retlunit.Data());
+   highXline = TString::Format("(%s)*%s", highX.Data(), retlunit.Data());
+   highYline = TString::Format("(%s)*%s", highY.Data(), retlunit.Data());
+   highZline = TString::Format("(%s)*%s", highZ.Data(), retlunit.Data());
 
 
    TGeoCtub* cuttube = new TGeoCtub(NameShort(name), Evaluate(rminline),
@@ -2311,13 +2311,13 @@ XMLNodePointer_t TGDMLParse::Cone(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   rmin1line = TString::Format("%s*%s", rmin1.Data(), retlunit.Data());
-   rmax1line = TString::Format("%s*%s", rmax1.Data(), retlunit.Data());
-   rmin2line = TString::Format("%s*%s", rmin2.Data(), retlunit.Data());
-   rmax2line = TString::Format("%s*%s", rmax2.Data(), retlunit.Data());
-   zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
-   startphiline = TString::Format("%s*%s", startphi.Data(), retaunit.Data());
-   deltaphiline = TString::Format("%s*%s", deltaphi.Data(), retaunit.Data());
+   rmin1line = TString::Format("(%s)*%s", rmin1.Data(), retlunit.Data());
+   rmax1line = TString::Format("(%s)*%s", rmax1.Data(), retlunit.Data());
+   rmin2line = TString::Format("(%s)*%s", rmin2.Data(), retlunit.Data());
+   rmax2line = TString::Format("(%s)*%s", rmax2.Data(), retlunit.Data());
+   zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
+   startphiline = TString::Format("(%s)*%s", startphi.Data(), retaunit.Data());
+   deltaphiline = TString::Format("(%s)*%s", deltaphi.Data(), retaunit.Data());
    Double_t sphi = Evaluate(startphiline);
    Double_t ephi = sphi + Evaluate(deltaphiline);
 
@@ -2419,17 +2419,17 @@ XMLNodePointer_t TGDMLParse::Trap(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   x1line = TString::Format("%s*%s", x1.Data(), retlunit.Data());
-   x2line = TString::Format("%s*%s", x2.Data(), retlunit.Data());
-   x3line = TString::Format("%s*%s", x3.Data(), retlunit.Data());
-   x4line = TString::Format("%s*%s", x4.Data(), retlunit.Data());
-   y1line = TString::Format("%s*%s", y1.Data(), retlunit.Data());
-   y2line = TString::Format("%s*%s", y2.Data(), retlunit.Data());
-   zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
-   philine = TString::Format("%s*%s", phi.Data(), retaunit.Data());
-   thetaline = TString::Format("%s*%s", theta.Data(), retaunit.Data());
-   alpha1line = TString::Format("%s*%s", alpha1.Data(), retaunit.Data());
-   alpha2line = TString::Format("%s*%s", alpha2.Data(), retaunit.Data());
+   x1line = TString::Format("(%s)*%s", x1.Data(), retlunit.Data());
+   x2line = TString::Format("(%s)*%s", x2.Data(), retlunit.Data());
+   x3line = TString::Format("(%s)*%s", x3.Data(), retlunit.Data());
+   x4line = TString::Format("(%s)*%s", x4.Data(), retlunit.Data());
+   y1line = TString::Format("(%s)*%s", y1.Data(), retlunit.Data());
+   y2line = TString::Format("(%s)*%s", y2.Data(), retlunit.Data());
+   zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
+   philine = TString::Format("(%s)*%s", phi.Data(), retaunit.Data());
+   thetaline = TString::Format("(%s)*%s", theta.Data(), retaunit.Data());
+   alpha1line = TString::Format("(%s)*%s", alpha1.Data(), retaunit.Data());
+   alpha2line = TString::Format("(%s)*%s", alpha2.Data(), retaunit.Data());
 
    TGeoTrap* trap = new TGeoTrap(NameShort(name), Evaluate(zline) / 2,
                                  Evaluate(thetaline),
@@ -2504,11 +2504,11 @@ XMLNodePointer_t TGDMLParse::Trd(TXMLEngine* gdml, XMLNodePointer_t node, XMLAtt
 
    retlunit = GetScale(lunit);
 
-   x1line = TString::Format("%s*%s", x1.Data(), retlunit.Data());
-   x2line = TString::Format("%s*%s", x2.Data(), retlunit.Data());
-   y1line = TString::Format("%s*%s", y1.Data(), retlunit.Data());
-   y2line = TString::Format("%s*%s", y2.Data(), retlunit.Data());
-   zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
+   x1line = TString::Format("(%s)*%s", x1.Data(), retlunit.Data());
+   x2line = TString::Format("(%s)*%s", x2.Data(), retlunit.Data());
+   y1line = TString::Format("(%s)*%s", y1.Data(), retlunit.Data());
+   y2line = TString::Format("(%s)*%s", y2.Data(), retlunit.Data());
+   zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
 
    TGeoTrd2* trd = new TGeoTrd2(NameShort(name),
                                 Evaluate(x1line) / 2,
@@ -2608,15 +2608,15 @@ XMLNodePointer_t TGDMLParse::Polycone(TXMLEngine* gdml, XMLNodePointer_t node, X
 
             if (tempattr == "rmin") {
                rmin = gdml->GetAttrValue(attr);
-               rminline = TString::Format("%s*%s", rmin.Data(), retlunit.Data());
+               rminline = TString::Format("(%s)*%s", rmin.Data(), retlunit.Data());
                table[planeno][0] = Evaluate(rminline);
             } else if (tempattr == "rmax") {
                rmax = gdml->GetAttrValue(attr);
-               rmaxline = TString::Format("%s*%s", rmax.Data(), retlunit.Data());
+               rmaxline = TString::Format("(%s)*%s", rmax.Data(), retlunit.Data());
                table[planeno][1] = Evaluate(rmaxline);
             } else if (tempattr == "z") {
                z = gdml->GetAttrValue(attr);
-               zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
+               zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
                table[planeno][2] = Evaluate(zline);
             }
             attr = gdml->GetNextAttr(attr);
@@ -2629,8 +2629,8 @@ XMLNodePointer_t TGDMLParse::Polycone(TXMLEngine* gdml, XMLNodePointer_t node, X
    TString startphiline = "";
    TString deltaphiline = "";
 
-   startphiline = TString::Format("%s*%s", startphi.Data(), retaunit.Data());
-   deltaphiline = TString::Format("%s*%s", deltaphi.Data(), retaunit.Data());
+   startphiline = TString::Format("(%s)*%s", startphi.Data(), retaunit.Data());
+   deltaphiline = TString::Format("(%s)*%s", deltaphi.Data(), retaunit.Data());
 
    TGeoPcon* poly = new TGeoPcon(NameShort(name),
                                  Evaluate(startphiline),
@@ -2740,15 +2740,15 @@ XMLNodePointer_t TGDMLParse::Polyhedra(TXMLEngine* gdml, XMLNodePointer_t node,
 
             if (tempattr == "rmin") {
                rmin = gdml->GetAttrValue(attr);
-               rminline = TString::Format("%s*%s", rmin.Data(), retlunit.Data());
+               rminline = TString::Format("(%s)*%s", rmin.Data(), retlunit.Data());
                table[planeno][0] = Evaluate(rminline);
             } else if (tempattr == "rmax") {
                rmax = gdml->GetAttrValue(attr);
-               rmaxline = TString::Format("%s*%s", rmax.Data(), retlunit.Data());
+               rmaxline = TString::Format("(%s)*%s", rmax.Data(), retlunit.Data());
                table[planeno][1] = Evaluate(rmaxline);
             } else if (tempattr == "z") {
                z = gdml->GetAttrValue(attr);
-               zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
+               zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
                table[planeno][2] = Evaluate(zline);
             }
 
@@ -2763,8 +2763,8 @@ XMLNodePointer_t TGDMLParse::Polyhedra(TXMLEngine* gdml, XMLNodePointer_t node,
    TString deltaphiline = "";
    TString numsidesline = "";
 
-   startphiline = TString::Format("%s*%s", startphi.Data(), retaunit.Data());
-   deltaphiline = TString::Format("%s*%s", deltaphi.Data(), retaunit.Data());
+   startphiline = TString::Format("(%s)*%s", startphi.Data(), retaunit.Data());
+   deltaphiline = TString::Format("(%s)*%s", deltaphi.Data(), retaunit.Data());
    numsidesline = TString::Format("%s", numsides.Data());
 
    TGeoPgon* polyg = new TGeoPgon(NameShort(name),
@@ -2852,12 +2852,12 @@ XMLNodePointer_t TGDMLParse::Sphere(TXMLEngine* gdml, XMLNodePointer_t node, XML
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   rminline = TString::Format("%s*%s", rmin.Data(), retlunit.Data());
-   rmaxline = TString::Format("%s*%s", rmax.Data(), retlunit.Data());
-   startphiline = TString::Format("%s*%s", startphi.Data(), retaunit.Data());
-   deltaphiline = TString::Format("(%s*%s) + %s", deltaphi.Data(), retaunit.Data(), startphiline.Data());
-   startthetaline = TString::Format("%s*%s", starttheta.Data(), retaunit.Data());
-   deltathetaline = TString::Format("(%s*%s) + %s", deltatheta.Data(), retaunit.Data(), startthetaline.Data());
+   rminline = TString::Format("(%s)*%s", rmin.Data(), retlunit.Data());
+   rmaxline = TString::Format("(%s)*%s", rmax.Data(), retlunit.Data());
+   startphiline = TString::Format("(%s)*%s", startphi.Data(), retaunit.Data());
+   deltaphiline = TString::Format("((%s)*%s) + %s", deltaphi.Data(), retaunit.Data(), startphiline.Data());
+   startthetaline = TString::Format("(%s)*%s", starttheta.Data(), retaunit.Data());
+   deltathetaline = TString::Format("((%s)*%s) + %s", deltatheta.Data(), retaunit.Data(), startthetaline.Data());
 
    TGeoSphere* sphere = new TGeoSphere(NameShort(name),
                                        Evaluate(rminline),
@@ -2933,11 +2933,11 @@ XMLNodePointer_t TGDMLParse::Torus(TXMLEngine* gdml, XMLNodePointer_t node, XMLA
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   rminline = TString::Format("%s*%s", rmin.Data(), retlunit.Data());
-   rmaxline = TString::Format("%s*%s", rmax.Data(), retlunit.Data());
-   rtorline = TString::Format("%s*%s", rtor.Data(), retlunit.Data());
-   startphiline = TString::Format("%s*%s", startphi.Data(), retaunit.Data());
-   deltaphiline = TString::Format("%s*%s", deltaphi.Data(), retaunit.Data());
+   rminline = TString::Format("(%s)*%s", rmin.Data(), retlunit.Data());
+   rmaxline = TString::Format("(%s)*%s", rmax.Data(), retlunit.Data());
+   rtorline = TString::Format("(%s)*%s", rtor.Data(), retlunit.Data());
+   startphiline = TString::Format("(%s)*%s", startphi.Data(), retaunit.Data());
+   deltaphiline = TString::Format("(%s)*%s", deltaphi.Data(), retaunit.Data());
 
 
    TGeoTorus* torus = new TGeoTorus(NameShort(name), Evaluate(rtorline),
@@ -3011,11 +3011,11 @@ XMLNodePointer_t TGDMLParse::Hype(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   rminline = TString::Format("%s*%s", rmin.Data(), retlunit.Data());
-   rmaxline = TString::Format("%s*%s", rmax.Data(), retlunit.Data());
-   zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
-   instline = TString::Format("%s*%s", inst.Data(), retaunit.Data());
-   outstline = TString::Format("%s*%s", outst.Data(), retaunit.Data());
+   rminline = TString::Format("(%s)*%s", rmin.Data(), retlunit.Data());
+   rmaxline = TString::Format("(%s)*%s", rmax.Data(), retlunit.Data());
+   zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
+   instline = TString::Format("(%s)*%s", inst.Data(), retaunit.Data());
+   outstline = TString::Format("(%s)*%s", outst.Data(), retaunit.Data());
 
 
    TGeoHype* hype = new TGeoHype(NameShort(name),
@@ -3095,12 +3095,12 @@ XMLNodePointer_t TGDMLParse::Para(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   xline = TString::Format("%s*%s", x.Data(), retlunit.Data());
-   yline = TString::Format("%s*%s", y.Data(), retlunit.Data());
-   zline = TString::Format("%s*%s", z.Data(), retlunit.Data());
-   philine = TString::Format("%s*%s", phi.Data(), retaunit.Data());
-   alphaline = TString::Format("%s*%s", alpha.Data(), retaunit.Data());
-   thetaline = TString::Format("%s*%s", theta.Data(), retaunit.Data());
+   xline = TString::Format("(%s)*%s", x.Data(), retlunit.Data());
+   yline = TString::Format("(%s)*%s", y.Data(), retlunit.Data());
+   zline = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
+   philine = TString::Format("(%s)*%s", phi.Data(), retaunit.Data());
+   alphaline = TString::Format("(%s)*%s", alpha.Data(), retaunit.Data());
+   thetaline = TString::Format("(%s)*%s", theta.Data(), retaunit.Data());
 
 
    TGeoPara* para = new TGeoPara(NameShort(name),
@@ -3206,18 +3206,18 @@ XMLNodePointer_t TGDMLParse::TwistTrap(TXMLEngine* gdml, XMLNodePointer_t node,
    retlunit = GetScale(lunit);
    retaunit = GetScale(aunit);
 
-   x1line = TString::Format("%s*%s", x1.Data(), retlunit.Data());
-   x2line = TString::Format("%s*%s", x2.Data(), retlunit.Data());
-   x3line = TString::Format("%s*%s", x3.Data(), retlunit.Data());
-   x4line = TString::Format("%s*%s", x4.Data(), retlunit.Data());
-   y1line = TString::Format("%s*%s", y1.Data(), retlunit.Data());
-   y2line = TString::Format("%s*%s", y2.Data(), retlunit.Data());
-   zline  = TString::Format("%s*%s", z.Data(), retlunit.Data());
-   philine = TString::Format("%s*%s", phi.Data(), retaunit.Data());
-   thetaline = TString::Format("%s*%s", theta.Data(), retaunit.Data());
-   alpha1line = TString::Format("%s*%s", alpha1.Data(), retaunit.Data());
-   alpha2line = TString::Format("%s*%s", alpha2.Data(), retaunit.Data());
-   twistline = TString::Format("%s*%s", twist.Data(), retaunit.Data());
+   x1line = TString::Format("(%s)*%s", x1.Data(), retlunit.Data());
+   x2line = TString::Format("(%s)*%s", x2.Data(), retlunit.Data());
+   x3line = TString::Format("(%s)*%s", x3.Data(), retlunit.Data());
+   x4line = TString::Format("(%s)*%s", x4.Data(), retlunit.Data());
+   y1line = TString::Format("(%s)*%s", y1.Data(), retlunit.Data());
+   y2line = TString::Format("(%s)*%s", y2.Data(), retlunit.Data());
+   zline  = TString::Format("(%s)*%s", z.Data(), retlunit.Data());
+   philine = TString::Format("(%s)*%s", phi.Data(), retaunit.Data());
+   thetaline = TString::Format("(%s)*%s", theta.Data(), retaunit.Data());
+   alpha1line = TString::Format("(%s)*%s", alpha1.Data(), retaunit.Data());
+   alpha2line = TString::Format("(%s)*%s", alpha2.Data(), retaunit.Data());
+   twistline = TString::Format("(%s)*%s", twist.Data(), retaunit.Data());
 
 
    TGeoGtra* twtrap = new TGeoGtra(NameShort(name), Evaluate(zline) / 2,
@@ -3287,9 +3287,9 @@ XMLNodePointer_t TGDMLParse::ElTube(TXMLEngine* gdml, XMLNodePointer_t node, XML
 
    retunit = GetScale(lunit);
 
-   xline = TString::Format("%s*%s", xpos.Data(), retunit.Data());
-   yline = TString::Format("%s*%s", ypos.Data(), retunit.Data());
-   zline = TString::Format("%s*%s", zpos.Data(), retunit.Data());
+   xline = TString::Format("(%s)*%s", xpos.Data(), retunit.Data());
+   yline = TString::Format("(%s)*%s", ypos.Data(), retunit.Data());
+   zline = TString::Format("(%s)*%s", zpos.Data(), retunit.Data());
 
    TGeoEltu* eltu = new TGeoEltu(NameShort(name), Evaluate(xline),
                                  Evaluate(yline),
@@ -3339,7 +3339,7 @@ XMLNodePointer_t TGDMLParse::Orb(TXMLEngine* gdml, XMLNodePointer_t node, XMLAtt
 
    retunit = GetScale(lunit);
 
-   rline = TString::Format("%s*%s", r.Data(), retunit.Data());
+   rline = TString::Format("(%s)*%s", r.Data(), retunit.Data());
 
    TGeoSphere* orb = new TGeoSphere(NameShort(name), 0, Evaluate(rline), 0, 180, 0, 360);
 
@@ -3441,11 +3441,11 @@ XMLNodePointer_t TGDMLParse::Xtru(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
 
             if (tempattr == "x") {
                x = gdml->GetAttrValue(attr);
-               xline = TString::Format("%s*%s", x.Data(), retlunit.Data());
+               xline = TString::Format("(%s)*%s", x.Data(), retlunit.Data());
                vertx[vert] = Evaluate(xline);
             } else if (tempattr == "y") {
                y = gdml->GetAttrValue(attr);
-               yline = TString::Format("%s*%s", y.Data(), retlunit.Data());
+               yline = TString::Format("(%s)*%s", y.Data(), retlunit.Data());
                verty[vert] = Evaluate(yline);
             }
 
@@ -3471,15 +3471,15 @@ XMLNodePointer_t TGDMLParse::Xtru(TXMLEngine* gdml, XMLNodePointer_t node, XMLAt
                section[sect][0] = Evaluate(zorder);
             } else if (tempattr == "zPosition") {
                zpos = gdml->GetAttrValue(attr);
-               zposline = TString::Format("%s*%s", zpos.Data(), retlunit.Data());
+               zposline = TString::Format("(%s)*%s", zpos.Data(), retlunit.Data());
                section[sect][1] = Evaluate(zposline);
             } else if (tempattr == "xOffset") {
                xoff = gdml->GetAttrValue(attr);
-               xoffline = TString::Format("%s*%s", xoff.Data(), retlunit.Data());
+               xoffline = TString::Format("(%s)*%s", xoff.Data(), retlunit.Data());
                section[sect][2] = Evaluate(xoffline);
             } else if (tempattr == "yOffset") {
                yoff = gdml->GetAttrValue(attr);
-               yoffline = TString::Format("%s*%s", yoff.Data(), retlunit.Data());
+               yoffline = TString::Format("(%s)*%s", yoff.Data(), retlunit.Data());
                section[sect][3] = Evaluate(yoffline);
             } else if (tempattr == "scalingFactor") {
                scale = gdml->GetAttrValue(attr);
diff --git a/geom/geom/inc/TGeoArb8.h b/geom/geom/inc/TGeoArb8.h
index 38eb9b7..0ed751d 100644
--- a/geom/geom/inc/TGeoArb8.h
+++ b/geom/geom/inc/TGeoArb8.h
@@ -68,20 +68,24 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
    void                  ComputeTwist();
-   virtual Bool_t        Contains(Double_t *point) const;     
-   Double_t              DistToPlane(Double_t *point, Double_t *dir, Int_t ipl, Bool_t in) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Bool_t        Contains(const Double_t *point) const;     
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   Double_t              DistToPlane(const Double_t *point, const Double_t *dir, Int_t ipl, Bool_t in) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const;
    virtual void          GetBoundingCylinder(Double_t *param) const;
    virtual Int_t         GetByteCount() const {return 100;}
-   Double_t              GetClosestEdge(Double_t *point, Double_t *vert, Int_t &isegment) const;
+   Double_t              GetClosestEdge(const Double_t *point, Double_t *vert, Int_t &isegment) const;
    virtual Bool_t        GetPointsOnFacet(Int_t /*index*/, Int_t /*npoints*/, Double_t * /*array*/) const;
    Double_t              GetDz() const {return fDz;}
    virtual Int_t         GetFittingBox(const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz) const;
@@ -90,12 +94,13 @@ public:
    Double_t             *GetVertices() {return &fXY[0][0];}
    Double_t              GetTwist(Int_t iseg) const;
    virtual Bool_t        IsCylType() const {return kFALSE;}
-   static Bool_t         IsSamePoint(Double_t *p1, Double_t *p2) {return (TMath::Abs(p1[0]-p2[0])<1.E-16 && TMath::Abs(p1[1]-p2[1])<1.E-16)?kTRUE:kFALSE;}
+   static Bool_t         IsSamePoint(const Double_t *p1, const Double_t *p2) {return (TMath::Abs(p1[0]-p2[0])<1.E-16 && TMath::Abs(p1[1]-p2[1])<1.E-16)?kTRUE:kFALSE;}
    static Bool_t         InsidePolygon(Double_t x, Double_t y, Double_t *pts);
    virtual void          InspectShape() const;
    Bool_t                IsTwisted() const {return (fTwist==0)?kFALSE:kTRUE;}
-   Double_t              SafetyToFace(Double_t *point, Int_t iseg, Bool_t in) const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   Double_t              SafetyToFace(const Double_t *point, Int_t iseg, Bool_t in) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetPlaneVertices(Double_t zpl, Double_t *vertices) const;
    virtual void          SetVertex(Int_t vnum, Double_t x, Double_t y);
@@ -150,10 +155,12 @@ public:
             Double_t tl2, Double_t alpha2);
    // destructor
    virtual ~TGeoTrap();
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    Double_t              GetTheta() const {return fTheta;}
@@ -168,7 +175,8 @@ public:
    Double_t              GetAlpha2() const   {return fAlpha2;}
    virtual TGeoShape    *GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const;
    virtual void          SetDimensions(Double_t *param);
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
 
    ClassDef(TGeoTrap, 1)         // G3 TRAP shape
@@ -205,13 +213,16 @@ public:
             Double_t tl2, Double_t alpha2);
    // destructor
    virtual ~TGeoGtra();
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoShape    *GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const;
    Double_t              GetTwistAngle() const {return fTwistAngle;}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SetDimensions(Double_t *param);
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
  
diff --git a/geom/geom/inc/TGeoBBox.h b/geom/geom/inc/TGeoBBox.h
index d98529d..ec20e53 100644
--- a/geom/geom/inc/TGeoBBox.h
+++ b/geom/geom/inc/TGeoBBox.h
@@ -48,17 +48,21 @@ public:
    static  Bool_t        AreOverlapping(const TGeoBBox *box1, const TGeoMatrix *mat1, const TGeoBBox *box2, const TGeoMatrix *mat2);
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    static  Bool_t        Contains(const Double_t *point, Double_t dx, Double_t dy, Double_t dz, const Double_t *origin);
-   virtual Bool_t        CouldBeCrossed(Double_t *point, Double_t *dir) const;
+   virtual Bool_t        CouldBeCrossed(const Double_t *point, const Double_t *dir) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    static  Double_t      DistFromInside(const Double_t *point,const Double_t *dir, 
                                    Double_t dx, Double_t dy, Double_t dz, const Double_t *origin, Double_t stepmax=TGeoShape::Big());
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    static  Double_t      DistFromOutside(const Double_t *point,const Double_t *dir, 
                                    Double_t dx, Double_t dy, Double_t dz, const Double_t *origin, Double_t stepmax=TGeoShape::Big());
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
@@ -84,7 +88,8 @@ public:
    virtual Bool_t        IsValidBox() const {return ((fDX<0)||(fDY<0)||(fDZ<0))?kFALSE:kTRUE;}
    virtual Bool_t        IsNullBox() const {return ((fDX<1.E-16)&&(fDY<1.E-16)&&(fDZ<1.E-16))?kTRUE:kFALSE;}
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetBoxDimensions(Double_t dx, Double_t dy, Double_t dz, Double_t *origin=0);
    virtual void          SetDimensions(Double_t *param);
diff --git a/geom/geom/inc/TGeoBoolNode.h b/geom/geom/inc/TGeoBoolNode.h
index e32a608..e4e40d7 100644
--- a/geom/geom/inc/TGeoBoolNode.h
+++ b/geom/geom/inc/TGeoBoolNode.h
@@ -74,12 +74,12 @@ public:
    virtual ~TGeoBoolNode();
    // methods
    virtual void      ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin) = 0;
-   virtual void      ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm) = 0;
-   virtual Bool_t    Contains(Double_t *point) const         = 0;
+   virtual void      ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) = 0;
+   virtual Bool_t    Contains(const Double_t *point) const         = 0;
    virtual Int_t     DistanceToPrimitive(Int_t px, Int_t py) = 0;
-   virtual Double_t  DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const = 0;
-   virtual Double_t  DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const = 0;
    virtual EGeoBoolType GetBooleanOperator() const = 0;
    virtual Int_t     GetNpoints() = 0;
@@ -91,7 +91,7 @@ public:
    virtual void      Paint(Option_t *option);
    void              RegisterMatrices();
    Bool_t            ReplaceMatrix(TGeoMatrix *mat, TGeoMatrix *newmat);
-   virtual Double_t  Safety(Double_t *point, Bool_t in=kTRUE) const = 0;
+   virtual Double_t  Safety(const Double_t *point, Bool_t in=kTRUE) const = 0;
    virtual void      SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void      SetPoints(Double_t *points) const;
    virtual void      SetPoints(Float_t *points)  const;
@@ -119,16 +119,16 @@ public:
    virtual ~TGeoUnion();
    // methods
    virtual void      ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin);
-   virtual void      ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t    Contains(Double_t *point) const;
+   virtual void      ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual Bool_t    Contains(const Double_t *point) const;
    virtual Int_t     DistanceToPrimitive(Int_t px, Int_t py);
-   virtual Double_t  DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const;
-   virtual Double_t  DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const;
    virtual EGeoBoolType GetBooleanOperator() const {return kGeoUnion;}
    virtual Int_t     GetNpoints();
-   virtual Double_t  Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t  Safety(const Double_t *point, Bool_t in=kTRUE) const;
    virtual void      SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void      Sizeof3D() const;
 
@@ -158,16 +158,16 @@ public:
    virtual ~TGeoIntersection();
    // methods
    virtual void      ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin);
-   virtual void      ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t    Contains(Double_t *point) const;
+   virtual void      ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual Bool_t    Contains(const Double_t *point) const;
    virtual Int_t     DistanceToPrimitive(Int_t px, Int_t py);
-   virtual Double_t  DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const;
-   virtual Double_t  DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const;
    virtual EGeoBoolType GetBooleanOperator() const {return kGeoIntersection;}
    virtual Int_t     GetNpoints();
-   virtual Double_t  Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t  Safety(const Double_t *point, Bool_t in=kTRUE) const;
    virtual void      SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void      Sizeof3D() const;
 
@@ -196,16 +196,16 @@ public:
    virtual ~TGeoSubtraction();
    // methods
    virtual void      ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin);
-   virtual void      ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t    Contains(Double_t *point) const;
+   virtual void      ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual Bool_t    Contains(const Double_t *point) const;
    virtual Int_t     DistanceToPrimitive(Int_t px, Int_t py);
-   virtual Double_t  DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const;
-   virtual Double_t  DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1,
+   virtual Double_t  DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1,
                                Double_t step=0, Double_t *safe=0) const;
    virtual EGeoBoolType GetBooleanOperator() const {return kGeoSubtraction;}
    virtual Int_t     GetNpoints();
-   virtual Double_t  Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t  Safety(const Double_t *point, Bool_t in=kTRUE) const;
    virtual void      SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void      Sizeof3D() const;
 
diff --git a/geom/geom/inc/TGeoCompositeShape.h b/geom/geom/inc/TGeoCompositeShape.h
index 6c2b55a..825af8a 100644
--- a/geom/geom/inc/TGeoCompositeShape.h
+++ b/geom/geom/inc/TGeoCompositeShape.h
@@ -51,13 +51,17 @@ public:
    virtual void          ClearThreadData() const;
    virtual void          CreateThreadData(Int_t nthreads);
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    TGeoBoolNode         *GetBoolNode() const {return fNode;}
@@ -72,7 +76,8 @@ public:
    void                  MakeNode(const char *expression);
    virtual Bool_t        PaintComposite(Option_t *option = "") const;
    void                  RegisterYourself();
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetDimensions(Double_t * /*param*/) {;}
    virtual void          SetPoints(Double_t *points) const;
diff --git a/geom/geom/inc/TGeoCone.h b/geom/geom/inc/TGeoCone.h
index c85e390..54831a0 100644
--- a/geom/geom/inc/TGeoCone.h
+++ b/geom/geom/inc/TGeoCone.h
@@ -53,20 +53,24 @@ public:
    virtual Double_t      Capacity() const;
    static  Double_t      Capacity(Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2);
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   static  void          ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   static  void          ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                                         Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   static  void          DistToCone(Double_t *point, Double_t *dir, Double_t dz, Double_t r1, Double_t r2, Double_t &b, Double_t &delta);   
-   static  Double_t      DistFromInsideS(Double_t *point, Double_t *dir, Double_t dz,
+   static  void          DistToCone(const Double_t *point, const Double_t *dir, Double_t dz, Double_t r1, Double_t r2, Double_t &b, Double_t &delta);   
+   static  Double_t      DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz,
                                     Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   static  Double_t      DistFromOutsideS(Double_t *point, Double_t *dir, Double_t dz,
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   static  Double_t      DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz,
                                    Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2);
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
 
@@ -88,8 +92,9 @@ public:
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kTRUE;}
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
-   static  Double_t      SafetyS(Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
+   static  Double_t      SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
                                  Double_t rmin2, Double_t rmax2, Int_t skipz=0);
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetConeDimensions(Double_t dz, Double_t rmin1, Double_t rmax1,
@@ -134,23 +139,26 @@ public:
    virtual Double_t      Capacity() const;
    static  Double_t      Capacity(Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2);
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   static  void          ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   static  void          ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                                         Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2,
                                         Double_t c1, Double_t s1, Double_t c2, Double_t s2);
-   virtual Bool_t        Contains(Double_t *point) const;
-
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   static  Double_t      DistToCons(Double_t *point, Double_t *dir, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Double_t phi1, Double_t phi2);
-   static  Double_t      DistFromInsideS(Double_t *point, Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, 
+   static  Double_t      DistToCons(const Double_t *point, const Double_t *dir, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Double_t phi1, Double_t phi2);
+   static  Double_t      DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, 
                                    Double_t rmin2, Double_t rmax2, Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   static  Double_t      DistFromOutsideS(Double_t *point, Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   static  Double_t      DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, 
                                    Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi);   
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const;
@@ -165,8 +173,9 @@ public:
    Double_t              GetPhi2() const {return fPhi2;}
    virtual void          InspectShape() const;
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
-   static  Double_t      SafetyS(Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
+   static  Double_t      SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
                                  Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2, Int_t skipz=0);
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetConsDimensions(Double_t dz, Double_t rmin1, Double_t rmax1,
diff --git a/geom/geom/inc/TGeoEltu.h b/geom/geom/inc/TGeoEltu.h
index e6539c2..ad2efa8 100644
--- a/geom/geom/inc/TGeoEltu.h
+++ b/geom/geom/inc/TGeoEltu.h
@@ -38,13 +38,17 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetA() const    {return fRmin;}
@@ -57,7 +61,8 @@ public:
    virtual Bool_t        GetPointsOnSegments(Int_t /*npoints*/, Double_t * /*array*/) const {return kFALSE;}
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kTRUE;}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetEltuDimensions(Double_t a, Double_t b, Double_t dz);
    virtual void          SetDimensions(Double_t *param);
diff --git a/geom/geom/inc/TGeoExtension.h b/geom/geom/inc/TGeoExtension.h
index fdf1af7..e68d572 100644
--- a/geom/geom/inc/TGeoExtension.h
+++ b/geom/geom/inc/TGeoExtension.h
@@ -37,7 +37,7 @@ protected:
 public:
    // Method called whenever requiring a pointer to the extension
    // Equivalent to new()
-   virtual TGeoExtension *Grab() const = 0;
+   virtual TGeoExtension *Grab() = 0;
    // Method called always when the pointer to the extension is not needed
    // Equivalent to delete()
    virtual void           Release() const = 0;
@@ -61,7 +61,7 @@ public:
    TGeoRCExtension() : TGeoExtension(), fRC(0), fUserObject(0) {fRC++;}
    TGeoRCExtension(TObject *obj) : TGeoExtension(), fRC(0), fUserObject(obj) {fRC++;}
 
-   TGeoExtension       *Grab() const                {fRC++; return (TGeoExtension*)this;}
+   TGeoExtension       *Grab()                      {fRC++; return this;}
    void                 Release() const             {assert(fRC > 0); fRC--; if (fRC ==0) delete this;}
 
    void                 SetUserObject(TObject *obj) {fUserObject = obj;}
@@ -70,8 +70,8 @@ public:
    
 private:
    // Copy constructor and assignment not allowed
-   TGeoRCExtension(const TGeoRCExtension &) {}
-   TGeoRCExtension &operator =(const TGeoRCExtension &) {return *this;}
+   TGeoRCExtension(const TGeoRCExtension &); // Not implemented
+   TGeoRCExtension &operator =(const TGeoRCExtension &); // Not implemented
    mutable Int_t        fRC;           // Reference counter
    TObject             *fUserObject;   // Attached user object
 
diff --git a/geom/geom/inc/TGeoHalfSpace.h b/geom/geom/inc/TGeoHalfSpace.h
index 7738baf..a615de4 100644
--- a/geom/geom/inc/TGeoHalfSpace.h
+++ b/geom/geom/inc/TGeoHalfSpace.h
@@ -42,13 +42,17 @@ public:
    // methods
    virtual Double_t      Capacity() const {return 0.;}
    virtual void          ComputeBBox() {;}
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t     *GetPoint()    {return fP;}
@@ -59,7 +63,8 @@ public:
    virtual Int_t         GetNmeshVertices() const {return 0;}
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kFALSE;}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetDimensions(Double_t *param);
    virtual void          SetPoints(Double_t * /*points*/) const {;}
diff --git a/geom/geom/inc/TGeoHype.h b/geom/geom/inc/TGeoHype.h
index b6c9b9e..5f3b311 100644
--- a/geom/geom/inc/TGeoHype.h
+++ b/geom/geom/inc/TGeoHype.h
@@ -73,13 +73,17 @@ public:
 
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   Int_t                 DistToHype(Double_t *point, Double_t *dir, Double_t *s, Bool_t inner, Bool_t in) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   Int_t                 DistToHype(const Double_t *point, const Double_t *dir, Double_t *s, Bool_t inner, Bool_t in) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
@@ -100,8 +104,9 @@ public:
    virtual Bool_t        IsCylType() const {return kTRUE;}
    virtual TBuffer3D    *MakeBuffer3D() const;
    //virtual void          Paint(Option_t *option);
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
-   Double_t              SafetyToHype(Double_t *point, Bool_t inner, Bool_t in) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
+   Double_t              SafetyToHype(const Double_t *point, Bool_t inner, Bool_t in) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetHypeDimensions(Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz);
    virtual void          SetDimensions(Double_t *param);
diff --git a/geom/geom/inc/TGeoManager.h b/geom/geom/inc/TGeoManager.h
index e162331..58b5080 100644
--- a/geom/geom/inc/TGeoManager.h
+++ b/geom/geom/inc/TGeoManager.h
@@ -76,6 +76,7 @@ private :
    Bool_t                fLoopVolumes;      //! flag volume lists loop
    Bool_t                fStreamVoxels;     // flag to allow voxelization I/O
    Bool_t                fIsGeomReading;    //! flag set when reading geometry
+   Bool_t                fIsGeomCleaning;   //! flag to notify that the manager is being destructed
    Bool_t                fPhiCut;           // flag for phi cuts
    Bool_t                fTimeCut;          // time cut for tracks
    Bool_t                fDrawExtra;        //! flag that the list of physical nodes has to be drawn
@@ -450,6 +451,7 @@ public:
    static TGeoManager    *Import(const char *filename, const char *name="", Option_t *option="");
    static Bool_t          IsLocked();
    Bool_t                 IsStreamingVoxels() const {return fStreamVoxels;}
+   Bool_t                 IsCleaning() const {return fIsGeomCleaning;}
 
    //--- list getters
    TObjArray             *GetListOfNodes()              {return fNodes;}
diff --git a/geom/geom/inc/TGeoMatrix.h b/geom/geom/inc/TGeoMatrix.h
index ccf00ad..513fb92 100644
--- a/geom/geom/inc/TGeoMatrix.h
+++ b/geom/geom/inc/TGeoMatrix.h
@@ -256,6 +256,7 @@ public :
    TGeoScale(const char *name, Double_t sx, Double_t sy, Double_t sz);
    virtual ~TGeoScale();
    
+   TGeoScale& operator=(const TGeoScale &other);   
    virtual TGeoMatrix&  Inverse() const;
    void                 SetScale(Double_t sx, Double_t sy, Double_t sz);
    virtual void         LocalToMaster(const Double_t *local, Double_t *master) const;
diff --git a/geom/geom/inc/TGeoNode.h b/geom/geom/inc/TGeoNode.h
index ef0a156..7328de4 100644
--- a/geom/geom/inc/TGeoNode.h
+++ b/geom/geom/inc/TGeoNode.h
@@ -116,7 +116,7 @@ public:
    Bool_t            MayOverlap(Int_t iother) const;
 
    virtual TGeoNode *MakeCopyNode() const {return 0;}
-   Double_t          Safety(Double_t *point, Bool_t in=kTRUE) const;
+   Double_t          Safety(const Double_t *point, Bool_t in=kTRUE) const;
    void              SaveAttributes(std::ostream &out);
    void              SetCurrentPoint(Double_t x, Double_t y, Double_t z) {fVolume->SetCurrentPoint(x,y,z);}// *MENU*
    void              SetVolume(TGeoVolume *volume)       {fVolume = volume;}
@@ -211,7 +211,7 @@ public:
    virtual TGeoPatternFinder *GetFinder() const {return fFinder;}
    virtual TGeoMatrix *GetMatrix() const {cd(); return fFinder->GetMatrix();}
    virtual TGeoNode *MakeCopyNode() const;
-   void              SetFinder(const TGeoPatternFinder *finder) {fFinder = (TGeoPatternFinder*)finder;}
+   void              SetFinder(TGeoPatternFinder *finder) {fFinder = finder;}
 
    ClassDef(TGeoNodeOffset, 1)      // a geometry node with just an offset
 };
diff --git a/geom/geom/inc/TGeoPara.h b/geom/geom/inc/TGeoPara.h
index 033708e..2e9911f 100644
--- a/geom/geom/inc/TGeoPara.h
+++ b/geom/geom/inc/TGeoPara.h
@@ -53,12 +53,16 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const;
@@ -78,7 +82,8 @@ public:
    Double_t              GetTyz() const {return fTyz;}
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kFALSE;}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetDimensions(Double_t *param);
    virtual void          SetPoints(Double_t *points) const;
diff --git a/geom/geom/inc/TGeoParaboloid.h b/geom/geom/inc/TGeoParaboloid.h
index da1e43b..2867ef6 100644
--- a/geom/geom/inc/TGeoParaboloid.h
+++ b/geom/geom/inc/TGeoParaboloid.h
@@ -53,14 +53,18 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   Double_t              DistToParaboloid(Double_t *point, Double_t *dir, Bool_t in) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   Double_t              DistToParaboloid(const Double_t *point, const Double_t *dir, Bool_t in) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual const TBuffer3D &GetBuffer3D(Int_t reqSections, Bool_t localFrame) const;
@@ -76,7 +80,8 @@ public:
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kTRUE;}
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetParaboloidDimensions(Double_t rlo, Double_t rhi, Double_t dz);
    virtual void          SetDimensions(Double_t *param);
diff --git a/geom/geom/inc/TGeoPatternFinder.h b/geom/geom/inc/TGeoPatternFinder.h
index 4f6af3e..c771aef 100644
--- a/geom/geom/inc/TGeoPatternFinder.h
+++ b/geom/geom/inc/TGeoPatternFinder.h
@@ -41,6 +41,9 @@ public:
 
       ThreadData_t();
       ~ThreadData_t();
+   private:
+      ThreadData_t(const ThreadData_t&); // Not implemented
+      ThreadData_t& operator=(const ThreadData_t&); // Not implemented
    };
    ThreadData_t& GetThreadData()   const;
    void          ClearThreadData() const;
diff --git a/geom/geom/inc/TGeoPcon.h b/geom/geom/inc/TGeoPcon.h
index 9957d40..b087f9d 100644
--- a/geom/geom/inc/TGeoPcon.h
+++ b/geom/geom/inc/TGeoPcon.h
@@ -62,14 +62,18 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual void          DefineSection(Int_t snum, Double_t z, Double_t rmin, Double_t rmax);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   Double_t              DistToSegZ(Double_t *point, Double_t *dir, Int_t &iz) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   Double_t              DistToSegZ(const Double_t *point, const Double_t *dir, Int_t &iz) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
@@ -100,8 +104,9 @@ public:
    Double_t             &Rmin(Int_t ipl) {return fRmin[ipl];}
    Double_t             &Rmax(Int_t ipl) {return fRmax[ipl];}
    Double_t             &Z(Int_t ipl) {return fZ[ipl];}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
-   Double_t              SafetyToSegment(Double_t *point, Int_t ipl, Bool_t in=kTRUE, Double_t safmin=TGeoShape::Big()) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
+   Double_t              SafetyToSegment(const Double_t *point, Int_t ipl, Bool_t in=kTRUE, Double_t safmin=TGeoShape::Big()) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetDimensions(Double_t *param);
    virtual void          SetPoints(Double_t *points) const;
diff --git a/geom/geom/inc/TGeoPgon.h b/geom/geom/inc/TGeoPgon.h
index 1ea7536..05136dc 100644
--- a/geom/geom/inc/TGeoPgon.h
+++ b/geom/geom/inc/TGeoPgon.h
@@ -37,15 +37,15 @@ protected:
    mutable Int_t        *fIntBuffer; //![fNedges+4] temporary int buffer array
    mutable Double_t     *fDblBuffer; //![fNedges+4] temporary double buffer array
    
-   Int_t                 GetPhiCrossList(Double_t *point, Double_t *dir, Int_t istart, Double_t *sphi, Int_t *iphi, Double_t stepmax=TGeoShape::Big()) const;
-   Bool_t                IsCrossingSlice(Double_t *point, Double_t *dir, Int_t iphi, Double_t sstart, Int_t &ipl, Double_t &snext, Double_t stepmax) const;
-   void                  LocatePhi(Double_t *point, Int_t &ipsec) const;
+   Int_t                 GetPhiCrossList(const Double_t *point, const Double_t *dir, Int_t istart, Double_t *sphi, Int_t *iphi, Double_t stepmax=TGeoShape::Big()) const;
+   Bool_t                IsCrossingSlice(const Double_t *point, const Double_t *dir, Int_t iphi, Double_t sstart, Int_t &ipl, Double_t &snext, Double_t stepmax) const;
+   void                  LocatePhi(const Double_t *point, Int_t &ipsec) const;
    Double_t              Rpg(Double_t z, Int_t ipl, Bool_t inner, Double_t &a, Double_t &b) const;
-   Double_t              Rproj(Double_t z,Double_t *point, Double_t *dir, Double_t cphi, Double_t sphi, Double_t &a, Double_t &b) const; 
-   Bool_t                SliceCrossing(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
-   Bool_t                SliceCrossingIn(Double_t *point, Double_t *dir, Int_t ipl, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
-   Bool_t                SliceCrossingZ(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
-   Bool_t                SliceCrossingInZ(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
+   Double_t              Rproj(Double_t z,const Double_t *point, const Double_t *dir, Double_t cphi, Double_t sphi, Double_t &a, Double_t &b) const; 
+   Bool_t                SliceCrossing(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
+   Bool_t                SliceCrossingIn(const Double_t *point, const Double_t *dir, Int_t ipl, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
+   Bool_t                SliceCrossingZ(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
+   Bool_t                SliceCrossingInZ(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *sphi, Double_t &snext, Double_t stepmax) const;
 
 public:
    // constructors
@@ -58,12 +58,16 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
@@ -78,8 +82,9 @@ public:
    virtual Bool_t        GetPointsOnSegments(Int_t npoints, Double_t *array) const {return TGeoBBox::GetPointsOnSegments(npoints,array);}
    virtual void          InspectShape() const;
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
-   Double_t              SafetyToSegment(Double_t *point, Int_t ipl, Int_t iphi, Bool_t in, Double_t safphi, Double_t safmin=TGeoShape::Big()) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
+   Double_t              SafetyToSegment(const Double_t *point, Int_t ipl, Int_t iphi, Bool_t in, Double_t safphi, Double_t safmin=TGeoShape::Big()) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetDimensions(Double_t *param);
    void                  SetNedges(Int_t ne) {if (ne>2) fNedges=ne;}
diff --git a/geom/geom/inc/TGeoPolygon.h b/geom/geom/inc/TGeoPolygon.h
index 993c903..1f18284 100644
--- a/geom/geom/inc/TGeoPolygon.h
+++ b/geom/geom/inc/TGeoPolygon.h
@@ -48,7 +48,7 @@ protected :
 private:
    void                ConvexCheck(); // force convexity checking
    Bool_t              IsSegConvex(Int_t i1, Int_t i2=-1) const;
-   Bool_t              IsRightSided(Double_t *point, Int_t ind1, Int_t ind2) const;
+   Bool_t              IsRightSided(const Double_t *point, Int_t ind1, Int_t ind2) const;
    void                OutscribedConvex();
 public:
    // constructors
@@ -58,7 +58,7 @@ public:
    virtual ~TGeoPolygon();
    // methods
    Double_t            Area() const;
-   Bool_t              Contains(Double_t *point) const;
+   Bool_t              Contains(const Double_t *point) const;
    virtual void        Draw(Option_t *option="");
    void                FinishPolygon();
    Int_t               GetNvert() const {return fNvert;}
@@ -71,7 +71,7 @@ public:
    Bool_t              IsConvex() const {return TObject::TestBit(kGeoConvex);}
    Bool_t              IsFinished() const {return TObject::TestBit(kGeoFinishPolygon);}
    Bool_t              IsIllegalCheck() const;
-   Double_t            Safety(Double_t *point, Int_t &isegment) const;
+   Double_t            Safety(const Double_t *point, Int_t &isegment) const;
    void                SetConvex(Bool_t flag=kTRUE) {TObject::SetBit(kGeoConvex,flag);}
    void                SetXY(Double_t *x, Double_t *y);   
    void                SetNextIndex(Int_t index=-1);
diff --git a/geom/geom/inc/TGeoScaledShape.h b/geom/geom/inc/TGeoScaledShape.h
index 1b59e85..765df6e 100644
--- a/geom/geom/inc/TGeoScaledShape.h
+++ b/geom/geom/inc/TGeoScaledShape.h
@@ -43,13 +43,17 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual TGeoShape    *GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const;
@@ -64,7 +68,8 @@ public:
    virtual Bool_t        IsReflected() const;
    virtual TBuffer3D    *MakeBuffer3D() const;
    static  TGeoShape    *MakeScaledShape(const char *name, TGeoShape *shape, TGeoScale *scale);
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetScale(TGeoScale *scale) {fScale = scale;}
    virtual void          SetPoints(Double_t *points) const;
diff --git a/geom/geom/inc/TGeoShape.h b/geom/geom/inc/TGeoShape.h
index d5666d6..d959512 100644
--- a/geom/geom/inc/TGeoShape.h
+++ b/geom/geom/inc/TGeoShape.h
@@ -104,15 +104,19 @@ public:
    virtual Double_t      Capacity() const                        = 0;
    void                  CheckShape(Int_t testNo, Int_t nsamples=10000, Option_t *option="");
    virtual void          ComputeBBox()                           = 0;
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm) = 0;
-   virtual Bool_t        Contains(Double_t *point) const         = 0;
-   virtual Bool_t        CouldBeCrossed(Double_t *point, Double_t *dir) const = 0;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm) = 0;
+   virtual void          ComputeNormal_v(const Double_t *, const Double_t *, Double_t *, Int_t) {}
+   virtual Bool_t        Contains(const Double_t *point) const         = 0;
+   virtual void          Contains_v(const Double_t *, Bool_t *, Int_t) const {}
+   virtual Bool_t        CouldBeCrossed(const Double_t *point, const Double_t *dir) const = 0;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py) = 0;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const = 0;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *, const Double_t *, Double_t *, Int_t, Double_t *) const {}
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const = 0;
-   static Double_t       DistToPhiMin(Double_t *point, Double_t *dir, Double_t s1, Double_t c1, Double_t s2, Double_t c2, 
+   virtual void          DistFromOutside_v(const Double_t *, const Double_t *, Double_t *, Int_t, Double_t *) const {}
+   static Double_t       DistToPhiMin(const Double_t *point, const Double_t *dir, Double_t s1, Double_t c1, Double_t s2, Double_t c2, 
                                       Double_t sm, Double_t cm, Bool_t in=kTRUE);
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step)   = 0; 
@@ -134,21 +138,22 @@ public:
    virtual Bool_t        IsAssembly() const {return kFALSE;}
    virtual Bool_t        IsComposite() const {return kFALSE;}
    virtual Bool_t        IsCylType() const = 0;
-   static  Bool_t        IsCloseToPhi(Double_t epsil, Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2);
-   static  Bool_t        IsCrossingSemiplane(Double_t *point, Double_t *dir, Double_t cphi, Double_t sphi, Double_t &snext, Double_t &rxy);
+   static  Bool_t        IsCloseToPhi(Double_t epsil, const Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2);
+   static  Bool_t        IsCrossingSemiplane(const Double_t *point, const Double_t *dir, Double_t cphi, Double_t sphi, Double_t &snext, Double_t &rxy);
    static  Bool_t        IsSameWithinTolerance(Double_t a, Double_t b);
    static  Bool_t        IsSegCrossing(Double_t x1, Double_t y1, Double_t x2, Double_t y2,Double_t x3, Double_t y3,Double_t x4, Double_t y4);
-   static  Bool_t        IsInPhiRange(Double_t *point, Double_t phi1, Double_t phi2);
+   static  Bool_t        IsInPhiRange(const Double_t *point, Double_t phi1, Double_t phi2);
    virtual Bool_t        IsReflected() const {return kFALSE;}
    Bool_t                IsRunTimeShape() const {return TestShapeBit(kGeoRunTimeShape);}
    Bool_t                IsValid() const {return !TestShapeBit(kGeoInvalidShape);}
    virtual Bool_t        IsValidBox() const                      = 0; 
    virtual void          InspectShape() const                    = 0;
    virtual TBuffer3D    *MakeBuffer3D() const {return 0;}
-   static void           NormalPhi(Double_t *point, Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2);
+   static void           NormalPhi(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2);
    virtual void          Paint(Option_t *option="");
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const = 0;
-   static  Double_t      SafetyPhi(Double_t *point, Bool_t in, Double_t phi1, Double_t phi2);
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const = 0;
+   virtual void          Safety_v(const Double_t *, const Bool_t *, Double_t *, Int_t) const {}
+   static  Double_t      SafetyPhi(const Double_t *point, Bool_t in, Double_t phi1, Double_t phi2);
    static  Double_t      SafetySeg(Double_t r, Double_t z, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Bool_t outer);
    virtual void          SetDimensions(Double_t *param)          = 0;
    void                  SetId(Int_t id) {fShapeId = id;}
diff --git a/geom/geom/inc/TGeoShapeAssembly.h b/geom/geom/inc/TGeoShapeAssembly.h
index 18eaf27..2eef13a 100644
--- a/geom/geom/inc/TGeoShapeAssembly.h
+++ b/geom/geom/inc/TGeoShapeAssembly.h
@@ -41,13 +41,17 @@ public:
    virtual ~TGeoShapeAssembly();
    // methods
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual TGeoShape    *GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const;
@@ -58,7 +62,8 @@ public:
    virtual Bool_t        IsCylType() const {return kFALSE;}
    void                  NeedsBBoxRecompute() {fBBoxOK = kFALSE;}
    void                  RecomputeBoxLast();
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetPoints(Double_t *points) const;
    virtual void          SetPoints(Float_t *points) const;
diff --git a/geom/geom/inc/TGeoSphere.h b/geom/geom/inc/TGeoSphere.h
index 2f86a0f..b5a6303 100644
--- a/geom/geom/inc/TGeoSphere.h
+++ b/geom/geom/inc/TGeoSphere.h
@@ -53,14 +53,18 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   Double_t              DistToSphere(Double_t *point, Double_t *dir, Double_t rsph, Bool_t check=kTRUE, Bool_t firstcross=kTRUE) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   Double_t              DistToSphere(const Double_t *point, const Double_t *dir, Double_t rsph, Bool_t check=kTRUE, Bool_t firstcross=kTRUE) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual const char   *GetAxisName(Int_t iaxis) const;
@@ -82,15 +86,17 @@ public:
    Double_t              GetPhi2() const {return fPhi2;}
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kFALSE;}
-   Int_t                 IsOnBoundary(Double_t *point) const;
-   Bool_t                IsPointInside(Double_t *point, Bool_t checkR=kTRUE, Bool_t checkTh=kTRUE, Bool_t checkPh=kTRUE) const;
+   Int_t                 IsOnBoundary(const Double_t *point) const;
+   Bool_t                IsPointInside(const Double_t *point, Bool_t checkR=kTRUE, Bool_t checkTh=kTRUE, Bool_t checkPh=kTRUE) const;
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetSphDimensions(Double_t rmin, Double_t rmax, Double_t theta1,
                                        Double_t theta2, Double_t phi1, Double_t phi2);
    virtual void          SetNumberOfDivisions(Int_t p);
    virtual void          SetDimensions(Double_t *param);
+   void                  SetDimensions(Double_t *param, Int_t nparam);
    virtual void          SetPoints(Double_t *points) const;
    virtual void          SetPoints(Float_t *points) const;
    virtual void          SetSegsAndPols(TBuffer3D &buff) const;
diff --git a/geom/geom/inc/TGeoTorus.h b/geom/geom/inc/TGeoTorus.h
index eb5e109..84dc818 100644
--- a/geom/geom/inc/TGeoTorus.h
+++ b/geom/geom/inc/TGeoTorus.h
@@ -40,10 +40,10 @@ protected :
 
 public:
    virtual Double_t      Capacity() const;
-   Double_t              Daxis(Double_t *pt, Double_t *dir, Double_t t) const;
-   Double_t              DDaxis(Double_t *pt, Double_t *dir, Double_t t) const;
-   Double_t              DDDaxis(Double_t *pt, Double_t *dir, Double_t t) const;
-   Double_t              ToBoundary(Double_t *pt, Double_t *dir, Double_t r, Bool_t in) const;
+   Double_t              Daxis(const Double_t *pt, const Double_t *dir, Double_t t) const;
+   Double_t              DDaxis(const Double_t *pt, const Double_t *dir, Double_t t) const;
+   Double_t              DDDaxis(const Double_t *pt, const Double_t *dir, Double_t t) const;
+   Double_t              ToBoundary(const Double_t *pt, const Double_t *dir, Double_t r, Bool_t in) const;
    Int_t                 SolveCubic(Double_t a, Double_t b, Double_t c, Double_t *x) const;
    Int_t                 SolveQuartic(Double_t a, Double_t b, Double_t c, Double_t d, Double_t *x) const;
 public:
@@ -57,12 +57,16 @@ public:
    // methods
 
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
@@ -83,7 +87,8 @@ public:
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kTRUE;}
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetTorusDimensions(Double_t r, Double_t rmin, Double_t rmax, Double_t phi1, Double_t dphi);
    virtual void          SetDimensions(Double_t *param);
diff --git a/geom/geom/inc/TGeoTrd1.h b/geom/geom/inc/TGeoTrd1.h
index c333f38..ec8c172 100644
--- a/geom/geom/inc/TGeoTrd1.h
+++ b/geom/geom/inc/TGeoTrd1.h
@@ -48,12 +48,16 @@ public:
 
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const;
@@ -65,11 +69,12 @@ public:
    Double_t              GetDz() const  {return fDz;}
    virtual Int_t         GetFittingBox(const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz) const;
    virtual TGeoShape    *GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const;
-   void                  GetVisibleCorner(Double_t *point, Double_t *vertex, Double_t *normals) const;
-   void                  GetOppositeCorner(Double_t *point, Int_t inorm, Double_t *vertex, Double_t *normals) const;
+   void                  GetVisibleCorner(const Double_t *point, Double_t *vertex, Double_t *normals) const;
+   void                  GetOppositeCorner(const Double_t *point, Int_t inorm, Double_t *vertex, Double_t *normals) const;
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kFALSE;}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetDimensions(Double_t *param);
    virtual void          SetPoints(Double_t *points) const;
diff --git a/geom/geom/inc/TGeoTrd2.h b/geom/geom/inc/TGeoTrd2.h
index 1f5ae90..d88cbd5 100644
--- a/geom/geom/inc/TGeoTrd2.h
+++ b/geom/geom/inc/TGeoTrd2.h
@@ -48,13 +48,17 @@ public:
    // methods
 
    virtual Double_t      Capacity() const;
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const;
@@ -67,11 +71,12 @@ public:
    Double_t              GetDz() const  {return fDz;}
    virtual Int_t         GetFittingBox(const TGeoBBox *parambox, TGeoMatrix *mat, Double_t &dx, Double_t &dy, Double_t &dz) const;
    virtual TGeoShape    *GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix *mat) const;
-   void                  GetVisibleCorner(Double_t *point, Double_t *vertex, Double_t *normals) const;
-   void                  GetOppositeCorner(Double_t *point, Int_t inorm, Double_t *vertex, Double_t *normals) const;
+   void                  GetVisibleCorner(const Double_t *point, Double_t *vertex, Double_t *normals) const;
+   void                  GetOppositeCorner(const Double_t *point, Int_t inorm, Double_t *vertex, Double_t *normals) const;
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kFALSE;}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    virtual void          SetDimensions(Double_t *param);
    virtual void          SetPoints(Double_t *points) const;
diff --git a/geom/geom/inc/TGeoTube.h b/geom/geom/inc/TGeoTube.h
index a49a95a..19e3e64 100644
--- a/geom/geom/inc/TGeoTube.h
+++ b/geom/geom/inc/TGeoTube.h
@@ -47,16 +47,20 @@ public:
    virtual Double_t      Capacity() const;
    static  Double_t      Capacity(Double_t rmin, Double_t rmax, Double_t dz);
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   static  void          ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   static  void          ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                                         Double_t rmin, Double_t rmax, Double_t dz);
-   virtual Bool_t        Contains(Double_t *point) const;
-   static  Double_t      DistFromInsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   static  Double_t      DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz);
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   static  Double_t      DistFromOutsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz);
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   static  Double_t      DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz);
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    static  void          DistToTube(Double_t rsq, Double_t nsq, Double_t rdotn, Double_t radius, Double_t &b, Double_t &delta);
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
@@ -77,8 +81,9 @@ public:
    virtual void          InspectShape() const;
    virtual Bool_t        IsCylType() const {return kTRUE;}
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
-   static  Double_t      SafetyS(Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz=0);
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
+   static  Double_t      SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz=0);
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetTubeDimensions(Double_t rmin, Double_t rmax, Double_t dz);
    virtual void          SetDimensions(Double_t *param);
@@ -121,20 +126,24 @@ public:
    virtual Double_t      Capacity() const;
    static  Double_t      Capacity(Double_t rmin, Double_t rmax, Double_t dz, Double_t phi1, Double_t phi2);
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   static  void          ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   static  void          ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                                         Double_t rmin, Double_t rmax, Double_t dz,
                                         Double_t c1, Double_t s1, Double_t c2, Double_t s2);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
-   static  Double_t      DistFromInsideS(Double_t *point, Double_t *dir,Double_t rmin, Double_t rmax, Double_t dz, 
+   static  Double_t      DistFromInsideS(const Double_t *point, const Double_t *dir,Double_t rmin, Double_t rmax, Double_t dz, 
                                     Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   static  Double_t      DistFromOutsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz,
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   static  Double_t      DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz,
                                    Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi);
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const;
@@ -149,8 +158,9 @@ public:
    Double_t              GetPhi2() const {return fPhi2;}
    virtual void          InspectShape() const;
    virtual TBuffer3D    *MakeBuffer3D() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
-   static  Double_t      SafetyS(Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, 
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
+   static  Double_t      SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, 
                                  Double_t phi1, Double_t phi2, Int_t skipz=0);
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetTubsDimensions(Double_t rmin, Double_t rmax, Double_t dz,
@@ -195,12 +205,16 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual TGeoVolume   *Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv, 
                                 Double_t start, Double_t step);
    virtual Double_t      GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const;
@@ -214,7 +228,8 @@ public:
    const Double_t       *GetNhigh() const {return &fNhigh[0];}
    Double_t              GetZcoord(Double_t xc, Double_t yc, Double_t zc) const;
    virtual void          InspectShape() const;
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetCtubDimensions(Double_t rmin, Double_t rmax, Double_t dz,
                                        Double_t phi1, Double_t phi2, Double_t lx, Double_t ly, Double_t lz,
diff --git a/geom/geom/inc/TGeoVolume.h b/geom/geom/inc/TGeoVolume.h
index c6e48fa..c7091f1 100644
--- a/geom/geom/inc/TGeoVolume.h
+++ b/geom/geom/inc/TGeoVolume.h
@@ -119,7 +119,7 @@ public:
    void            CheckOverlaps(Double_t ovlp=0.1, Option_t *option="") const; // *MENU*
    void            CheckShape(Int_t testNo, Int_t nsamples=10000, Option_t *option=""); // *MENU*
    Int_t           CountNodes(Int_t nlevels=1000, Int_t option=0);
-   Bool_t          Contains(Double_t *point) const {return fShape->Contains(point);}
+   Bool_t          Contains(const Double_t *point) const {return fShape->Contains(point);}
    virtual Bool_t  IsAssembly() const;
    virtual Bool_t  IsFolder() const;
    Bool_t          IsRunTime() const {return fShape->IsRunTimeShape();}
@@ -281,7 +281,7 @@ public:
    virtual void    AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option="");       // most general case
    virtual void    AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option="");
    virtual TGeoVolume *Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed=0, Option_t *option="");
-   TGeoShape      *GetLastShape() const {return GetVolume(fVolumes->GetEntriesFast()-1)->GetShape();}
+   TGeoShape      *GetLastShape() const;
    Int_t           GetNvolumes() const {return fVolumes->GetEntriesFast();}
    Int_t           GetAxis() const {return fNdiv;}
    Int_t           GetNdiv() const {return fNdiv;}
diff --git a/geom/geom/inc/TGeoVoxelFinder.h b/geom/geom/inc/TGeoVoxelFinder.h
index 32c5595..8c370c0 100644
--- a/geom/geom/inc/TGeoVoxelFinder.h
+++ b/geom/geom/inc/TGeoVoxelFinder.h
@@ -76,7 +76,7 @@ protected:
    Int_t              *GetExtraX(Int_t islice, Bool_t left, Int_t &nextra) const;
    Int_t              *GetExtraY(Int_t islice, Bool_t left, Int_t &nextra) const;
    Int_t              *GetExtraZ(Int_t islice, Bool_t left, Int_t &nextra) const;
-   Bool_t              GetIndices(Double_t *point, TGeoStateInfo &td);
+   Bool_t              GetIndices(const Double_t *point, TGeoStateInfo &td);
    Int_t               GetPriority(Int_t iaxis) const {return fPriority[iaxis];}
    Int_t               GetNcandidates( TGeoStateInfo &td) const;
    Int_t              *GetValidExtra(Int_t *list, Int_t &ncheck, TGeoStateInfo &td);
@@ -101,22 +101,22 @@ public :
    TGeoVoxelFinder();
    TGeoVoxelFinder(TGeoVolume *vol);
    virtual ~TGeoVoxelFinder();
-   void                DaughterToMother(Int_t id, Double_t *local, Double_t *master) const;
+   void                DaughterToMother(Int_t id, const Double_t *local, Double_t *master) const;
    virtual Double_t    Efficiency();
-   virtual Int_t      *GetCheckList(Double_t *point, Int_t &nelem, TGeoStateInfo &td);
+   virtual Int_t      *GetCheckList(const Double_t *point, Int_t &nelem, TGeoStateInfo &td);
    Int_t              *GetCheckList(Int_t &nelem, TGeoStateInfo &td) const;
-   virtual Int_t      *GetNextCandidates(Double_t *point, Int_t &ncheck, TGeoStateInfo &td); 
+   virtual Int_t      *GetNextCandidates(const Double_t *point, Int_t &ncheck, TGeoStateInfo &td); 
    virtual void        FindOverlaps(Int_t inode) const;
    Bool_t              IsInvalid() const {return TObject::TestBit(kGeoInvalidVoxels);}
    Bool_t              NeedRebuild() const {return TObject::TestBit(kGeoRebuildVoxels);}
    Double_t           *GetBoxes() const {return fBoxes;}
-   Bool_t              IsSafeVoxel(Double_t *point, Int_t inode, Double_t minsafe) const;
+   Bool_t              IsSafeVoxel(const Double_t *point, Int_t inode, Double_t minsafe) const;
    virtual void        Print(Option_t *option="") const;
-   void                PrintVoxelLimits(Double_t *point) const;
+   void                PrintVoxelLimits(const Double_t *point) const;
    void                SetInvalid(Bool_t flag=kTRUE) {TObject::SetBit(kGeoInvalidVoxels, flag);}
    void                SetNeedRebuild(Bool_t flag=kTRUE) {TObject::SetBit(kGeoRebuildVoxels, flag);}
-   virtual Int_t      *GetNextVoxel(Double_t *point, Double_t *dir, Int_t &ncheck, TGeoStateInfo &td);
-   virtual void        SortCrossedVoxels(Double_t *point, Double_t *dir, TGeoStateInfo &td);
+   virtual Int_t      *GetNextVoxel(const Double_t *point, const Double_t *dir, Int_t &ncheck, TGeoStateInfo &td);
+   virtual void        SortCrossedVoxels(const Double_t *point, const Double_t *dir, TGeoStateInfo &td);
    virtual void        Voxelize(Option_t *option="");
 
    ClassDef(TGeoVoxelFinder, 4)                // voxel finder class
diff --git a/geom/geom/inc/TGeoXtru.h b/geom/geom/inc/TGeoXtru.h
index b6cbc8e..a677caf 100644
--- a/geom/geom/inc/TGeoXtru.h
+++ b/geom/geom/inc/TGeoXtru.h
@@ -64,11 +64,11 @@ protected:
    TGeoXtru& operator=(const TGeoXtru&);
 
    // methods
-   Double_t              DistToPlane(Double_t *point, Double_t *dir, Int_t iz, Int_t ivert, Double_t stepmax, Bool_t in) const;
+   Double_t              DistToPlane(const Double_t *point, const Double_t *dir, Int_t iz, Int_t ivert, Double_t stepmax, Bool_t in) const;
    void                  GetPlaneVertices(Int_t iz, Int_t ivert, Double_t *vert) const;
    void                  GetPlaneNormal(const Double_t *vert, Double_t *norm) const;
-   Bool_t                IsPointInsidePlane(Double_t *point, Double_t *vert, Double_t *norm) const;
-   Double_t              SafetyToSector(Double_t *point, Int_t iz, Double_t safmin, Bool_t in);
+   Bool_t                IsPointInsidePlane(const Double_t *point, Double_t *vert, Double_t *norm) const;
+   Double_t              SafetyToSector(const Double_t *point, Int_t iz, Double_t safmin, Bool_t in);
    void                  SetIz(Int_t iz);
    void                  SetSeg(Int_t iseg);
 
@@ -82,14 +82,18 @@ public:
    // methods
    virtual Double_t      Capacity() const;
    virtual void          ComputeBBox();
-   virtual void          ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm);
-   virtual Bool_t        Contains(Double_t *point) const;
+   virtual void          ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm);
+   virtual void          ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize);
+   virtual Bool_t        Contains(const Double_t *point) const;
+   virtual void          Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const;
    Bool_t                DefinePolygon(Int_t nvert, const Double_t *xv, const Double_t *yv);
    virtual void          DefineSection(Int_t snum, Double_t z, Double_t x0=0., Double_t y0=0., Double_t scale=1.);
-   virtual Double_t      DistFromInside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual Double_t      DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
-   virtual Double_t      DistFromOutside(Double_t *point, Double_t *dir, Int_t iact=1, 
+   virtual void          DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
+   virtual Double_t      DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, 
                                    Double_t step=TGeoShape::Big(), Double_t *safe=0) const;
+   virtual void          DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t *step) const;
    virtual Int_t         DistancetoPrimitive(Int_t px, Int_t py);
    void                  DrawPolygon(Option_t *option="");
    virtual const TBuffer3D &GetBuffer3D(Int_t reqSections, Bool_t localFrame) const;
@@ -109,7 +113,8 @@ public:
    virtual void          InspectShape() const;
    virtual TBuffer3D    *MakeBuffer3D() const;
    Double_t             &Z(Int_t ipl) {return fZ[ipl];}
-   virtual Double_t      Safety(Double_t *point, Bool_t in=kTRUE) const;
+   virtual Double_t      Safety(const Double_t *point, Bool_t in=kTRUE) const;
+   virtual void          Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const;
    virtual void          SavePrimitive(std::ostream &out, Option_t *option = "");
    void                  SetCurrentZ(Double_t z, Int_t iz);
    void                  SetCurrentVertices(Double_t x0, Double_t y0, Double_t scale);
diff --git a/geom/geom/inc/TVirtualGeoTrack.h b/geom/geom/inc/TVirtualGeoTrack.h
index 08ceed9..cebc3ea 100644
--- a/geom/geom/inc/TVirtualGeoTrack.h
+++ b/geom/geom/inc/TVirtualGeoTrack.h
@@ -63,7 +63,7 @@ public:
    virtual void        AddPoint(Double_t x, Double_t y, Double_t z, Double_t t) = 0;
    virtual TVirtualGeoTrack *FindTrackWithId(Int_t id) const;
    Int_t               GetId() const         {return fId;}
-   virtual Int_t       GetDaughterId(Int_t index) const {return GetDaughter(index)->GetId();}
+   virtual Int_t       GetDaughterId(Int_t index) const;
    TVirtualGeoTrack   *GetDaughter(Int_t index) const {return (TVirtualGeoTrack*)fTracks->At(index);}
    TVirtualGeoTrack   *GetMother() const {return fParent;}
    TObject            *GetMotherParticle() const {return (fParent)?fParent->GetParticle():0;}
diff --git a/geom/geom/src/TGeoArb8.cxx b/geom/geom/src/TGeoArb8.cxx
index 82f60cb..640eb26 100644
--- a/geom/geom/src/TGeoArb8.cxx
+++ b/geom/geom/src/TGeoArb8.cxx
@@ -339,7 +339,7 @@ Double_t TGeoArb8::GetTwist(Int_t iseg) const
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoArb8::GetClosestEdge(Double_t *point, Double_t *vert, Int_t &isegment) const
+Double_t TGeoArb8::GetClosestEdge(const Double_t *point, Double_t *vert, Int_t &isegment) const
 {
 // Get index of the edge of the quadrilater represented by vert closest to point.
 // If [P1,P2] is the closest segment and P is the point, the function returns the fraction of the
@@ -407,7 +407,7 @@ Double_t TGeoArb8::GetClosestEdge(Double_t *point, Double_t *vert, Int_t &isegme
 }   
 
 //_____________________________________________________________________________
-void TGeoArb8::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoArb8::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    Double_t safc;
@@ -471,7 +471,7 @@ void TGeoArb8::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoArb8::Contains(Double_t *point) const
+Bool_t TGeoArb8::Contains(const Double_t *point) const
 {
 // Test if point is inside this shape.
    // first check Z range
@@ -490,7 +490,7 @@ Bool_t TGeoArb8::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoArb8::DistToPlane(Double_t *point, Double_t *dir, Int_t ipl, Bool_t in) const 
+Double_t TGeoArb8::DistToPlane(const Double_t *point, const Double_t *dir, Int_t ipl, Bool_t in) const 
 {
 // Computes distance to plane ipl :
 // ipl=0 : points 0,4,1,5
@@ -614,7 +614,7 @@ Double_t TGeoArb8::DistToPlane(Double_t *point, Double_t *dir, Int_t ipl, Bool_t
 }      
       
 //_____________________________________________________________________________
-Double_t TGeoArb8::DistFromOutside(Double_t *point, Double_t *dir, Int_t /*iact*/, Double_t step, Double_t * /*safe*/) const
+Double_t TGeoArb8::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t /*iact*/, Double_t step, Double_t * /*safe*/) const
 {
 // Computes distance from outside point to surface of the shape.
    Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
@@ -641,7 +641,7 @@ Double_t TGeoArb8::DistFromOutside(Double_t *point, Double_t *dir, Int_t /*iact*
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoArb8::DistFromInside(Double_t *point, Double_t *dir, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
+Double_t TGeoArb8::DistFromInside(const Double_t *point, const Double_t *dir, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
 {
 // Compute distance from inside point to surface of the shape.
    Int_t i;
@@ -977,7 +977,7 @@ void TGeoArb8::InspectShape() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoArb8::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoArb8::Safety(const Double_t *point, Bool_t in) const
 {
 // Computes the closest distance from given point to this shape.
    Double_t safz = fDz-TMath::Abs(point[2]);
@@ -1053,7 +1053,7 @@ Double_t TGeoArb8::Safety(Double_t *point, Bool_t in) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoArb8::SafetyToFace(Double_t *point, Int_t iseg, Bool_t in) const
+Double_t TGeoArb8::SafetyToFace(const Double_t *point, Int_t iseg, Bool_t in) const
 {
 // Estimate safety to lateral plane defined by segment iseg in range [0,3]
 // Might be negative: plane seen only from inside.
@@ -1203,6 +1203,47 @@ void TGeoArb8::Streamer(TBuffer &R__b)
    }
 }   
 
+//_____________________________________________________________________________
+void TGeoArb8::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoArb8::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoArb8::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoArb8::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoArb8::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
+
 ClassImp(TGeoTrap)
 
 //_____________________________________________________________________________
@@ -1314,7 +1355,7 @@ TGeoTrap::~TGeoTrap()
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrap::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTrap::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the trapezoid
    if (iact<3 && safe) {
@@ -1366,7 +1407,7 @@ Double_t TGeoTrap::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoTrap::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTrap::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the trapezoid
    if (iact<3 && safe) {
@@ -1565,7 +1606,7 @@ TGeoShape *TGeoTrap::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * /*mat*/
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrap::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoTrap::Safety(const Double_t *point, Bool_t in) const
 {
 // Computes the closest distance from given point to this shape.
    Double_t safe = TGeoShape::Big();
@@ -1689,6 +1730,29 @@ void TGeoTrap::SetDimensions(Double_t *param)
    else TGeoArb8::ComputeBBox();
 }   
 
+//_____________________________________________________________________________
+void TGeoTrap::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrap::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrap::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
+
 ClassImp(TGeoGtra)
 
 //_____________________________________________________________________________
@@ -1782,7 +1846,7 @@ TGeoGtra::~TGeoGtra()
 }
 
 //_____________________________________________________________________________
-Double_t TGeoGtra::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoGtra::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the shape.
    if (iact<3 && safe) {
@@ -1796,7 +1860,7 @@ Double_t TGeoGtra::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoGtra::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoGtra::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the shape.
    if (iact<3 && safe) {
@@ -1850,7 +1914,7 @@ TGeoShape *TGeoGtra::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * /*mat*/
 }
 
 //_____________________________________________________________________________
-Double_t TGeoGtra::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoGtra::Safety(const Double_t *point, Bool_t in) const
 {
 // Computes the closest distance from given point to this shape.
    return TGeoArb8::Safety(point,in);
@@ -1926,3 +1990,26 @@ void TGeoGtra::SetDimensions(Double_t *param)
        (fH2<0) || (fBl2<0) || (fTl2<0)) SetShapeBit(kGeoRunTimeShape);
    else TGeoArb8::ComputeBBox();
 }   
+
+//_____________________________________________________________________________
+void TGeoGtra::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoGtra::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoGtra::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoBBox.cxx b/geom/geom/src/TGeoBBox.cxx
index 35f7d9c..2f60c79 100644
--- a/geom/geom/src/TGeoBBox.cxx
+++ b/geom/geom/src/TGeoBBox.cxx
@@ -182,7 +182,7 @@ Double_t TGeoBBox::Capacity() const
 }
 
 //_____________________________________________________________________________
-void TGeoBBox::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoBBox::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Computes normal to closest surface from POINT. 
    memset(norm,0,3*sizeof(Double_t));
@@ -196,7 +196,7 @@ void TGeoBBox::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoBBox::CouldBeCrossed(Double_t *point, Double_t *dir) const
+Bool_t TGeoBBox::CouldBeCrossed(const Double_t *point, const Double_t *dir) const
 {
 // Decides fast if the bounding box could be crossed by a vector.
    Double_t mind = fDX;
@@ -279,7 +279,7 @@ void TGeoBBox::ComputeBBox()
 }   
 
 //_____________________________________________________________________________
-Bool_t TGeoBBox::Contains(Double_t *point) const
+Bool_t TGeoBBox::Contains(const Double_t *point) const
 {
 // Test if point is inside this shape.
    if (TMath::Abs(point[2]-fOrigin[2]) > fDZ) return kFALSE;
@@ -291,7 +291,8 @@ Bool_t TGeoBBox::Contains(Double_t *point) const
 //_____________________________________________________________________________
 Bool_t TGeoBBox::Contains(const Double_t *point, Double_t dx, Double_t dy, Double_t dz, const Double_t *origin)
 {
-// Test if point is inside this shape.
+// Static method to check if point[3] is located inside a box of having dx, dy, dz
+// as half-lengths.
    if (TMath::Abs(point[2]-origin[2]) > dz) return kFALSE;
    if (TMath::Abs(point[0]-origin[0]) > dx) return kFALSE;
    if (TMath::Abs(point[1]-origin[1]) > dy) return kFALSE;
@@ -299,7 +300,7 @@ Bool_t TGeoBBox::Contains(const Double_t *point, Double_t dx, Double_t dy, Doubl
 }
 
 //_____________________________________________________________________________
-Double_t TGeoBBox::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoBBox::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the box.
 // Boundary safe algorithm.
@@ -363,7 +364,7 @@ Double_t TGeoBBox::DistFromInside(const Double_t *point,const Double_t *dir,
 }
 
 //_____________________________________________________________________________
-Double_t TGeoBBox::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoBBox::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the box.
 // Boundary safe algorithm.
@@ -775,7 +776,7 @@ void TGeoBBox::SetSegsAndPols(TBuffer3D &buff) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoBBox::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoBBox::Safety(const Double_t *point, Bool_t in) const
 {
 // Computes the closest distance from given point to this shape.
 
@@ -960,3 +961,44 @@ void TGeoBBox::FillBuffer3D(TBuffer3D & buffer, Int_t reqSections, Bool_t localF
       buffer.SetSectionsValid(TBuffer3D::kBoundingBox);
    }
 }
+
+//_____________________________________________________________________________
+void TGeoBBox::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoBBox::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoBBox::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoBBox::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoBBox::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoBoolNode.cxx b/geom/geom/src/TGeoBoolNode.cxx
index a3450c9..858cd7f 100644
--- a/geom/geom/src/TGeoBoolNode.cxx
+++ b/geom/geom/src/TGeoBoolNode.cxx
@@ -114,6 +114,9 @@ void TGeoBoolNode::CreateThreadData(Int_t nthreads)
          fThreadData[tid] = new ThreadData_t;
       }
    }   
+   // Propagate to components
+   if (fLeft)  fLeft->CreateThreadData(nthreads);
+   if (fRight) fRight->CreateThreadData(nthreads);
    TThread::UnLock();
 }
 
@@ -479,7 +482,7 @@ void TGeoUnion::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *
 }
 
 //______________________________________________________________________________
-Bool_t TGeoUnion::Contains(Double_t *point) const
+Bool_t TGeoUnion::Contains(const Double_t *point) const
 {
 // Find if a union of two shapes contains a given point
    Double_t local[3];
@@ -492,7 +495,7 @@ Bool_t TGeoUnion::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-void TGeoUnion::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoUnion::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
    ThreadData_t& td = GetThreadData();
@@ -550,7 +553,7 @@ Int_t TGeoUnion::DistanceToPrimitive(Int_t /*px*/, Int_t /*py*/)
 }
 
 //______________________________________________________________________________
-Double_t TGeoUnion::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoUnion::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact,
                               Double_t step, Double_t *safe) const
 {
 // Computes distance from a given point inside the shape to its boundary.
@@ -662,7 +665,7 @@ Double_t TGeoUnion::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
 }
 
 //______________________________________________________________________________
-Double_t TGeoUnion::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoUnion::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact,
                               Double_t step, Double_t *safe) const
 {
 // Compute distance from a given outside point to the shape.
@@ -730,7 +733,7 @@ Int_t TGeoUnion::GetNpoints()
 }
 
 //______________________________________________________________________________
-Double_t TGeoUnion::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoUnion::Safety(const Double_t *point, Bool_t in) const
 {
 // Compute safety distance for a union node;
    Double_t local1[3], local2[3];
@@ -856,7 +859,7 @@ void TGeoSubtraction::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Doub
 }   
 
 //_____________________________________________________________________________
-void TGeoSubtraction::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoSubtraction::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
    ThreadData_t& td = GetThreadData();
@@ -905,7 +908,7 @@ void TGeoSubtraction::ComputeNormal(Double_t *point, Double_t *dir, Double_t *no
 }
 
 //______________________________________________________________________________
-Bool_t TGeoSubtraction::Contains(Double_t *point) const
+Bool_t TGeoSubtraction::Contains(const Double_t *point) const
 {
 // Find if a subtraction of two shapes contains a given point
    Double_t local[3];
@@ -925,7 +928,7 @@ Int_t TGeoSubtraction::DistanceToPrimitive(Int_t /*px*/, Int_t /*py*/)
 }
 
 //______________________________________________________________________________
-Double_t TGeoSubtraction::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoSubtraction::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact,
                               Double_t step, Double_t *safe) const
 {
 // Compute distance from a given point inside to the shape boundary.
@@ -955,7 +958,7 @@ Double_t TGeoSubtraction::DistFromInside(Double_t *point, Double_t *dir, Int_t i
 }   
 
 //______________________________________________________________________________
-Double_t TGeoSubtraction::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoSubtraction::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact,
                               Double_t step, Double_t *safe) const
 {
 // Compute distance from a given point outside to the shape.
@@ -1047,7 +1050,7 @@ Int_t TGeoSubtraction::GetNpoints()
 }
 
 //______________________________________________________________________________
-Double_t TGeoSubtraction::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoSubtraction::Safety(const Double_t *point, Bool_t in) const
 {
 // Compute safety distance for a union node;
    Double_t local1[3], local2[3];
@@ -1242,7 +1245,7 @@ void TGeoIntersection::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Dou
 }   
 
 //_____________________________________________________________________________
-void TGeoIntersection::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoIntersection::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
    ThreadData_t& td = GetThreadData();
@@ -1291,7 +1294,7 @@ void TGeoIntersection::ComputeNormal(Double_t *point, Double_t *dir, Double_t *n
 }
 
 //______________________________________________________________________________
-Bool_t TGeoIntersection::Contains(Double_t *point) const
+Bool_t TGeoIntersection::Contains(const Double_t *point) const
 {
 // Find if a intersection of two shapes contains a given point
    Double_t local[3];
@@ -1311,7 +1314,7 @@ Int_t TGeoIntersection::DistanceToPrimitive(Int_t /*px*/, Int_t /*py*/)
 }
 
 //______________________________________________________________________________
-Double_t TGeoIntersection::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoIntersection::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact,
                               Double_t step, Double_t *safe) const
 {
 // Compute distance from a given point inside to the shape boundary.
@@ -1341,7 +1344,7 @@ Double_t TGeoIntersection::DistFromInside(Double_t *point, Double_t *dir, Int_t
 }   
 
 //______________________________________________________________________________
-Double_t TGeoIntersection::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoIntersection::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact,
                               Double_t step, Double_t *safe) const
 {
 // Compute distance from a given point outside to the shape.
@@ -1457,7 +1460,7 @@ Int_t TGeoIntersection::GetNpoints()
 }
 
 //______________________________________________________________________________
-Double_t TGeoIntersection::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoIntersection::Safety(const Double_t *point, Bool_t in) const
 {
 // Compute safety distance for a union node;
    Double_t local1[3], local2[3];
diff --git a/geom/geom/src/TGeoBranchArray.cxx b/geom/geom/src/TGeoBranchArray.cxx
index 9c5863a..791585e 100644
--- a/geom/geom/src/TGeoBranchArray.cxx
+++ b/geom/geom/src/TGeoBranchArray.cxx
@@ -244,7 +244,6 @@ void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
    Int_t level = cache->GetLevel();
    if (!fMatrix) fMatrix = new TGeoHMatrix();
    fMatrix->CopyFrom(cache->GetCurrentMatrix());
-//   TThread::Lock();
    if (!fArray || level+1>fMaxLevel) {
       delete [] fArray; 
       fMaxLevel = level+1;
@@ -252,7 +251,6 @@ void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
    }
    fLevel = level;
    memcpy(fArray, branch, (fLevel+1)*sizeof(TGeoNode*));
-//   TThread::UnLock();
 }
 
 //______________________________________________________________________________
diff --git a/geom/geom/src/TGeoCache.cxx b/geom/geom/src/TGeoCache.cxx
index b249efa..e3a8bf1 100644
--- a/geom/geom/src/TGeoCache.cxx
+++ b/geom/geom/src/TGeoCache.cxx
@@ -141,7 +141,8 @@ void TGeoNodeCache::BuildIdArray()
 void TGeoNodeCache::BuildInfoBranch()
 {
 // Bulds info branch. Navigation is possible only after this step.
-   if (fInfoBranch && fInfoBranch[0]) return;
+   if (!fInfoBranch) fInfoBranch  = new TGeoStateInfo*[fGeoInfoStackSize];
+   else if (fInfoBranch[0]) return;
    for (Int_t i=0; i<fGeoInfoStackSize; i++) {
       fInfoBranch[i] = new TGeoStateInfo();
    }   
diff --git a/geom/geom/src/TGeoCompositeShape.cxx b/geom/geom/src/TGeoCompositeShape.cxx
index 76cb13e..588f4b8 100644
--- a/geom/geom/src/TGeoCompositeShape.cxx
+++ b/geom/geom/src/TGeoCompositeShape.cxx
@@ -263,14 +263,14 @@ void TGeoCompositeShape::ComputeBBox()
 }
 
 //_____________________________________________________________________________
-void TGeoCompositeShape::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoCompositeShape::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Computes normal vector in POINT to the composite shape.
    if (fNode) fNode->ComputeNormal(point,dir,norm);
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoCompositeShape::Contains(Double_t *point) const
+Bool_t TGeoCompositeShape::Contains(const Double_t *point) const
 {
 // Tests if point is inside the shape.
    if (fNode) return fNode->Contains(point);
@@ -286,7 +286,7 @@ Int_t TGeoCompositeShape::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCompositeShape::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoCompositeShape::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact,
                                       Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to this composite shape.
@@ -298,7 +298,7 @@ Double_t TGeoCompositeShape::DistFromOutside(Double_t *point, Double_t *dir, Int
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCompositeShape::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
+Double_t TGeoCompositeShape::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact,
                                       Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to outside of this composite shape.
@@ -453,7 +453,7 @@ void TGeoCompositeShape::RegisterYourself()
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCompositeShape::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoCompositeShape::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -501,3 +501,44 @@ Int_t TGeoCompositeShape::GetNmeshVertices() const
    if (!fNode) return 0;
    return fNode->GetNpoints();
 }
+
+//_____________________________________________________________________________
+void TGeoCompositeShape::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCompositeShape::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCompositeShape::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCompositeShape::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCompositeShape::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoCone.cxx b/geom/geom/src/TGeoCone.cxx
index 7f9e3ef..d5edc4c 100644
--- a/geom/geom/src/TGeoCone.cxx
+++ b/geom/geom/src/TGeoCone.cxx
@@ -162,7 +162,7 @@ void TGeoCone::ComputeBBox()
 }
 
 //_____________________________________________________________________________
-void TGeoCone::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoCone::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t safr,safe,phi;
@@ -204,7 +204,7 @@ void TGeoCone::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-void TGeoCone::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+void TGeoCone::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                               Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
 {
 // Compute normal to closest surface from POINT.
@@ -240,7 +240,7 @@ void TGeoCone::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoCone::Contains(Double_t *point) const
+Bool_t TGeoCone::Contains(const Double_t *point) const
 {
 // test if point is inside this cone
    if (TMath::Abs(point[2]) > fDz) return kFALSE;
@@ -252,7 +252,7 @@ Bool_t TGeoCone::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCone::DistFromInsideS(Double_t *point, Double_t *dir, Double_t dz,
+Double_t TGeoCone::DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz,
                               Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
 {
 // Compute distance from inside point to surface of the cone (static)
@@ -323,7 +323,7 @@ Double_t TGeoCone::DistFromInsideS(Double_t *point, Double_t *dir, Double_t dz,
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCone::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoCone::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the cone
 // Boundary safe algorithm.
@@ -338,7 +338,7 @@ Double_t TGeoCone::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCone::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t dz,
+Double_t TGeoCone::DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz,
                              Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
 {
 // Compute distance from outside point to surface of the tube
@@ -468,7 +468,7 @@ Double_t TGeoCone::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t dz,
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCone::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoCone::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the tube
    // compute safe radius
@@ -485,7 +485,7 @@ Double_t TGeoCone::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, D
 }
 
 //_____________________________________________________________________________
-void TGeoCone::DistToCone(Double_t *point, Double_t *dir, Double_t dz, Double_t r1, Double_t r2,
+void TGeoCone::DistToCone(const Double_t *point, const Double_t *dir, Double_t dz, Double_t r1, Double_t r2,
                               Double_t &b, Double_t &delta)
 {
    // Static method to compute distance to a conical surface with :
@@ -832,7 +832,7 @@ void TGeoCone::SetSegsAndPols(TBuffer3D &buffer) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCone::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoCone::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -846,7 +846,7 @@ Double_t TGeoCone::Safety(Double_t *point, Bool_t in) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCone::SafetyS(Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
+Double_t TGeoCone::SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
                            Double_t rmin2, Double_t rmax2, Int_t skipz)
 {
 // computes the closest distance from given point to this shape, according
@@ -1107,6 +1107,47 @@ const TBuffer3D & TGeoCone::GetBuffer3D(Int_t reqSections, Bool_t localFrame) co
    return buffer;
 }
 
+//_____________________________________________________________________________
+void TGeoCone::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCone::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCone::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCone::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCone::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
+
 ClassImp(TGeoConeSeg)
 
 //_____________________________________________________________________________
@@ -1225,7 +1266,7 @@ void TGeoConeSeg::ComputeBBox()
 }
 
 //_____________________________________________________________________________
-void TGeoConeSeg::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoConeSeg::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t saf[3];
@@ -1280,7 +1321,7 @@ void TGeoConeSeg::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-void TGeoConeSeg::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+void TGeoConeSeg::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                                  Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2,
                                  Double_t c1, Double_t s1, Double_t c2, Double_t s2)
 {
@@ -1326,7 +1367,7 @@ void TGeoConeSeg::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoConeSeg::Contains(Double_t *point) const
+Bool_t TGeoConeSeg::Contains(const Double_t *point) const
 {
 // test if point is inside this sphere
    if (!TGeoCone::Contains(point)) return kFALSE;
@@ -1342,7 +1383,7 @@ Bool_t TGeoConeSeg::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoConeSeg::DistToCons(Double_t *point, Double_t *dir, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Double_t phi1, Double_t phi2)
+Double_t TGeoConeSeg::DistToCons(const Double_t *point, const Double_t *dir, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Double_t phi1, Double_t phi2)
 {
    // Static method to compute distance to a conical surface with :
    // - r1, z1 - radius and Z position of lower base
@@ -1416,7 +1457,7 @@ Double_t TGeoConeSeg::DistToCons(Double_t *point, Double_t *dir, Double_t r1, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoConeSeg::DistFromInsideS(Double_t *point, Double_t *dir, Double_t dz, 
+Double_t TGeoConeSeg::DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t dz, 
                        Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, 
                        Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
 {
@@ -1465,7 +1506,7 @@ Double_t TGeoConeSeg::DistFromInsideS(Double_t *point, Double_t *dir, Double_t d
 }
 
 //_____________________________________________________________________________
-Double_t TGeoConeSeg::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoConeSeg::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the tube segment
    if (iact<3 && safe) {
@@ -1491,7 +1532,7 @@ Double_t TGeoConeSeg::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
 }
 
 //_____________________________________________________________________________
-Double_t TGeoConeSeg::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t dz, 
+Double_t TGeoConeSeg::DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t dz, 
                        Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, 
                        Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
 {
@@ -1765,7 +1806,7 @@ Double_t TGeoConeSeg::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t
 }
 
 //_____________________________________________________________________________
-Double_t TGeoConeSeg::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoConeSeg::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the tube
    // compute safe radius
@@ -2054,7 +2095,7 @@ void TGeoConeSeg::SetSegsAndPols(TBuffer3D &buffer) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoConeSeg::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoConeSeg::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -2068,7 +2109,7 @@ Double_t TGeoConeSeg::Safety(Double_t *point, Bool_t in) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoConeSeg::SafetyS(Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
+Double_t TGeoConeSeg::SafetyS(const Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
                               Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2, Int_t skipz)
 {
 // Static method to compute the closest distance from given point to this shape.
@@ -2323,3 +2364,44 @@ Bool_t TGeoConeSeg::GetPointsOnSegments(Int_t npoints, Double_t *array) const
    }
    return kTRUE;
 }                    
+
+//_____________________________________________________________________________
+void TGeoConeSeg::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoConeSeg::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoConeSeg::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoConeSeg::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoConeSeg::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoElement.cxx b/geom/geom/src/TGeoElement.cxx
index 544d61a..df6a629 100644
--- a/geom/geom/src/TGeoElement.cxx
+++ b/geom/geom/src/TGeoElement.cxx
@@ -257,6 +257,7 @@ TGeoIsotope *TGeoIsotope::FindIsotope(const char *name)
 {
 // Find existing isotope by name.
    TGeoElementTable *elTable = TGeoElement::GetElementTable();
+   if (!elTable) return 0;
    return elTable->FindIsotope(name);
 }   
 
diff --git a/geom/geom/src/TGeoEltu.cxx b/geom/geom/src/TGeoEltu.cxx
index 3929a0b..802ab43 100644
--- a/geom/geom/src/TGeoEltu.cxx
+++ b/geom/geom/src/TGeoEltu.cxx
@@ -96,7 +96,7 @@ void TGeoEltu::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoEltu::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoEltu::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t a = fRmin;
@@ -116,7 +116,7 @@ void TGeoEltu::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoEltu::Contains(Double_t *point) const
+Bool_t TGeoEltu::Contains(const Double_t *point) const
 {
 // test if point is inside the elliptical tube
    if (TMath::Abs(point[2]) > fDz) return kFALSE;
@@ -135,7 +135,7 @@ Int_t TGeoEltu::DistancetoPrimitive(Int_t px, Int_t py)
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoEltu::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoEltu::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the tube
    Double_t a2=fRmin*fRmin;
@@ -206,7 +206,7 @@ Double_t TGeoEltu::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoEltu::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoEltu::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the tube and safe distance
    Double_t safz=TMath::Abs(point[2])-fDz;
@@ -338,7 +338,7 @@ void TGeoEltu::InspectShape() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoEltu::Safety(Double_t *point, Bool_t /*in*/) const
+Double_t TGeoEltu::Safety(const Double_t *point, Bool_t /*in*/) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -553,3 +553,44 @@ const TBuffer3D & TGeoEltu::GetBuffer3D(Int_t reqSections, Bool_t localFrame) co
       
    return buffer;
 }
+
+//_____________________________________________________________________________
+void TGeoEltu::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoEltu::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoEltu::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoEltu::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoEltu::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoHalfSpace.cxx b/geom/geom/src/TGeoHalfSpace.cxx
index bee5b83..14bf949 100644
--- a/geom/geom/src/TGeoHalfSpace.cxx
+++ b/geom/geom/src/TGeoHalfSpace.cxx
@@ -63,7 +63,7 @@ TGeoHalfSpace::~TGeoHalfSpace()
 }
 
 //_____________________________________________________________________________   
-void TGeoHalfSpace::ComputeNormal(Double_t * /*point*/, Double_t *dir, Double_t *norm)
+void TGeoHalfSpace::ComputeNormal(const Double_t * /*point*/, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    memcpy(norm, fN, 3*sizeof(Double_t));
@@ -75,7 +75,7 @@ void TGeoHalfSpace::ComputeNormal(Double_t * /*point*/, Double_t *dir, Double_t
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoHalfSpace::Contains(Double_t *point) const
+Bool_t TGeoHalfSpace::Contains(const Double_t *point) const
 {
 // test if point is inside the half-space
    Double_t r[3];
@@ -95,7 +95,7 @@ Int_t TGeoHalfSpace::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoHalfSpace::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoHalfSpace::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to the plane
    Double_t r[3];
@@ -118,7 +118,7 @@ Double_t TGeoHalfSpace::DistFromInside(Double_t *point, Double_t *dir, Int_t iac
 }
 
 //_____________________________________________________________________________
-Double_t TGeoHalfSpace::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoHalfSpace::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to the plane
    Double_t r[3];
@@ -168,7 +168,7 @@ void TGeoHalfSpace::InspectShape() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoHalfSpace::Safety(Double_t *point, Bool_t /*in*/) const
+Double_t TGeoHalfSpace::Safety(const Double_t *point, Bool_t /*in*/) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -207,3 +207,44 @@ void TGeoHalfSpace::SetDimensions(Double_t *param)
    fN[1] /= nsq;
    fN[2] /= nsq;
 }   
+
+//_____________________________________________________________________________
+void TGeoHalfSpace::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHalfSpace::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHalfSpace::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHalfSpace::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHalfSpace::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoHype.cxx b/geom/geom/src/TGeoHype.cxx
index e11507a..4cf4a0f 100644
--- a/geom/geom/src/TGeoHype.cxx
+++ b/geom/geom/src/TGeoHype.cxx
@@ -143,7 +143,7 @@ void TGeoHype::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoHype::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoHype::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    Double_t saf[3];
@@ -179,7 +179,7 @@ void TGeoHype::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoHype::Contains(Double_t *point) const
+Bool_t TGeoHype::Contains(const Double_t *point) const
 {
 // test if point is inside this tube
    if (TMath::Abs(point[2]) > fDz) return kFALSE;
@@ -201,7 +201,7 @@ Int_t TGeoHype::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoHype::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoHype::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the hyperboloid.
    if (iact<3 && safe) {
@@ -240,7 +240,7 @@ Double_t TGeoHype::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 
 
 //_____________________________________________________________________________
-Double_t TGeoHype::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoHype::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the hyperboloid.
    if (iact<3 && safe) {
@@ -298,7 +298,7 @@ Double_t TGeoHype::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, D
 }
 
 //_____________________________________________________________________________
-Int_t TGeoHype::DistToHype(Double_t *point, Double_t *dir, Double_t *s, Bool_t inner, Bool_t in) const
+Int_t TGeoHype::DistToHype(const Double_t *point, const Double_t *dir, Double_t *s, Bool_t inner, Bool_t in) const
 {
 // Compute distance from an arbitrary point to inner/outer surface of hyperboloid.
 // Returns number of positive solutions. S[2] contains the solutions.
@@ -684,7 +684,7 @@ Double_t TGeoHype::ZHypeSq(Double_t r, Bool_t inner) const
 }     
 
 //_____________________________________________________________________________
-Double_t TGeoHype::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoHype::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -706,7 +706,7 @@ Double_t TGeoHype::Safety(Double_t *point, Bool_t in) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoHype::SafetyToHype(Double_t *point, Bool_t inner, Bool_t in) const
+Double_t TGeoHype::SafetyToHype(const Double_t *point, Bool_t inner, Bool_t in) const
 {
 // Compute an underestimate of the closest distance from a point to inner or
 // outer infinite hyperbolas.
@@ -947,3 +947,44 @@ const TBuffer3D & TGeoHype::GetBuffer3D(Int_t reqSections, Bool_t localFrame) co
       
    return buffer;
 }
+
+//_____________________________________________________________________________
+void TGeoHype::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHype::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHype::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHype::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoHype::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoManager.cxx b/geom/geom/src/TGeoManager.cxx
index adc1be9..5387796 100644
--- a/geom/geom/src/TGeoManager.cxx
+++ b/geom/geom/src/TGeoManager.cxx
@@ -350,6 +350,7 @@ TGeoManager::TGeoManager()
       fDrawExtra = kFALSE;
       fStreamVoxels = kFALSE;
       fIsGeomReading = kFALSE;
+      fIsGeomCleaning = kFALSE;
       fClosed = kFALSE;
       fLoopVolumes = kFALSE;
       fBits = 0;
@@ -446,6 +447,7 @@ void TGeoManager::Init()
    fDrawExtra = kFALSE;
    fStreamVoxels = kFALSE;
    fIsGeomReading = kFALSE;
+   fIsGeomCleaning = kFALSE;
    fClosed = kFALSE;
    fLoopVolumes = kFALSE;
    fBits = new UChar_t[50000]; // max 25000 nodes per volume
@@ -524,6 +526,7 @@ TGeoManager::TGeoManager(const TGeoManager& gm) :
   fLoopVolumes(gm.fLoopVolumes),
   fStreamVoxels(gm.fStreamVoxels),
   fIsGeomReading(gm.fIsGeomReading),
+  fIsGeomCleaning(kFALSE),
   fPhiCut(gm.fPhiCut),
   fTimeCut(gm.fTimeCut),
   fDrawExtra(gm.fDrawExtra),
@@ -603,6 +606,7 @@ TGeoManager& TGeoManager::operator=(const TGeoManager& gm)
       fLoopVolumes=gm.fLoopVolumes;
       fStreamVoxels=gm.fStreamVoxels;
       fIsGeomReading=gm.fIsGeomReading;
+      fIsGeomCleaning = kFALSE;
       fPhiCut=gm.fPhiCut;
       fTimeCut=gm.fTimeCut;
       fDrawExtra=gm.fDrawExtra;
@@ -657,6 +661,7 @@ TGeoManager::~TGeoManager()
 {
 //   Destructor
    if (gGeoManager != this) gGeoManager = this;
+   fIsGeomCleaning = kTRUE;
 
    if (gROOT->GetListOfFiles()) { //in case this function is called from TROOT destructor
       gROOT->GetListOfGeometries()->Remove(this);
@@ -695,6 +700,7 @@ TGeoManager::~TGeoManager()
       delete [] fKeyPNEId;
       delete [] fValuePNEId;
    }
+   fIsGeomCleaning = kFALSE;
    gGeoIdentity = 0;
    gGeoManager = 0;
 }
@@ -825,16 +831,23 @@ TGeoNavigator *TGeoManager::AddNavigator()
    return nav;
 }   
 
+TTHREAD_TLS_DECLARE(TGeoNavigator*, tnav);
+
 //_____________________________________________________________________________
 TGeoNavigator *TGeoManager::GetCurrentNavigator() const
 {
 // Returns current navigator for the calling thread.
+   TTHREAD_TLS_INIT(TGeoNavigator*,tnav,0);
    if (!fMultiThread) return fCurrentNavigator;
+   TGeoNavigator *nav = TTHREAD_TLS_GET(TGeoNavigator*,tnav);
+   if (nav) return nav;
    Long_t threadId = TThread::SelfId();
    NavigatorsMap_t::const_iterator it = fNavigators.find(threadId);
    if (it == fNavigators.end()) return 0;
    TGeoNavigatorArray *array = it->second;
-   return array->GetCurrentNavigator();
+   nav = array->GetCurrentNavigator();
+   TTHREAD_TLS_SET(TGeoNavigator*,tnav,nav);
+   return nav;
 }
 
 //_____________________________________________________________________________
@@ -1746,7 +1759,7 @@ void TGeoManager::DrawTracks(Option_t *option)
    SetAnimateTracks();
    for (Int_t i=0; i<fNtracks; i++) {
       track = GetTrack(i);
-      track->Draw(option);
+      if (track) track->Draw(option);
    }
    SetAnimateTracks(kFALSE);
    ModifiedPad();
@@ -3214,9 +3227,12 @@ void TGeoManager::SetTopVolume(TGeoVolume *vol)
       fCurrentNavigator = AddNavigator();
       return;
    }      
-   Int_t nnavigators = GetListOfNavigators()->GetEntriesFast();
+   Int_t nnavigators = 0;
+   TGeoNavigatorArray *arr = GetListOfNavigators();
+   if (!arr) return;
+   nnavigators = arr->GetEntriesFast();
    for (Int_t i=0; i<nnavigators; i++) {
-      TGeoNavigator *nav = (TGeoNavigator*)GetListOfNavigators()->At(i);
+      TGeoNavigator *nav = (TGeoNavigator*)arr->At(i);
       nav->ResetAll();
       if (fClosed) nav->GetCache()->BuildInfoBranch();
    }
@@ -3632,7 +3648,9 @@ void TGeoManager::UpdateElements()
          nelem = mix->GetNelements();
          for (i=0; i<nelem; i++) {
             elem = mix->GetElement(i);
+            if (!elem) continue;
             elem_table = fElementTable->GetElement(elem->Z());
+            if (!elem_table) continue;
             if (elem != elem_table) {
                elem_table->SetDefined(elem->IsDefined());
                elem_table->SetUsed(elem->IsUsed());
@@ -3642,7 +3660,9 @@ void TGeoManager::UpdateElements()
          }
       } else {
          elem = mat->GetElement();
+         if (!elem) continue;
          elem_table = fElementTable->GetElement(elem->Z());
+         if (!elem_table) continue;
          if (elem != elem_table) {
             elem_table->SetDefined(elem->IsDefined());
             elem_table->SetUsed(elem->IsUsed());
diff --git a/geom/geom/src/TGeoMaterial.cxx b/geom/geom/src/TGeoMaterial.cxx
index 996723a..022811c 100644
--- a/geom/geom/src/TGeoMaterial.cxx
+++ b/geom/geom/src/TGeoMaterial.cxx
@@ -122,7 +122,7 @@ TGeoMaterial::TGeoMaterial(const char *name, Double_t a, Double_t z,
    }
    if (fZ - Int_t(fZ) > 1E-3)
       Warning("ctor", "Material %s defined with fractional Z=%f", GetName(), fZ);
-   GetElement()->SetUsed();
+   if (GetElement()) GetElement()->SetUsed();
    gGeoManager->AddMaterial(this);
 }
 
@@ -155,7 +155,7 @@ TGeoMaterial::TGeoMaterial(const char *name, Double_t a, Double_t z, Double_t rh
    }
    if (fZ - Int_t(fZ) > 1E-3)
       Warning("ctor", "Material %s defined with fractional Z=%f", GetName(), fZ);
-   GetElement()->SetUsed();
+   if (GetElement()) GetElement()->SetUsed();
    gGeoManager->AddMaterial(this);
 }
 
@@ -192,7 +192,7 @@ TGeoMaterial::TGeoMaterial(const char *name, TGeoElement *elem, Double_t rho)
    }
    if (fZ - Int_t(fZ) > 1E-3)
       Warning("ctor", "Material %s defined with fractional Z=%f", GetName(), fZ);
-   GetElement()->SetUsed();
+   if (GetElement()) GetElement()->SetUsed();
    gGeoManager->AddMaterial(this);
 }
 
@@ -344,6 +344,10 @@ void TGeoMaterial::SetRadLen(Double_t radlen, Double_t intlen)
       const Double_t lambda0 = 35.*g/(cm*cm);  // [g/cm^2]
       Double_t nilinv = 0.0;
       TGeoElement *elem = GetElement();
+      if (!elem) {
+         Fatal("SetRadLen", "Element not found for material %s", GetName());
+         return;
+      }   
       Double_t nbAtomsPerVolume = TMath::Na()*fDensity/elem->A();
       nilinv += nbAtomsPerVolume*TMath::Power(elem->Neff(), 0.6666667);
       nilinv *= amu/lambda0;
@@ -521,6 +525,10 @@ void TGeoMaterial::FillMaterialEvolution(TObjArray *population, Double_t precisi
    TIter next(table->GetElementsRN());
    while ((elemrn=(TGeoElementRN*)next())) elemrn->ResetRatio();
    elem = GetElement();
+   if (!elem) {
+      Fatal("FillMaterialEvolution", "Element not found for material %s", GetName());
+      return;
+   }   
    if (!elem->IsRadioNuclide()) {
       population->Add(elem);
       return;
diff --git a/geom/geom/src/TGeoMatrix.cxx b/geom/geom/src/TGeoMatrix.cxx
index afcf376..381e2a5 100644
--- a/geom/geom/src/TGeoMatrix.cxx
+++ b/geom/geom/src/TGeoMatrix.cxx
@@ -208,7 +208,7 @@ TGeoMatrix::~TGeoMatrix()
 {
 // Destructor
    if (IsRegistered() && gGeoManager) {
-      if (gGeoManager->GetListOfVolumes()) {
+      if (!gGeoManager->IsCleaning()) {
          gGeoManager->GetListOfMatrices()->Remove(this);
          Warning("dtor", "Registered matrix %s was removed", GetName());
       }
@@ -377,7 +377,7 @@ void TGeoMatrix::LocalToMasterBomb(const Double_t *local, Double_t *master) cons
    }   
    Int_t i;
    const Double_t *tr = GetTranslation();
-   Double_t bombtr[3];
+   Double_t bombtr[3] = {0.,0.,0.};
    gGeoManager->BombTranslation(tr, &bombtr[0]);
    if (!IsRotation()) {
       for (i=0; i<3; i++) master[i] = bombtr[i] + local[i];
@@ -441,7 +441,7 @@ void TGeoMatrix::MasterToLocalBomb(const Double_t *master, Double_t *local) cons
       return;
    }   
    const Double_t *tr = GetTranslation();
-   Double_t bombtr[3];
+   Double_t bombtr[3] = {0.,0.,0.};
    Int_t i;
    gGeoManager->UnbombTranslation(tr, &bombtr[0]);
    if (!IsRotation()) {
@@ -700,7 +700,7 @@ void TGeoTranslation::LocalToMasterBomb(const Double_t *local, Double_t *master)
 {
 // convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
    const Double_t *tr = GetTranslation();
-   Double_t bombtr[3];
+   Double_t bombtr[3] = {0.,0.,0.};
    gGeoManager->BombTranslation(tr, &bombtr[0]);
    for (Int_t i=0; i<3; i++) 
       master[i] = bombtr[i] + local[i]; 
@@ -727,7 +727,7 @@ void TGeoTranslation::MasterToLocalBomb(const Double_t *master, Double_t *local)
 {
 // convert a point by multiplying its column vector (x, y, z, 1) to matrix
    const Double_t *tr = GetTranslation();
-   Double_t bombtr[3];
+   Double_t bombtr[3] = {0.,0.,0.};
    gGeoManager->UnbombTranslation(tr, &bombtr[0]);
    for (Int_t i=0; i<3; i++) 
       local[i] =  master[i]-bombtr[i];
@@ -1273,6 +1273,19 @@ TGeoScale::~TGeoScale()
 }
 
 //_____________________________________________________________________________
+TGeoScale &TGeoScale::operator=(const TGeoScale &other)
+{
+// Assignment operator
+   if (&other == this) return *this;
+   SetBit(kGeoScale);
+   const Double_t *scl =  other.GetScale();
+   memcpy(fScale, scl, kN3);
+   if (fScale[0]*fScale[1]*fScale[2]<0) SetBit(kGeoReflection);
+   else SetBit(kGeoReflection, kFALSE);
+   return *this;
+}   
+
+//_____________________________________________________________________________
 TGeoMatrix& TGeoScale::Inverse() const
 {
 // Return a temporary inverse of this.
diff --git a/geom/geom/src/TGeoNavigator.cxx b/geom/geom/src/TGeoNavigator.cxx
index cf4eaf3..b26248e 100644
--- a/geom/geom/src/TGeoNavigator.cxx
+++ b/geom/geom/src/TGeoNavigator.cxx
@@ -288,7 +288,7 @@ Bool_t TGeoNavigator::cd(const char *path)
 {
 // Browse the tree of nodes starting from top node according to pathname.
 // Changes the path accordingly.
-   if (!strlen(path)) return kFALSE;
+   if (!path[0]) return kFALSE;
    CdTop();
    TString spath = path;
    TGeoVolume *vol;
@@ -678,7 +678,7 @@ TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax, const char *path, Bo
              fDirection[0], fDirection[1], fDirection[2]);
       printf("  pstep=%9.6g  path=%s\n", stepmax, GetPath());
    }   
-   if (strlen(path)) {
+   if (path[0]) {
       PushPath();
       if (!cd(path)) {
          PopPath();
@@ -868,6 +868,10 @@ TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax, const char *path, Bo
          TGeoHMatrix *matrix;
          while (nmany) {
             mothernode = GetMother(up);
+            if (!mothernode) {
+               Fatal("FindNextBoundary", "Cannot find mother node");
+               return 0;
+            }   
             mup = mothernode;
             imother = up+1;
             offset = kFALSE;
@@ -885,6 +889,10 @@ TGeoNode *TGeoNavigator::FindNextBoundary(Double_t stepmax, const char *path, Bo
             }   
             if (ovlp || nextovlp) {
                matrix = GetMotherMatrix(up);
+               if (!matrix) {
+                  Fatal("FindNextBoundary", "Cannot find mother matrix");
+                  return 0;
+               }   
                matrix->MasterToLocal(fPoint,dpt);
                matrix->MasterToLocalVect(fDirection,dvec);
                snext = TGeoShape::Big();
diff --git a/geom/geom/src/TGeoNode.cxx b/geom/geom/src/TGeoNode.cxx
index 2b231af..e794b77 100644
--- a/geom/geom/src/TGeoNode.cxx
+++ b/geom/geom/src/TGeoNode.cxx
@@ -409,56 +409,6 @@ Int_t TGeoNode::FindNode(const TGeoNode *node, Int_t level)
 }
 
 //_____________________________________________________________________________
-void TGeoNode::SetUserExtension(TGeoExtension *ext)
-{
-// Connect user-defined extension to the node. The node "grabs" a copy, so
-// the original object can be released by the producer. Release the previously 
-// connected extension if any.
-//==========================================================================
-// NOTE: This interface is intended for user extensions and is guaranteed not
-// to be used by TGeo
-//==========================================================================
-   if (fUserExtension) fUserExtension->Release();
-   fUserExtension = 0;
-   if (ext) fUserExtension = ext->Grab();
-}   
-
-//_____________________________________________________________________________
-void TGeoNode::SetFWExtension(TGeoExtension *ext)
-{
-// Connect framework defined extension to the node. The node "grabs" a copy,
-// so the original object can be released by the producer. Release the previously 
-// connected extension if any.
-//==========================================================================
-// NOTE: This interface is intended for the use by TGeo and the users should
-//       NOT connect extensions using this method
-//==========================================================================
-   if (fFWExtension) fFWExtension->Release();
-   fFWExtension = 0;
-   if (ext) fFWExtension = ext->Grab();
-}   
-
-//_____________________________________________________________________________
-TGeoExtension *TGeoNode::GrabUserExtension() const
-{
-// Get a copy of the user extension pointer. The user must call Release() on
-// the copy pointer once this pointer is not needed anymore (equivalent to
-// delete() after calling new())
-   if (fUserExtension) return fUserExtension->Grab();
-   return 0;
-}   
-   
-//_____________________________________________________________________________
-TGeoExtension *TGeoNode::GrabFWExtension() const
-{
-// Get a copy of the framework extension pointer. The user must call Release() on
-// the copy pointer once this pointer is not needed anymore (equivalent to
-// delete() after calling new())
-   if (fFWExtension) return fFWExtension->Grab();
-   return 0;
-}   
-
-//_____________________________________________________________________________
 void TGeoNode::SaveAttributes(std::ostream &out)
 {
 // save attributes for this node
@@ -510,6 +460,55 @@ void TGeoNode::SaveAttributes(std::ostream &out)
 }
 
 //_____________________________________________________________________________
+void TGeoNode::SetUserExtension(TGeoExtension *ext)
+{
+// Connect user-defined extension to the node. The node "grabs" a copy, so
+// the original object can be released by the producer. Release the previously 
+// connected extension if any.
+//==========================================================================
+// NOTE: This interface is intended for user extensions and is guaranteed not
+// to be used by TGeo
+//==========================================================================
+   if (fUserExtension) fUserExtension->Release();
+   fUserExtension = 0;
+   if (ext) fUserExtension = ext->Grab();
+}   
+
+//_____________________________________________________________________________
+void TGeoNode::SetFWExtension(TGeoExtension *ext)
+{
+// Connect framework defined extension to the node. The node "grabs" a copy,
+// so the original object can be released by the producer. Release the previously 
+// connected extension if any.
+//==========================================================================
+// NOTE: This interface is intended for the use by TGeo and the users should
+//       NOT connect extensions using this method
+//==========================================================================
+   if (fFWExtension) fFWExtension->Release();
+   fFWExtension = 0;
+   if (ext) fFWExtension = ext->Grab();
+}   
+
+//_____________________________________________________________________________
+TGeoExtension *TGeoNode::GrabUserExtension() const
+{
+// Get a copy of the user extension pointer. The user must call Release() on
+// the copy pointer once this pointer is not needed anymore (equivalent to
+// delete() after calling new())
+   if (fUserExtension) return fUserExtension->Grab();
+   return 0;
+}   
+   
+//_____________________________________________________________________________
+TGeoExtension *TGeoNode::GrabFWExtension() const
+{
+// Get a copy of the framework extension pointer. The user must call Release() on
+// the copy pointer once this pointer is not needed anymore (equivalent to
+// delete() after calling new())
+   if (fFWExtension) return fFWExtension->Grab();
+   return 0;
+}   
+//_____________________________________________________________________________
 Bool_t TGeoNode::MayOverlap(Int_t iother) const 
 {
 // Check the overlab between the bounding box of the node overlaps with the one
@@ -626,7 +625,7 @@ void TGeoNode::PrintOverlaps() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoNode::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoNode::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape
 
diff --git a/geom/geom/src/TGeoPara.cxx b/geom/geom/src/TGeoPara.cxx
index 436dc7b..7b8387c 100644
--- a/geom/geom/src/TGeoPara.cxx
+++ b/geom/geom/src/TGeoPara.cxx
@@ -158,7 +158,7 @@ void TGeoPara::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoPara::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoPara::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    Double_t saf[3];
@@ -200,7 +200,7 @@ void TGeoPara::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoPara::Contains(Double_t *point) const
+Bool_t TGeoPara::Contains(const Double_t *point) const
 {
 // test if point is inside this sphere
    // test Z range
@@ -214,7 +214,7 @@ Bool_t TGeoPara::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPara::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoPara::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the para
 // Boundary safe algorithm.
@@ -258,7 +258,7 @@ Double_t TGeoPara::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPara::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoPara::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the para
    Double_t snxt=TGeoShape::Big();
@@ -527,7 +527,7 @@ void TGeoPara::InspectShape() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPara::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoPara::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -627,3 +627,43 @@ void TGeoPara::Sizeof3D() const
    TGeoBBox::Sizeof3D();
 }
 
+//_____________________________________________________________________________
+void TGeoPara::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPara::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPara::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPara::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPara::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoParaboloid.cxx b/geom/geom/src/TGeoParaboloid.cxx
index c9826b8..abee3c1 100644
--- a/geom/geom/src/TGeoParaboloid.cxx
+++ b/geom/geom/src/TGeoParaboloid.cxx
@@ -114,7 +114,7 @@ void TGeoParaboloid::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoParaboloid::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoParaboloid::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    norm[0] = norm[1] = 0.0;
@@ -146,7 +146,7 @@ void TGeoParaboloid::ComputeNormal(Double_t *point, Double_t *dir, Double_t *nor
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoParaboloid::Contains(Double_t *point) const
+Bool_t TGeoParaboloid::Contains(const Double_t *point) const
 {
 // test if point is inside the elliptical tube
    if (TMath::Abs(point[2])>fDz) return kFALSE;
@@ -167,7 +167,7 @@ Int_t TGeoParaboloid::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoParaboloid::DistToParaboloid(Double_t *point, Double_t *dir, Bool_t in) const
+Double_t TGeoParaboloid::DistToParaboloid(const Double_t *point, const Double_t *dir, Bool_t in) const
 {
 // Compute distance from a point to the parabola given by:
 //  z = a*rsq + b;   rsq = x*x+y*y
@@ -206,7 +206,7 @@ Double_t TGeoParaboloid::DistToParaboloid(Double_t *point, Double_t *dir, Bool_t
 }      
 
 //_____________________________________________________________________________
-Double_t TGeoParaboloid::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoParaboloid::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the paraboloid
    if (iact<3 && safe) {
@@ -227,7 +227,7 @@ Double_t TGeoParaboloid::DistFromInside(Double_t *point, Double_t *dir, Int_t ia
 }
 
 //_____________________________________________________________________________
-Double_t TGeoParaboloid::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoParaboloid::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the paraboloid and safe distance
    Double_t snxt = TGeoShape::Big();
@@ -397,7 +397,7 @@ void TGeoParaboloid::SetSegsAndPols(TBuffer3D &buff) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoParaboloid::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoParaboloid::Safety(const Double_t *point, Bool_t in) const
 {
 // Computes the closest distance from given point to this shape.
    Double_t safz = fDz-TMath::Abs(point[2]);
@@ -626,3 +626,44 @@ const TBuffer3D & TGeoParaboloid::GetBuffer3D(Int_t reqSections, Bool_t localFra
       
    return buffer;
 }
+
+//_____________________________________________________________________________
+void TGeoParaboloid::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoParaboloid::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoParaboloid::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoParaboloid::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoParaboloid::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoPcon.cxx b/geom/geom/src/TGeoPcon.cxx
index 4958b31..f1d330f 100644
--- a/geom/geom/src/TGeoPcon.cxx
+++ b/geom/geom/src/TGeoPcon.cxx
@@ -331,7 +331,7 @@ void TGeoPcon::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoPcon::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoPcon::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    memset(norm,0,3*sizeof(Double_t));
@@ -391,7 +391,7 @@ void TGeoPcon::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoPcon::Contains(Double_t *point) const
+Bool_t TGeoPcon::Contains(const Double_t *point) const
 {
 // test if point is inside this shape
    // check total z range
@@ -442,7 +442,7 @@ Int_t TGeoPcon::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPcon::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoPcon::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the polycone
    if (iact<3 && safe) {
@@ -505,7 +505,7 @@ Double_t TGeoPcon::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPcon::DistToSegZ(Double_t *point, Double_t *dir, Int_t &iz) const
+Double_t TGeoPcon::DistToSegZ(const Double_t *point, const Double_t *dir, Int_t &iz) const
 {
 // compute distance to a pcon Z slice. Segment iz must be valid
    Double_t zmin=fZ[iz];
@@ -544,7 +544,7 @@ Double_t TGeoPcon::DistToSegZ(Double_t *point, Double_t *dir, Int_t &iz) const
 }      
 
 //_____________________________________________________________________________
-Double_t TGeoPcon::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoPcon::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the tube
    if ((iact<3) && safe) {
@@ -1024,7 +1024,7 @@ void TGeoPcon::SetSegsAndPols(TBuffer3D &buff) const
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoPcon::SafetyToSegment(Double_t *point, Int_t ipl, Bool_t in, Double_t safmin) const
+Double_t TGeoPcon::SafetyToSegment(const Double_t *point, Int_t ipl, Bool_t in, Double_t safmin) const
 {
 // Compute safety from POINT to segment between planes ipl, ipl+1 within safmin.
 
@@ -1055,7 +1055,7 @@ Double_t TGeoPcon::SafetyToSegment(Double_t *point, Int_t ipl, Bool_t in, Double
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPcon::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoPcon::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -1350,3 +1350,44 @@ void TGeoPcon::Streamer(TBuffer &R__b)
       R__b.WriteClassBuffer(TGeoPcon::Class(),this);
    }
 }
+
+//_____________________________________________________________________________
+void TGeoPcon::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPcon::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPcon::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPcon::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPcon::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoPgon.cxx b/geom/geom/src/TGeoPgon.cxx
index 0b8ade2..35630bf 100644
--- a/geom/geom/src/TGeoPgon.cxx
+++ b/geom/geom/src/TGeoPgon.cxx
@@ -198,7 +198,7 @@ void TGeoPgon::ComputeBBox()
 }
 
 //_____________________________________________________________________________   
-void TGeoPgon::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoPgon::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    memset(norm,0,3*sizeof(Double_t));
@@ -290,7 +290,7 @@ void TGeoPgon::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoPgon::Contains(Double_t *point) const
+Bool_t TGeoPgon::Contains(const Double_t *point) const
 {
 // test if point is inside this shape
    // check total z range
@@ -336,7 +336,7 @@ Bool_t TGeoPgon::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPgon::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoPgon::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the polygone
    // first find out in which Z section the point is in
@@ -432,7 +432,7 @@ Double_t TGeoPgon::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }   
 
 //_____________________________________________________________________________
-void TGeoPgon::LocatePhi(Double_t *point, Int_t &ipsec) const
+void TGeoPgon::LocatePhi(const Double_t *point, Int_t &ipsec) const
 {
 // Locates index IPSEC of the phi sector containing POINT.
    Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
@@ -442,7 +442,7 @@ void TGeoPgon::LocatePhi(Double_t *point, Int_t &ipsec) const
 }                    
 
 //_____________________________________________________________________________
-Int_t TGeoPgon::GetPhiCrossList(Double_t *point, Double_t *dir, Int_t istart, Double_t *sphi, Int_t *iphi, Double_t stepmax) const
+Int_t TGeoPgon::GetPhiCrossList(const Double_t *point, const Double_t *dir, Int_t istart, Double_t *sphi, Int_t *iphi, Double_t stepmax) const
 {
 // Returns lists of PGON phi crossings for a ray starting from POINT.
    Double_t rxy, phi, cph, sph;
@@ -517,7 +517,7 @@ Int_t TGeoPgon::GetPhiCrossList(Double_t *point, Double_t *dir, Int_t istart, Do
 }        
 
 //_____________________________________________________________________________
-Bool_t TGeoPgon::SliceCrossingInZ(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
+Bool_t TGeoPgon::SliceCrossingInZ(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
 {
 // Performs ray propagation between Z segments.
    snext = 0.;
@@ -588,7 +588,7 @@ Bool_t TGeoPgon::SliceCrossingInZ(Double_t *point, Double_t *dir, Int_t nphi, In
 }
  
 //_____________________________________________________________________________
-Bool_t TGeoPgon::SliceCrossingZ(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
+Bool_t TGeoPgon::SliceCrossingZ(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
 {
 // Performs ray propagation between Z segments.
    if (!nphi) return kFALSE;
@@ -665,7 +665,7 @@ Bool_t TGeoPgon::SliceCrossingZ(Double_t *point, Double_t *dir, Int_t nphi, Int_
 }  
 
 //_____________________________________________________________________________
-Bool_t TGeoPgon::SliceCrossingIn(Double_t *point, Double_t *dir, Int_t ipl, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
+Bool_t TGeoPgon::SliceCrossingIn(const Double_t *point, const Double_t *dir, Int_t ipl, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
 {
 // Check boundary crossing inside phi slices. Return distance snext to first crossing
 // if smaller than stepmax.
@@ -800,7 +800,7 @@ Bool_t TGeoPgon::SliceCrossingIn(Double_t *point, Double_t *dir, Int_t ipl, Int_
 }   
                
 //_____________________________________________________________________________
-Bool_t TGeoPgon::SliceCrossing(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
+Bool_t TGeoPgon::SliceCrossing(const Double_t *point, const Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
 {
 // Check boundary crossing inside phi slices. Return distance snext to first crossing
 // if smaller than stepmax.
@@ -888,7 +888,7 @@ Bool_t TGeoPgon::SliceCrossing(Double_t *point, Double_t *dir, Int_t nphi, Int_t
    return kFALSE;
 }
 //_____________________________________________________________________________
-Bool_t TGeoPgon::IsCrossingSlice(Double_t *point, Double_t *dir, Int_t iphi, Double_t sstart, Int_t &ipl, Double_t &snext, Double_t stepmax) const
+Bool_t TGeoPgon::IsCrossingSlice(const Double_t *point, const Double_t *dir, Int_t iphi, Double_t sstart, Int_t &ipl, Double_t &snext, Double_t stepmax) const
 {
 // Check crossing of a given pgon slice, from a starting point inside the slice
    if (ipl<0 || ipl>fNz-2) return kFALSE;
@@ -986,7 +986,7 @@ Bool_t TGeoPgon::IsCrossingSlice(Double_t *point, Double_t *dir, Int_t iphi, Dou
 }           
 
 //_____________________________________________________________________________
-Double_t TGeoPgon::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoPgon::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the polygone
    if (iact<3 && safe) {
@@ -1544,7 +1544,7 @@ Double_t TGeoPgon::Rpg(Double_t z, Int_t ipl, Bool_t inner, Double_t &a, Double_
 }         
 
 //_____________________________________________________________________________
-Double_t TGeoPgon::Rproj(Double_t z, Double_t *point, Double_t *dir, Double_t cphi, Double_t sphi, Double_t &a, Double_t &b) const
+Double_t TGeoPgon::Rproj(Double_t z, const Double_t *point, const Double_t *dir, Double_t cphi, Double_t sphi, Double_t &a, Double_t &b) const
 {
 // Computes projected distance at a given Z for a given ray inside a given sector 
 // and fills coefficients:
@@ -1560,7 +1560,7 @@ Double_t TGeoPgon::Rproj(Double_t z, Double_t *point, Double_t *dir, Double_t cp
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoPgon::SafetyToSegment(Double_t *point, Int_t ipl, Int_t iphi, Bool_t in, Double_t safphi, Double_t safmin) const
+Double_t TGeoPgon::SafetyToSegment(const Double_t *point, Int_t ipl, Int_t iphi, Bool_t in, Double_t safphi, Double_t safmin) const
 {
 // Compute safety from POINT to segment between planes ipl, ipl+1 within safmin.
    Double_t saf[3];
@@ -1627,7 +1627,7 @@ Double_t TGeoPgon::SafetyToSegment(Double_t *point, Int_t ipl, Int_t iphi, Bool_
 }      
 
 //_____________________________________________________________________________
-Double_t TGeoPgon::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoPgon::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -1877,3 +1877,44 @@ const TBuffer3D & TGeoPgon::GetBuffer3D(Int_t reqSections, Bool_t localFrame) co
       
    return buffer;
 }
+
+//_____________________________________________________________________________
+void TGeoPgon::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPgon::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPgon::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPgon::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoPgon::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoPhysicalNode.cxx b/geom/geom/src/TGeoPhysicalNode.cxx
index f2ea443..3979075 100644
--- a/geom/geom/src/TGeoPhysicalNode.cxx
+++ b/geom/geom/src/TGeoPhysicalNode.cxx
@@ -80,7 +80,7 @@ TGeoPhysicalNode::TGeoPhysicalNode() : TNamed()
 TGeoPhysicalNode::TGeoPhysicalNode(const char *path) : TNamed(path,"")
 {
 // Constructor
-   if (!strlen(path)) {
+   if (!path[0]) {
       Error("ctor", "path not valid");
       return;
    }
diff --git a/geom/geom/src/TGeoPolygon.cxx b/geom/geom/src/TGeoPolygon.cxx
index 7e9922a..58e8d6a 100644
--- a/geom/geom/src/TGeoPolygon.cxx
+++ b/geom/geom/src/TGeoPolygon.cxx
@@ -112,7 +112,7 @@ Double_t TGeoPolygon::Area() const
 }      
 
 //_____________________________________________________________________________
-Bool_t TGeoPolygon::Contains(Double_t *point) const
+Bool_t TGeoPolygon::Contains(const Double_t *point) const
 {
 // Check if a point given by X = point[0], Y = point[1] is inside the polygon.
    Int_t i;
@@ -226,7 +226,7 @@ void TGeoPolygon::GetConvexVertices(Double_t *x, Double_t *y) const
 }
       
 //_____________________________________________________________________________
-Bool_t TGeoPolygon::IsRightSided(Double_t *point, Int_t ind1, Int_t ind2) const
+Bool_t TGeoPolygon::IsRightSided(const Double_t *point, Int_t ind1, Int_t ind2) const
 {
 // Check if POINT is right-sided with respect to the segment defined by IND1 and IND2.
    Double_t dot = (point[0]-fX[ind1])*(fY[ind2]-fY[ind1]) -
@@ -329,7 +329,7 @@ void TGeoPolygon::OutscribedConvex()
 }
 
 //_____________________________________________________________________________
-Double_t TGeoPolygon::Safety(Double_t *point, Int_t &isegment) const
+Double_t TGeoPolygon::Safety(const Double_t *point, Int_t &isegment) const
 {
 // Compute minimum distance from POINT to any segment. Returns segment index.
    Int_t i1, i2;
diff --git a/geom/geom/src/TGeoScaledShape.cxx b/geom/geom/src/TGeoScaledShape.cxx
index 3bb40cf..3b7207b 100644
--- a/geom/geom/src/TGeoScaledShape.cxx
+++ b/geom/geom/src/TGeoScaledShape.cxx
@@ -104,7 +104,7 @@ void TGeoScaledShape::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoScaledShape::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoScaledShape::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t local[3], ldir[3], lnorm[3];
@@ -118,7 +118,7 @@ void TGeoScaledShape::ComputeNormal(Double_t *point, Double_t *dir, Double_t *no
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoScaledShape::Contains(Double_t *point) const
+Bool_t TGeoScaledShape::Contains(const Double_t *point) const
 {
 // Test if point is inside the scaled shape
    Double_t local[3];
@@ -135,7 +135,7 @@ Int_t TGeoScaledShape::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoScaledShape::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoScaledShape::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the scaled shape.
    Double_t local[3], ldir[3];
@@ -152,7 +152,7 @@ Double_t TGeoScaledShape::DistFromInside(Double_t *point, Double_t *dir, Int_t i
 
 
 //_____________________________________________________________________________
-Double_t TGeoScaledShape::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoScaledShape::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the scaled shape.
    Double_t local[3], ldir[3];
@@ -281,7 +281,7 @@ void TGeoScaledShape::SetSegsAndPols(TBuffer3D &buff) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoScaledShape::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoScaledShape::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -345,3 +345,44 @@ void TGeoScaledShape::SetPoints(Float_t *points) const
       points[index+2] = master[2];
    }   
 }
+
+//_____________________________________________________________________________
+void TGeoScaledShape::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoScaledShape::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoScaledShape::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoScaledShape::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoScaledShape::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoShape.cxx b/geom/geom/src/TGeoShape.cxx
index 7acaf5b..4c1526b 100644
--- a/geom/geom/src/TGeoShape.cxx
+++ b/geom/geom/src/TGeoShape.cxx
@@ -78,7 +78,7 @@
 // Note that global queries related to a geometry are handled by the manager class.
 // However, shape-related queries might be sometimes usefull.
 //
-// A) Bool_t TGeoShape::Contains(Double_t *point[3])
+// A) Bool_t TGeoShape::Contains(const Double_t *point[3])
 //   - this method returns true if POINT is actually inside the shape. The point
 // has to be defined in the local shape reference. For instance, for a box having
 // DX, DY and DZ half-lengths a point will be considered inside if :
@@ -108,7 +108,7 @@
 //   - computes the distance to entering a shape from a given point OUTSIDE. Acts
 // in the same way as B).
 //
-// D) Double_t Safety(Double_t *point[3], Bool_t inside)
+// D) Double_t Safety(const Double_t *point[3], Bool_t inside)
 //
 //   - compute maximum shift of a point in any direction that does not change its
 // INSIDE/OUTSIDE state (does not cross shape boundaries). The state of the point
@@ -191,7 +191,7 @@ TGeoShape::TGeoShape(const char *name)
 TGeoShape::~TGeoShape()
 {
 // Destructor
-   if (gGeoManager) gGeoManager->GetListOfShapes()->Remove(this);
+   if (gGeoManager && !gGeoManager->IsCleaning()) gGeoManager->GetListOfShapes()->Remove(this);
 }
 
 //_____________________________________________________________________________
@@ -240,7 +240,7 @@ Double_t TGeoShape::EpsMch()
 const char *TGeoShape::GetName() const
 {
 // Get the shape name.
-   if (!strlen(fName)) {
+   if (!fName[0]) {
       return ((TObject *)this)->ClassName();
    }
    return TNamed::GetName();
@@ -256,7 +256,7 @@ Int_t TGeoShape::ShapeDistancetoPrimitive(Int_t numpoints, Int_t px, Int_t py) c
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoShape::IsCloseToPhi(Double_t epsil, Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
+Bool_t TGeoShape::IsCloseToPhi(Double_t epsil, const Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
 {
 // True if point is closer than epsil to one of the phi planes defined by c1,s1 or c2,s2
    Double_t saf1 = TGeoShape::Big();
@@ -269,7 +269,7 @@ Bool_t TGeoShape::IsCloseToPhi(Double_t epsil, Double_t *point, Double_t c1, Dou
 }   
 
 //_____________________________________________________________________________
-Bool_t TGeoShape::IsInPhiRange(Double_t *point, Double_t phi1, Double_t phi2)
+Bool_t TGeoShape::IsInPhiRange(const Double_t *point, Double_t phi1, Double_t phi2)
 {
 // Static method to check if a point is in the phi range (phi1, phi2) [degrees]
    Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
@@ -280,7 +280,7 @@ Bool_t TGeoShape::IsInPhiRange(Double_t *point, Double_t phi1, Double_t phi2)
 }   
 
 //_____________________________________________________________________________  
-Bool_t TGeoShape::IsCrossingSemiplane(Double_t *point, Double_t *dir, Double_t cphi, Double_t sphi, Double_t &snext, Double_t &rxy)
+Bool_t TGeoShape::IsCrossingSemiplane(const Double_t *point, const Double_t *dir, Double_t cphi, Double_t sphi, Double_t &snext, Double_t &rxy)
 {
 // Compute distance from POINT to semiplane defined by PHI angle along DIR. Computes
 // also radius at crossing point. This might be negative in case the crossing is
@@ -387,7 +387,7 @@ Bool_t TGeoShape::IsSegCrossing(Double_t x1, Double_t y1, Double_t x2, Double_t
 }         
 
 //_____________________________________________________________________________
-Double_t TGeoShape::DistToPhiMin(Double_t *point, Double_t *dir, Double_t s1, Double_t c1,
+Double_t TGeoShape::DistToPhiMin(const Double_t *point, const Double_t *dir, Double_t s1, Double_t c1,
                                  Double_t s2, Double_t c2, Double_t sm, Double_t cm, Bool_t in)
 {
 // compute distance from point (inside phi) to both phi planes. Return minimum.
@@ -418,7 +418,7 @@ Double_t TGeoShape::DistToPhiMin(Double_t *point, Double_t *dir, Double_t s1, Do
 }
 
 //_____________________________________________________________________________
-void TGeoShape::NormalPhi(Double_t *point, Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
+void TGeoShape::NormalPhi(const Double_t *point, const Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
 {
 // Static method to compute normal to phi planes.
    Double_t saf1 = TGeoShape::Big();
@@ -443,7 +443,7 @@ void TGeoShape::NormalPhi(Double_t *point, Double_t *dir, Double_t *norm, Double
 }           
  
 //_____________________________________________________________________________
-Double_t TGeoShape::SafetyPhi(Double_t *point, Bool_t in, Double_t phi1, Double_t phi2)
+Double_t TGeoShape::SafetyPhi(const Double_t *point, Bool_t in, Double_t phi1, Double_t phi2)
 {
 // Static method to compute safety w.r.t a phi corner defined by cosines/sines
 // of the angles phi1, phi2.
@@ -694,7 +694,7 @@ void TGeoShape::Draw(Option_t *option)
 {
 // Draw this shape.
    TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
-   if (option && strlen(option) > 0) {
+   if (option && option[0]) {
       painter->DrawShape(this, option); 
    } else {
       painter->DrawShape(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
@@ -706,7 +706,7 @@ void TGeoShape::Paint(Option_t *option)
 {
 // Paint this shape.
    TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
-   if (option && strlen(option) > 0) {
+   if (option && option[0]) {
       painter->PaintShape(this, option); 
    } else {
       painter->PaintShape(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
diff --git a/geom/geom/src/TGeoShapeAssembly.cxx b/geom/geom/src/TGeoShapeAssembly.cxx
index f59b10d..5e946ee 100644
--- a/geom/geom/src/TGeoShapeAssembly.cxx
+++ b/geom/geom/src/TGeoShapeAssembly.cxx
@@ -145,7 +145,7 @@ void TGeoShapeAssembly::RecomputeBoxLast()
 }  
 
 //_____________________________________________________________________________   
-void TGeoShapeAssembly::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoShapeAssembly::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. Should not be called.
    if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
@@ -167,7 +167,7 @@ void TGeoShapeAssembly::ComputeNormal(Double_t *point, Double_t *dir, Double_t *
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoShapeAssembly::Contains(Double_t *point) const
+Bool_t TGeoShapeAssembly::Contains(const Double_t *point) const
 {
 // Test if point is inside the assembly
    if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
@@ -182,7 +182,7 @@ Bool_t TGeoShapeAssembly::Contains(Double_t *point) const
       // get the list of nodes passing thorough the current voxel
       TGeoNavigator *nav = gGeoManager->GetCurrentNavigator();
       TGeoStateInfo &td = *nav->GetCache()->GetInfo();
-      check_list = voxels->GetCheckList(&point[0], ncheck, td);
+      check_list = voxels->GetCheckList(point, ncheck, td);
       if (!check_list) {
          nav->GetCache()->ReleaseInfo();
          return kFALSE;
@@ -223,7 +223,7 @@ Int_t TGeoShapeAssembly::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoShapeAssembly::DistFromInside(Double_t * /*point*/, Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
+Double_t TGeoShapeAssembly::DistFromInside(const Double_t * /*point*/, const Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
 {
 // Compute distance from inside point to surface of the hyperboloid.
    Info("DistFromInside", "Cannot compute distance from inside the assembly (but from a component)"); 
@@ -232,7 +232,7 @@ Double_t TGeoShapeAssembly::DistFromInside(Double_t * /*point*/, Double_t * /*di
 
 
 //_____________________________________________________________________________
-Double_t TGeoShapeAssembly::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoShapeAssembly::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the hyperboloid.
 //   fVolume->SetNextNodeIndex(-1);
@@ -350,7 +350,7 @@ void TGeoShapeAssembly::SetSegsAndPols(TBuffer3D & /*buff*/) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoShapeAssembly::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoShapeAssembly::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -433,3 +433,43 @@ void TGeoShapeAssembly::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
    npols = 0;
 }
 
+//_____________________________________________________________________________
+void TGeoShapeAssembly::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoShapeAssembly::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoShapeAssembly::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoShapeAssembly::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoShapeAssembly::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoSphere.cxx b/geom/geom/src/TGeoSphere.cxx
index a8c720d..32bab00 100644
--- a/geom/geom/src/TGeoSphere.cxx
+++ b/geom/geom/src/TGeoSphere.cxx
@@ -78,14 +78,18 @@ TGeoSphere::TGeoSphere(const char *name, Double_t rmin, Double_t rmax, Double_t
 }
 
 //_____________________________________________________________________________
-TGeoSphere::TGeoSphere(Double_t *param, Int_t /*nparam*/)
+TGeoSphere::TGeoSphere(Double_t *param, Int_t nparam)
            :TGeoBBox(0, 0, 0)
 {
 // Default constructor specifying minimum and maximum radius
 // param[0] = Rmin
 // param[1] = Rmax
+// param[2] = theta1
+// param[3] = theta2
+// param[4] = phi1
+// param[5] = phi2
    SetShapeBit(TGeoShape::kGeoSph);
-   SetDimensions(param);
+   SetDimensions(param, nparam);
    ComputeBBox();
    SetNumberOfDivisions(20);
 }
@@ -186,7 +190,7 @@ void TGeoSphere::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoSphere::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoSphere::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    Double_t rxy2 = point[0]*point[0]+point[1]*point[1];
@@ -242,7 +246,7 @@ void TGeoSphere::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Int_t TGeoSphere::IsOnBoundary(Double_t *point) const
+Int_t TGeoSphere::IsOnBoundary(const Double_t *point) const
 {
 // Check if a point in local sphere coordinates is close to a boundary within
 // shape tolerance. Return values:
@@ -292,7 +296,7 @@ Int_t TGeoSphere::IsOnBoundary(Double_t *point) const
 }      
 
 //_____________________________________________________________________________
-Bool_t TGeoSphere::IsPointInside(Double_t *point, Bool_t checkR, Bool_t checkTh, Bool_t checkPh) const
+Bool_t TGeoSphere::IsPointInside(const Double_t *point, Bool_t checkR, Bool_t checkTh, Bool_t checkPh) const
 {
 // Check if a point is inside radius/theta/phi ranges for the spherical sector.
    Double_t r2 = point[0]*point[0]+point[1]*point[1]+point[2]*point[2];
@@ -318,7 +322,7 @@ Bool_t TGeoSphere::IsPointInside(Double_t *point, Bool_t checkR, Bool_t checkTh,
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoSphere::Contains(Double_t *point) const
+Bool_t TGeoSphere::Contains(const Double_t *point) const
 {
 // test if point is inside this sphere
    // check Rmin<=R<=Rmax
@@ -356,7 +360,7 @@ Int_t TGeoSphere::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoSphere::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoSphere::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the sphere
 // Check if the bounding box is crossed within the requested distance
@@ -658,7 +662,7 @@ Double_t TGeoSphere::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoSphere::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoSphere::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the sphere
    Double_t saf[6];
@@ -882,7 +886,7 @@ Double_t TGeoSphere::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoSphere::DistToSphere(Double_t *point, Double_t *dir, Double_t rsph, Bool_t check, Bool_t firstcross) const
+Double_t TGeoSphere::DistToSphere(const Double_t *point, const Double_t *dir, Double_t rsph, Bool_t check, Bool_t firstcross) const
 {
 // compute distance to sphere of radius rsph. Direction has to be a unit vector
    if (rsph<=0) return TGeoShape::Big();
@@ -1416,7 +1420,7 @@ void TGeoSphere::SetSegsAndPols(TBuffer3D & buff) const
 }   
    
 //_____________________________________________________________________________
-Double_t TGeoSphere::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoSphere::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -1493,7 +1497,7 @@ void TGeoSphere::SetSphDimensions(Double_t rmin, Double_t rmax, Double_t theta1,
 }   
 
 //_____________________________________________________________________________
-void TGeoSphere::SetDimensions(Double_t *param)
+void TGeoSphere::SetDimensions(Double_t *param, Int_t nparam)
 {
 // Set dimensions of the spherical segment starting from a list of parameters.
    Double_t rmin = param[0];
@@ -1502,14 +1506,22 @@ void TGeoSphere::SetDimensions(Double_t *param)
    Double_t theta2 = 180.;
    Double_t phi1 = 0;
    Double_t phi2 = 360.;
-//   if (nparam > 2) theta1 = param[2];
-//   if (nparam > 3) theta2 = param[3];
-//   if (nparam > 4) phi1   = param[4];
-//   if (nparam > 5) phi2   = param[5];
+   if (nparam > 2) theta1 = param[2];
+   if (nparam > 3) theta2 = param[3];
+   if (nparam > 4) phi1   = param[4];
+   if (nparam > 5) phi2   = param[5];
    SetSphDimensions(rmin, rmax, theta1, theta2, phi1, phi2);
 }   
 
 //_____________________________________________________________________________
+void TGeoSphere::SetDimensions(Double_t *param)
+{
+// Set dimensions of the spherical segment starting from a list of parameters.
+// Only takes rmin and rmax
+   SetDimensions(param,2);
+}   
+
+//_____________________________________________________________________________
 void TGeoSphere::SetNumberOfDivisions(Int_t p)
 {
 // Set the number of divisions of mesh circles keeping aspect ratio.
@@ -1853,3 +1865,44 @@ const TBuffer3D & TGeoSphere::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
       
    return buffer;
 }
+
+//_____________________________________________________________________________
+void TGeoSphere::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoSphere::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoSphere::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoSphere::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoSphere::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoStateInfo.cxx b/geom/geom/src/TGeoStateInfo.cxx
index 700832d..5814a47 100644
--- a/geom/geom/src/TGeoStateInfo.cxx
+++ b/geom/geom/src/TGeoStateInfo.cxx
@@ -42,6 +42,10 @@ TGeoStateInfo::TGeoStateInfo()
    fVoxBits1 = new UChar_t[2 + ((maxDaughters-1)>>3)];
    fXtruXc = new Double_t[maxXtruVert];
    fXtruYc = new Double_t[maxXtruVert];
+   fVoxSlices[0] = fVoxSlices[1] = fVoxSlices[2] = -1;
+   fVoxInc[0] = fVoxInc[1] = fVoxInc[2] = 0;
+   fVoxInvdir[0] = fVoxInvdir[1] = fVoxInvdir[2] = 0;
+   fVoxLimits[0] = fVoxLimits[1] = fVoxLimits[2] = 0;
 }
 
 //_____________________________________________________________________________
@@ -82,6 +86,10 @@ TGeoStateInfo::TGeoStateInfo(const TGeoStateInfo &other)
    fVoxBits1 = new UChar_t[1 + ((maxDaughters-1)>>3)];
    fXtruXc = new Double_t[maxXtruVert];
    fXtruYc = new Double_t[maxXtruVert];
+   fVoxSlices[0] = fVoxSlices[1] = fVoxSlices[2] = -1;
+   fVoxInc[0] = fVoxInc[1] = fVoxInc[2] = 0;
+   fVoxInvdir[0] = fVoxInvdir[1] = fVoxInvdir[2] = 0;
+   fVoxLimits[0] = fVoxLimits[1] = fVoxLimits[2] = 0;
 }
 
 //_____________________________________________________________________________
@@ -99,9 +107,17 @@ TGeoStateInfo &TGeoStateInfo::operator=(const TGeoStateInfo &other)
    fDivCombi = other.fDivCombi;
    fVoxNcandidates = other.fVoxNcandidates;
    fVoxCurrent = other.fVoxCurrent;
+   fVoxCheckList = other.fVoxCheckList;
+   fVoxBits1 = other.fVoxBits1;
    fBoolSelected = other.fBoolSelected;
    fXtruSeg = other.fXtruSeg;
    fXtruIz = other.fXtruIz;
+   fXtruXc = other.fXtruXc;
+   fXtruYc = other.fXtruYc;
    fXtruPoly = other.fXtruPoly;
+   fVoxSlices[0] = fVoxSlices[1] = fVoxSlices[2] = -1;
+   fVoxInc[0] = fVoxInc[1] = fVoxInc[2] = 0;
+   fVoxInvdir[0] = fVoxInvdir[1] = fVoxInvdir[2] = 0;
+   fVoxLimits[0] = fVoxLimits[1] = fVoxLimits[2] = 0;
    return *this;
 }
diff --git a/geom/geom/src/TGeoTorus.cxx b/geom/geom/src/TGeoTorus.cxx
index 653e5d5..591c1e9 100644
--- a/geom/geom/src/TGeoTorus.cxx
+++ b/geom/geom/src/TGeoTorus.cxx
@@ -146,7 +146,7 @@ void TGeoTorus::ComputeBBox()
 }
 
 //-----------------------------------------------------------------------------   
-void TGeoTorus::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoTorus::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    Double_t phi = TMath::ATan2(point[1],point[0]);
@@ -188,7 +188,7 @@ void TGeoTorus::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoTorus::Contains(Double_t *point) const
+Bool_t TGeoTorus::Contains(const Double_t *point) const
 {
 // Test if point is inside the torus.
    // check phi range
@@ -219,7 +219,7 @@ Int_t TGeoTorus::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTorus::Daxis(Double_t *pt, Double_t *dir, Double_t t) const
+Double_t TGeoTorus::Daxis(const Double_t *pt, const Double_t *dir, Double_t t) const
 {
 // Computes distance to axis of the torus from point pt + t*dir;
    Double_t p[3];
@@ -229,7 +229,7 @@ Double_t TGeoTorus::Daxis(Double_t *pt, Double_t *dir, Double_t t) const
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoTorus::DDaxis(Double_t *pt, Double_t *dir, Double_t t) const
+Double_t TGeoTorus::DDaxis(const Double_t *pt, const Double_t *dir, Double_t t) const
 {
 // Computes derivative w.r.t. t of the distance to axis of the torus from point pt + t*dir;
    Double_t p[3];
@@ -243,7 +243,7 @@ Double_t TGeoTorus::DDaxis(Double_t *pt, Double_t *dir, Double_t t) const
 }   
 
 //_____________________________________________________________________________
-Double_t TGeoTorus::DDDaxis(Double_t *pt, Double_t *dir, Double_t t) const
+Double_t TGeoTorus::DDDaxis(const Double_t *pt, const Double_t *dir, Double_t t) const
 {
 // Second derivative of distance to torus axis w.r.t t.
    Double_t p[3];
@@ -260,7 +260,7 @@ Double_t TGeoTorus::DDDaxis(Double_t *pt, Double_t *dir, Double_t t) const
 }
    
 //_____________________________________________________________________________
-Double_t TGeoTorus::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTorus::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the torus.
    if (iact<3 && safe) {
@@ -298,7 +298,7 @@ Double_t TGeoTorus::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, D
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTorus::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTorus::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the torus.
    if (iact<3 && safe) {
@@ -686,7 +686,7 @@ void TGeoTorus::SetSegsAndPols(TBuffer3D &buff) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTorus::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoTorus::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -1032,7 +1032,7 @@ Int_t TGeoTorus::SolveQuartic(Double_t a, Double_t b, Double_t c, Double_t d, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTorus::ToBoundary(Double_t *pt, Double_t *dir, Double_t r, Bool_t in) const
+Double_t TGeoTorus::ToBoundary(const Double_t *pt, const Double_t *dir, Double_t r, Bool_t in) const
 {
 // Returns distance to the surface or the torus (fR,r) from a point, along
 // a direction. Point is close enough to the boundary so that the distance 
@@ -1186,3 +1186,43 @@ const TBuffer3D & TGeoTorus::GetBuffer3D(Int_t reqSections, Bool_t localFrame) c
    return buffer;
 }
 
+//_____________________________________________________________________________
+void TGeoTorus::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTorus::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTorus::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTorus::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTorus::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoTrd1.cxx b/geom/geom/src/TGeoTrd1.cxx
index f5cd90f..c0877ec 100644
--- a/geom/geom/src/TGeoTrd1.cxx
+++ b/geom/geom/src/TGeoTrd1.cxx
@@ -134,7 +134,7 @@ void TGeoTrd1::ComputeBBox()
 }
 
 //_____________________________________________________________________________   
-void TGeoTrd1::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoTrd1::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t safe, safemin;
@@ -172,7 +172,7 @@ void TGeoTrd1::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoTrd1::Contains(Double_t *point) const
+Bool_t TGeoTrd1::Contains(const Double_t *point) const
 {
 // test if point is inside this shape
    // check Z range
@@ -186,7 +186,7 @@ Bool_t TGeoTrd1::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrd1::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTrd1::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the trd1
 // Boundary safe algorithm.
@@ -238,7 +238,7 @@ Double_t TGeoTrd1::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-void TGeoTrd1::GetVisibleCorner(Double_t *point, Double_t *vertex, Double_t *normals) const
+void TGeoTrd1::GetVisibleCorner(const Double_t *point, Double_t *vertex, Double_t *normals) const
 {
 // get the most visible corner from outside point and the normals
    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
@@ -278,7 +278,7 @@ void TGeoTrd1::GetVisibleCorner(Double_t *point, Double_t *vertex, Double_t *nor
 }
 
 //_____________________________________________________________________________
-void TGeoTrd1::GetOppositeCorner(Double_t * /*point*/, Int_t inorm, Double_t *vertex, Double_t *normals) const
+void TGeoTrd1::GetOppositeCorner(const Double_t * /*point*/, Int_t inorm, Double_t *vertex, Double_t *normals) const
 {
 // get the opposite corner of the intersected face
    TGeoTrd1 *trd1 = (TGeoTrd1*)this;
@@ -301,7 +301,7 @@ void TGeoTrd1::GetOppositeCorner(Double_t * /*point*/, Int_t inorm, Double_t *ve
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrd1::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTrd1::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the trd1
 // Boundary safe algorithm
@@ -597,7 +597,7 @@ void TGeoTrd1::InspectShape() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrd1::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoTrd1::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -706,3 +706,44 @@ void TGeoTrd1::Sizeof3D() const
 // fill size of this 3-D object
    TGeoBBox::Sizeof3D();
 }
+
+//_____________________________________________________________________________
+void TGeoTrd1::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd1::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd1::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd1::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd1::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoTrd2.cxx b/geom/geom/src/TGeoTrd2.cxx
index b97aea7..cdfc92a 100644
--- a/geom/geom/src/TGeoTrd2.cxx
+++ b/geom/geom/src/TGeoTrd2.cxx
@@ -132,7 +132,7 @@ void TGeoTrd2::ComputeBBox()
 }
 
 //_____________________________________________________________________________   
-void TGeoTrd2::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoTrd2::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    Double_t safe, safemin;
@@ -182,7 +182,7 @@ void TGeoTrd2::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoTrd2::Contains(Double_t *point) const
+Bool_t TGeoTrd2::Contains(const Double_t *point) const
 {
 // test if point is inside this shape
    // check Z range
@@ -197,7 +197,7 @@ Bool_t TGeoTrd2::Contains(Double_t *point) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrd2::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTrd2::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the trd2
 // Boundary safe algorithm
@@ -259,7 +259,7 @@ Double_t TGeoTrd2::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrd2::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTrd2::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the trd2
 // Boundary safe algorithm
@@ -395,7 +395,7 @@ Double_t TGeoTrd2::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
 }         
             
 //_____________________________________________________________________________
-void TGeoTrd2::GetVisibleCorner(Double_t *point, Double_t *vertex, Double_t *normals) const
+void TGeoTrd2::GetVisibleCorner(const Double_t *point, Double_t *vertex, Double_t *normals) const
 {
 // get the most visible corner from outside point and the normals
    Double_t fx = 0.5*(fDx1-fDx2)/fDz;
@@ -441,7 +441,7 @@ void TGeoTrd2::GetVisibleCorner(Double_t *point, Double_t *vertex, Double_t *nor
 }
 
 //_____________________________________________________________________________
-void TGeoTrd2::GetOppositeCorner(Double_t * /*point*/, Int_t inorm, Double_t *vertex, Double_t *normals) const
+void TGeoTrd2::GetOppositeCorner(const Double_t * /*point*/, Int_t inorm, Double_t *vertex, Double_t *normals) const
 {
 // get the opposite corner of the intersected face
    TGeoTrd2 *trd2 = (TGeoTrd2*)this;
@@ -617,7 +617,7 @@ void TGeoTrd2::InspectShape() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTrd2::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoTrd2::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -735,3 +735,43 @@ void TGeoTrd2::Sizeof3D() const
    TGeoBBox::Sizeof3D();
 }
 
+//_____________________________________________________________________________
+void TGeoTrd2::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd2::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd2::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd2::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTrd2::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoTube.cxx b/geom/geom/src/TGeoTube.cxx
index 45d0afd..1f43c7d 100644
--- a/geom/geom/src/TGeoTube.cxx
+++ b/geom/geom/src/TGeoTube.cxx
@@ -190,7 +190,7 @@ void TGeoTube::ComputeBBox()
 }
 
 //_____________________________________________________________________________
-void TGeoTube::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoTube::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t saf[3];
@@ -216,7 +216,7 @@ void TGeoTube::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-void TGeoTube::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+void TGeoTube::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                               Double_t /*rmin*/, Double_t /*rmax*/, Double_t /*dz*/)
 {
 // Compute normal to closest surface from POINT.
@@ -231,7 +231,7 @@ void TGeoTube::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoTube::Contains(Double_t *point) const
+Bool_t TGeoTube::Contains(const Double_t *point) const
 {
 // test if point is inside this tube
    if (TMath::Abs(point[2]) > fDz) return kFALSE;
@@ -251,7 +251,7 @@ Int_t TGeoTube::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTube::DistFromInsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
+Double_t TGeoTube::DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
 {
 // Compute distance from inside point to surface of the tube (static)
 // Boundary safe algorithm.
@@ -297,7 +297,7 @@ Double_t TGeoTube::DistFromInsideS(Double_t *point, Double_t *dir, Double_t rmin
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTube::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTube::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the tube
 // Boundary safe algorithm.
@@ -311,7 +311,7 @@ Double_t TGeoTube::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTube::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
+Double_t TGeoTube::DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz)
 {
 // Static method to compute distance from outside point to a tube with given parameters
 // Boundary safe algorithm.
@@ -398,7 +398,7 @@ Double_t TGeoTube::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t rmi
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTube::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTube::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from outside point to surface of the tube and safe distance
 // Boundary safe algorithm.
@@ -782,7 +782,7 @@ void TGeoTube::SetSegsAndPols(TBuffer3D &buffer) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTube::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoTube::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -821,7 +821,7 @@ Double_t TGeoTube::Safety(Double_t *point, Bool_t in) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTube::SafetyS(Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz)
+Double_t TGeoTube::SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz, Int_t skipz)
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -1130,6 +1130,47 @@ const TBuffer3D & TGeoTube::GetBuffer3D(Int_t reqSections, Bool_t localFrame) co
    return buffer;
 }
 
+//_____________________________________________________________________________
+void TGeoTube::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTube::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTube::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTube::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTube::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
+
 ClassImp(TGeoTubeSeg)
 
 //_____________________________________________________________________________
@@ -1247,7 +1288,7 @@ void TGeoTubeSeg::ComputeBBox()
 }
 
 //_____________________________________________________________________________
-void TGeoTubeSeg::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoTubeSeg::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t saf[3];
@@ -1281,7 +1322,7 @@ void TGeoTubeSeg::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-void TGeoTubeSeg::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
+void TGeoTubeSeg::ComputeNormalS(const Double_t *point, const Double_t *dir, Double_t *norm,
                                  Double_t rmin, Double_t rmax, Double_t /*dz*/,
                                  Double_t c1, Double_t s1, Double_t c2, Double_t s2)
 {
@@ -1307,7 +1348,7 @@ void TGeoTubeSeg::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoTubeSeg::Contains(Double_t *point) const
+Bool_t TGeoTubeSeg::Contains(const Double_t *point) const
 {
 // test if point is inside this tube segment
    // first check if point is inside the tube
@@ -1325,7 +1366,7 @@ Int_t TGeoTubeSeg::DistancetoPrimitive(Int_t px, Int_t py)
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTubeSeg::DistFromInsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz,
+Double_t TGeoTubeSeg::DistFromInsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax, Double_t dz,
                                  Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
 {
 // Compute distance from inside point to surface of the tube segment (static)
@@ -1373,7 +1414,7 @@ Double_t TGeoTubeSeg::DistFromInsideS(Double_t *point, Double_t *dir, Double_t r
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTubeSeg::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTubeSeg::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // Compute distance from inside point to surface of the tube segment
 // Boundary safe algorithm.
@@ -1400,7 +1441,7 @@ Double_t TGeoTubeSeg::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTubeSeg::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t rmin, Double_t rmax,
+Double_t TGeoTubeSeg::DistFromOutsideS(const Double_t *point, const Double_t *dir, Double_t rmin, Double_t rmax,
                                 Double_t dz, Double_t c1, Double_t s1, Double_t c2, Double_t s2,
                                 Double_t cm, Double_t sm, Double_t cdfi)
 {
@@ -1656,7 +1697,7 @@ Double_t TGeoTubeSeg::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTubeSeg::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoTubeSeg::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the tube segment
    // fist localize point w.r.t tube
@@ -1938,7 +1979,7 @@ void TGeoTubeSeg::SetSegsAndPols(TBuffer3D &buff) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTubeSeg::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoTubeSeg::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -1967,7 +2008,7 @@ Double_t TGeoTubeSeg::Safety(Double_t *point, Bool_t in) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoTubeSeg::SafetyS(Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz,
+Double_t TGeoTubeSeg::SafetyS(const Double_t *point, Bool_t in, Double_t rmin, Double_t rmax, Double_t dz,
                               Double_t phi1, Double_t phi2, Int_t skipz)
 {
 // Static method to compute the closest distance from given point to this shape.
@@ -2239,6 +2280,47 @@ const TBuffer3D & TGeoTubeSeg::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
    return buffer;
 }
 
+//_____________________________________________________________________________
+void TGeoTubeSeg::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTubeSeg::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTubeSeg::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTubeSeg::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoTubeSeg::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
+
 ClassImp(TGeoCtub)
 
 TGeoCtub::TGeoCtub()
@@ -2409,7 +2491,7 @@ void TGeoCtub::ComputeBBox()
 }
 
 //_____________________________________________________________________________
-void TGeoCtub::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
+void TGeoCtub::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT.
    Double_t saf[4];
@@ -2463,7 +2545,7 @@ void TGeoCtub::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoCtub::Contains(Double_t *point) const
+Bool_t TGeoCtub::Contains(const Double_t *point) const
 {
 // check if point is contained in the cut tube
    // check the lower cut plane
@@ -2520,7 +2602,7 @@ Double_t TGeoCtub::GetZcoord(Double_t xc, Double_t yc, Double_t zc) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCtub::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoCtub::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the cut tube
    if (iact<3 && safe) {
@@ -2676,7 +2758,7 @@ Double_t TGeoCtub::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, D
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCtub::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoCtub::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the cut tube
    if (iact<3 && safe) *safe = Safety(point, kTRUE);
@@ -2794,7 +2876,7 @@ void TGeoCtub::InspectShape() const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoCtub::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoCtub::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -3015,3 +3097,44 @@ const TBuffer3D & TGeoCtub::GetBuffer3D(Int_t reqSections, Bool_t localFrame) co
 
    return buffer;
 }
+
+//_____________________________________________________________________________
+void TGeoCtub::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCtub::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCtub::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCtub::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoCtub::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TGeoVolume.cxx b/geom/geom/src/TGeoVolume.cxx
index bba5366..efdf7e6 100644
--- a/geom/geom/src/TGeoVolume.cxx
+++ b/geom/geom/src/TGeoVolume.cxx
@@ -500,7 +500,7 @@ void TGeoVolume::Browse(TBrowser *b)
    TString title;
    for (Int_t i=0; i<GetNdaughters(); i++) { 
       daughter = GetNode(i)->GetVolume();
-      if(!strlen(daughter->GetTitle())) {
+      if(daughter->GetTitle()[0]) {
          if (daughter->IsAssembly()) title.TString::Format("Assembly with %d daughter(s)", 
                                                 daughter->GetNdaughters());
          else if (daughter->GetFinder()) {
@@ -628,7 +628,7 @@ void TGeoVolume::CheckShapes()
    for (Int_t i=0; i<nd; i++) {
       node=(TGeoNode*)fNodes->At(i);
       // check if node has name
-      if (!strlen(node->GetName())) printf("Daughter %i of volume %s - NO NAME!!!\n",
+      if (!node->GetName()[0]) printf("Daughter %i of volume %s - NO NAME!!!\n",
                                            i, GetName());
       old_vol = node->GetVolume();
       shape = old_vol->GetShape();
@@ -638,6 +638,10 @@ void TGeoVolume::CheckShapes()
 //         old_vol->InspectShape();
          // make a copy of the node
          new_node = node->MakeCopyNode();
+         if (!new_node) {
+            Fatal("CheckShapes", "Cannot make copy node for %s", node->GetName());
+            return;
+         }   
          TGeoShape *new_shape = shape->GetMakeRuntimeShape(fShape, node->GetMatrix());
          if (!new_shape) {
             Error("CheckShapes","cannot resolve runtime shape for volume %s/%s\n",
@@ -804,7 +808,7 @@ TGeoVolume *TGeoVolume::Import(const char *filename, const char *name, Option_t
          printf("Error: TGeoVolume::Import : Cannot open file %s\n", filename);
          return 0;
       }
-      if (name && strlen(name) > 0) {
+      if (name && name[0]) {
          volume = (TGeoVolume*)f->Get(name);
       } else {
          TIter next(f->GetListOfKeys());
@@ -907,8 +911,8 @@ void TGeoVolume::AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat,
    node->SetMotherVolume(this);
    fNodes->Add(node);
    TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
-   if (fNodes->FindObject(name))
-      Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
+//   if (fNodes->FindObject(name))
+//      Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
    node->SetName(name);
    node->SetNumber(copy_no);
 }
@@ -1092,7 +1096,7 @@ void TGeoVolume::Draw(Option_t *option)
    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
    TGeoAtt::SetVisRaytrace(kFALSE);
    if (!IsVisContainers()) SetVisLeaves();
-   if (option && strlen(option) > 0) {
+   if (option && option[0] > 0) {
       painter->DrawVolume(this, option); 
    } else {
       painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
@@ -1111,7 +1115,7 @@ void TGeoVolume::DrawOnly(Option_t *option)
    SetVisOnly();
    TGeoAtt::SetVisRaytrace(kFALSE);
    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
-   if (option && strlen(option) > 0) {
+   if (option && option[0] > 0) {
       painter->DrawVolume(this, option); 
    } else {
       painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
@@ -1135,7 +1139,7 @@ void TGeoVolume::Paint(Option_t *option)
    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
    painter->SetTopVolume(this);
 //   painter->Paint(option);   
-   if (option && strlen(option) > 0) {
+   if (option && option[0] > 0) {
       painter->Paint(option); 
    } else {
       painter->Paint(gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
@@ -1368,7 +1372,7 @@ void TGeoVolume::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
    // check if we need to save shape/volume
    Bool_t mustDraw = kFALSE;
    if (fGeoManager->GetGeomPainter()->GetTopVolume()==this) mustDraw = kTRUE;
-   if (!strlen(option)) {
+   if (!option[0]) {
       fGeoManager->SetAllIndex();
       out << "   new TGeoManager(\"" << fGeoManager->GetName() << "\", \"" << fGeoManager->GetTitle() << "\");" << std::endl << std::endl;
 //      if (mustDraw) out << "   Bool_t mustDraw = kTRUE;" << std::endl;
@@ -1674,6 +1678,10 @@ void TGeoVolume::CloneNodesAndConnect(TGeoVolume *newmother) const
    for (Int_t i=0; i<nd; i++) {
       //create copies of nodes and add them to list
       node = GetNode(i)->MakeCopyNode();
+      if (!node) {
+         Fatal("CloneNodesAndConnect", "cannot make copy node");
+         return;
+      }   
       node->SetMotherVolume(newmother);
       list->Add(node);
    }
@@ -1734,13 +1742,17 @@ TGeoVolume *TGeoVolume::MakeReflectedVolume(const char *newname) const
    }   
    TGeoVolume *vol = (TGeoVolume*)map.GetValue(this);
    if (vol) {
-      if (strlen(newname)) vol->SetName(newname);
+      if (newname && newname[0]) vol->SetName(newname);
       return vol;
    }
 //   printf("Making reflection for volume: %s\n", GetName());   
    vol = CloneVolume();
+   if (!vol) {
+      Fatal("MakeReflectedVolume", "Cannot clone volume %s\n", GetName());
+      return 0;
+   }   
    map.Add((TObject*)this, vol);
-   if (strlen(newname)) vol->SetName(newname);
+   if (newname && newname[0]) vol->SetName(newname);
    delete vol->GetNodes();
    vol->SetNodes(NULL);
    vol->SetBit(kVolumeImportNodes, kFALSE);
@@ -1790,6 +1802,10 @@ TGeoVolume *TGeoVolume::MakeReflectedVolume(const char *newname) const
    // Volume is divided, so we have to reflect the division.
 //   printf("   ... divided %s\n", fFinder->ClassName());
    TGeoPatternFinder *new_finder = fFinder->MakeCopy(kTRUE);
+   if (!new_finder) {
+      Fatal("MakeReflectedVolume", "Could not copy finder for volume %s", GetName());
+      return 0;
+   }   
    new_finder->SetVolume(vol);
    vol->SetFinder(new_finder);
    TGeoNodeOffset *nodeoff;
@@ -1943,9 +1959,9 @@ Int_t TGeoVolume::GetByteCount() const
 {
 // get the total size in bytes for this volume
    Int_t count = 28+2+6+4+0;    // TNamed+TGeoAtt+TAttLine+TAttFill+TAtt3D
-   count += strlen(GetName()) + strlen(GetTitle()); // name+title
-   count += 4+4+4+4+4; // fShape + fMedium + fFinder + fField + fNodes
-   count += 8 + strlen(fOption.Data()); // fOption
+   count += fName.Capacity() + fTitle.Capacity(); // name+title
+   count += 7*sizeof(char*); // fShape + fMedium + fFinder + fField + fNodes + 2 extensions
+   count += fOption.Capacity(); // fOption
    if (fShape)  count += fShape->GetByteCount();
    if (fFinder) count += fFinder->GetByteCount();
    if (fNodes) {
@@ -2019,6 +2035,10 @@ TGeoNode *TGeoVolume::ReplaceNode(TGeoNode *nodeorig, TGeoShape *newshape, TGeoM
    // Make a copy of the node
    TGeoNode *newnode = nodeorig->MakeCopyNode();
    // Change the volume for the new node
+   if (!newnode) {
+      Fatal("ReplaceNode", "Cannot make copy node for %s", nodeorig->GetName());
+      return 0;
+   }   
    newnode->SetVolume(vol);
    // Replace the matrix
    if (newpos && !nodeorig->IsOffset()) {
@@ -2123,6 +2143,7 @@ Bool_t TGeoVolume::FindMatrixOfDaughterVolume(TGeoVolume *vol) const
    Int_t nd = GetNdaughters();
    if (!nd) return kFALSE;
    TGeoHMatrix *global = fGeoManager->GetHMatrix();
+   if (!global) return kFALSE;
    TGeoNode *dnode;
    TGeoVolume *dvol;
    TGeoMatrix *local;
@@ -2309,6 +2330,10 @@ void TGeoVolumeMulti::AddVolume(TGeoVolume *vol)
    TGeoVolume *cell;
    if (fDivision) {
       div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
+      if (!div) {
+         Fatal("AddVolume", "Cannot divide volume %s", vol->GetName());
+         return;
+      }   
       for (Int_t i=0; i<div->GetNvolumes(); i++) {
          cell = div->GetVolume(i);
          fDivision->AddVolume(cell);
@@ -2365,7 +2390,15 @@ void TGeoVolumeMulti::AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoM
 //   printf("--- vmulti %s : node ovlp %s added to %i components\n", GetName(), vol->GetName(), nvolumes);
 }
 
-
+//_____________________________________________________________________________
+TGeoShape *TGeoVolumeMulti::GetLastShape() const
+{
+// Returns the last shape.
+   TGeoVolume *vol = GetVolume(fVolumes->GetEntriesFast()-1);
+   if (!vol) return 0;
+   return vol->GetShape();
+}
+   
 //_____________________________________________________________________________
 TGeoVolume *TGeoVolumeMulti::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, const char *option)
 {
@@ -2443,6 +2476,10 @@ TGeoVolume *TGeoVolumeMulti::MakeCopyVolume(TGeoShape *newshape)
    if (fDivision) {
       TGeoVolume *cell;
       TGeoVolumeMulti *div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
+      if (!div) {
+         Fatal("MakeCopyVolume", "Cannot divide volume %s", vol->GetName());
+         return 0;
+      }   
       for (i=0; i<div->GetNvolumes(); i++) {
          cell = div->GetVolume(i);
          fDivision->AddVolume(cell);
@@ -2461,6 +2498,10 @@ TGeoVolume *TGeoVolumeMulti::MakeCopyVolume(TGeoShape *newshape)
    for (i=0; i<nd; i++) {
       //create copies of nodes and add them to list
       node = GetNode(i)->MakeCopyNode();
+      if (!node) {
+         Fatal("MakeCopyNode", "cannot make copy node for daughter %d of %s", i, GetName());
+         return 0;
+      }   
       node->SetMotherVolume(vol);
       list->Add(node);
    }
@@ -2595,6 +2636,7 @@ void TGeoVolumeAssembly::CreateThreadData(Int_t nthreads)
          fThreadData[tid] = new ThreadData_t;
       }
    }      
+   TGeoVolume::CreateThreadData(nthreads);
    TThread::UnLock();
 }
 
diff --git a/geom/geom/src/TGeoVoxelFinder.cxx b/geom/geom/src/TGeoVoxelFinder.cxx
index 98135e2..bfe088e 100644
--- a/geom/geom/src/TGeoVoxelFinder.cxx
+++ b/geom/geom/src/TGeoVoxelFinder.cxx
@@ -302,7 +302,7 @@ void TGeoVoxelFinder::BuildVoxelLimits()
 }
 
 //_____________________________________________________________________________
-void TGeoVoxelFinder::DaughterToMother(Int_t id, Double_t *local, Double_t *master) const
+void TGeoVoxelFinder::DaughterToMother(Int_t id, const Double_t *local, Double_t *master) const
 {
 // convert a point from the local reference system of node id to reference
 // system of mother volume
@@ -311,7 +311,7 @@ void TGeoVoxelFinder::DaughterToMother(Int_t id, Double_t *local, Double_t *mast
    else      mat->LocalToMaster(local, master);
 }
 //_____________________________________________________________________________
-Bool_t TGeoVoxelFinder::IsSafeVoxel(Double_t *point, Int_t inode, Double_t minsafe) const
+Bool_t TGeoVoxelFinder::IsSafeVoxel(const Double_t *point, Int_t inode, Double_t minsafe) const
 {
 // Computes squared distance from POINT to the voxel(s) containing node INODE. Returns 0
 // if POINT inside voxel(s).
@@ -430,7 +430,7 @@ void TGeoVoxelFinder::FindOverlaps(Int_t inode) const
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoVoxelFinder::GetIndices(Double_t *point, TGeoStateInfo &td)
+Bool_t TGeoVoxelFinder::GetIndices(const Double_t *point, TGeoStateInfo &td)
 {
 // Getindices for current slices on x, y, z
    td.fVoxSlices[0] = -2; // -2 means 'all daughters in slice'
@@ -587,7 +587,7 @@ Int_t *TGeoVoxelFinder::GetValidExtra(Int_t /*n1*/, UChar_t *array1, Int_t /*n2*
 }      
 
 //_____________________________________________________________________________
-Int_t *TGeoVoxelFinder::GetNextCandidates(Double_t *point, Int_t &ncheck, TGeoStateInfo &td)
+Int_t *TGeoVoxelFinder::GetNextCandidates(const Double_t *point, Int_t &ncheck, TGeoStateInfo &td)
 {
 // Returns list of new candidates in next voxel. If NULL, nowhere to
 // go next. 
@@ -1148,7 +1148,7 @@ Int_t *TGeoVoxelFinder::GetNextCandidates(Double_t *point, Int_t &ncheck, TGeoSt
 }
 
 //_____________________________________________________________________________
-void TGeoVoxelFinder::SortCrossedVoxels(Double_t *point, Double_t *dir, TGeoStateInfo &td)
+void TGeoVoxelFinder::SortCrossedVoxels(const Double_t *point, const Double_t *dir, TGeoStateInfo &td)
 {
 // get the list in the next voxel crossed by a ray
    if (NeedRebuild()) {
@@ -1281,7 +1281,7 @@ void TGeoVoxelFinder::SortCrossedVoxels(Double_t *point, Double_t *dir, TGeoStat
 }   
 
 //_____________________________________________________________________________
-Int_t *TGeoVoxelFinder::GetCheckList(Double_t *point, Int_t &nelem, TGeoStateInfo &td)
+Int_t *TGeoVoxelFinder::GetCheckList(const Double_t *point, Int_t &nelem, TGeoStateInfo &td)
 {
 // get the list of daughter indices for which point is inside their bbox
    if (NeedRebuild()) {
@@ -1439,7 +1439,7 @@ Int_t *TGeoVoxelFinder::GetVoxelCandidates(Int_t i, Int_t j, Int_t k, Int_t &nch
 }     
 
 //_____________________________________________________________________________
-Int_t *TGeoVoxelFinder::GetNextVoxel(Double_t *point, Double_t * /*dir*/, Int_t &ncheck, TGeoStateInfo &td)
+Int_t *TGeoVoxelFinder::GetNextVoxel(const Double_t *point, const Double_t * /*dir*/, Int_t &ncheck, TGeoStateInfo &td)
 {
 // get the list of new candidates for the next voxel crossed by current ray
 //   printf("### GetNextVoxel\n");
@@ -2246,7 +2246,7 @@ void TGeoVoxelFinder::Print(Option_t *) const
 }
 
 //_____________________________________________________________________________
-void TGeoVoxelFinder::PrintVoxelLimits(Double_t *point) const
+void TGeoVoxelFinder::PrintVoxelLimits(const Double_t *point) const
 {
 // print the voxel containing point
    if (NeedRebuild()) {
diff --git a/geom/geom/src/TGeoXtru.cxx b/geom/geom/src/TGeoXtru.cxx
index e04d7fa..9b98543 100644
--- a/geom/geom/src/TGeoXtru.cxx
+++ b/geom/geom/src/TGeoXtru.cxx
@@ -172,24 +172,37 @@ void TGeoXtru::SetSeg(Int_t iseg)
 
 //_____________________________________________________________________________
 TGeoXtru::TGeoXtru()
+         :TGeoBBox(),
+          fNvert(0),
+          fNz(0),
+          fZcurrent(0.),
+          fX(0),
+          fY(0),
+          fZ(0),
+          fScale(0),
+          fX0(0),
+          fY0(0),
+          fThreadData(0),
+          fThreadSize(0)
 {
 // dummy ctor
    SetShapeBit(TGeoShape::kGeoXtru);
-   fNvert = 0;
-   fNz = 0;
-   fZcurrent = 0.;
-   fX = 0;
-   fY = 0;
-   fZ = 0;
-   fScale = 0;
-   fX0 = 0;
-   fY0 = 0;
-   fThreadSize = 0;
 }   
 
 //_____________________________________________________________________________
 TGeoXtru::TGeoXtru(Int_t nz)
-         :TGeoBBox(0, 0, 0)
+         :TGeoBBox(0, 0, 0),
+          fNvert(0),
+          fNz(nz),
+          fZcurrent(0.),
+          fX(0),
+          fY(0),
+          fZ(new Double_t[nz]),
+          fScale(new Double_t[nz]),
+          fX0(new Double_t[nz]),
+          fY0(new Double_t[nz]),
+          fThreadData(0),
+          fThreadSize(0)         
 {
 // Default constructor
    SetShapeBit(TGeoShape::kGeoXtru);
@@ -198,21 +211,22 @@ TGeoXtru::TGeoXtru(Int_t nz)
       SetShapeBit(TGeoShape::kGeoBad);
       return;
    }
-   fNvert = 0;
-   fNz = nz;   
-   fZcurrent = 0.;
-   fX = 0;
-   fY = 0;
-   fZ = new Double_t[nz];
-   fScale = new Double_t[nz];
-   fX0 = new Double_t[nz];
-   fY0 = new Double_t[nz];
-   fThreadSize = 0;
 }
 
 //_____________________________________________________________________________
 TGeoXtru::TGeoXtru(Double_t *param)
-         :TGeoBBox(0, 0, 0)
+         :TGeoBBox(0, 0, 0),
+          fNvert(0),
+          fNz(0),
+          fZcurrent(0.),
+          fX(0),
+          fY(0),
+          fZ(0),
+          fScale(0),
+          fX0(0),
+          fY0(0),
+          fThreadData(0),
+          fThreadSize(0)         
 {
 // Default constructor in GEANT3 style
 // param[0] = nz  // number of z planes
@@ -227,31 +241,22 @@ TGeoXtru::TGeoXtru(Double_t *param)
 // param[4*(nz-1)+3] = yn
 // param[4*(nz-1)+4] = scalen
    SetShapeBit(TGeoShape::kGeoXtru);
-   fNvert = 0;
-   fNz = 0;
-   fZcurrent = 0.;
-   fX = 0;
-   fY = 0;
-   fZ = 0;
-   fScale = 0;
-   fX0 = 0;
-   fY0 = 0;
-   fThreadSize = 0;
    SetDimensions(param);
 }
 
 //_____________________________________________________________________________
 TGeoXtru::TGeoXtru(const TGeoXtru& xt) :
   TGeoBBox(xt),
-  fNvert(xt.fNvert),
-  fNz(xt.fNz),
-  fZcurrent(xt.fZcurrent),
-  fX(xt.fX),
-  fY(xt.fY),
-  fZ(xt.fZ),
-  fScale(xt.fScale),
-  fX0(xt.fX0),
-  fY0(xt.fY0),
+  fNvert(0),
+  fNz(0),
+  fZcurrent(0),
+  fX(0),
+  fY(0),
+  fZ(0),
+  fScale(0),
+  fX0(0),
+  fY0(0),
+  fThreadData(0),
   fThreadSize(0)
 { 
    //copy constructor
@@ -263,16 +268,16 @@ TGeoXtru& TGeoXtru::operator=(const TGeoXtru& xt)
    //assignment operator
    if(this!=&xt) {
       TGeoBBox::operator=(xt);
-      fNvert=xt.fNvert;
-      fNz=xt.fNz;
-      fZcurrent=xt.fZcurrent;
-      fX=xt.fX;
-      fY=xt.fY;
-      fZ=xt.fZ;
-      fScale=xt.fScale;
-      fX0=xt.fX0;
-      fY0=xt.fY0;
-      ClearThreadData();
+      fNvert=0;
+      fNz=0;
+      fZcurrent=0;
+      fX=0;
+      fY=0;
+      fZ=0;
+      fScale=0;
+      fX0=0;
+      fY0=0;
+      fThreadSize=0;
    } 
    return *this;
 }
@@ -345,7 +350,7 @@ void TGeoXtru::ComputeBBox()
 }   
 
 //_____________________________________________________________________________   
-void TGeoXtru::ComputeNormal(Double_t * /*point*/, Double_t *dir, Double_t *norm)
+void TGeoXtru::ComputeNormal(const Double_t * /*point*/, const Double_t *dir, Double_t *norm)
 {
 // Compute normal to closest surface from POINT. 
    ThreadData_t& td = GetThreadData();
@@ -366,7 +371,7 @@ void TGeoXtru::ComputeNormal(Double_t * /*point*/, Double_t *dir, Double_t *norm
 }
 
 //_____________________________________________________________________________
-Bool_t TGeoXtru::Contains(Double_t *point) const
+Bool_t TGeoXtru::Contains(const Double_t *point) const
 {
 // test if point is inside this shape
    ThreadData_t& td = GetThreadData();
@@ -412,7 +417,7 @@ void TGeoXtru::DrawPolygon(Option_t *option)
 }
    
 //_____________________________________________________________________________
-Double_t TGeoXtru::DistToPlane(Double_t *point, Double_t *dir, Int_t iz, Int_t ivert, Double_t stepmax, Bool_t in) const
+Double_t TGeoXtru::DistToPlane(const Double_t *point, const Double_t *dir, Int_t iz, Int_t ivert, Double_t stepmax, Bool_t in) const
 {
 // Compute distance to a Xtru lateral surface.
    ThreadData_t& td = GetThreadData();
@@ -442,16 +447,17 @@ Double_t TGeoXtru::DistToPlane(Double_t *point, Double_t *dir, Int_t iz, Int_t i
       safe = (vert[0]-point[0])*norm[0]+
              (vert[1]-point[1])*norm[1]+
              (vert[2]-point[2])*norm[2];
-      if (safe<0) return TGeoShape::Big(); // direction outwards plane
+      if (safe<-1.E-8) return TGeoShape::Big(); // direction outwards plane
    } else {
       ndotd = -ndotd;
       if (ndotd<=0) return TGeoShape::Big(); 
       safe = (point[0]-vert[0])*norm[0]+
              (point[1]-vert[1])*norm[1]+
              (point[2]-vert[2])*norm[2];
-      if (safe<0) return TGeoShape::Big(); // direction outwards plane
+      if (safe<-1.E-8) return TGeoShape::Big(); // direction outwards plane
    }      
    snext = safe/ndotd;
+   if (snext<0) return 0.;
    if (snext>stepmax) return TGeoShape::Big();
    if (fZ[iz]<fZ[iz+1]) {
       znew = point[2] + snext*dir[2];
@@ -466,7 +472,7 @@ Double_t TGeoXtru::DistToPlane(Double_t *point, Double_t *dir, Int_t iz, Int_t i
 }
 
 //_____________________________________________________________________________
-Double_t TGeoXtru::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoXtru::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from inside point to surface of the polycone
    // locate Z segment
@@ -517,6 +523,7 @@ Double_t TGeoXtru::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
             if (convex) return snext;
          }   
       }
+      if (snext < 1.E10) return snext;
       return TGeoShape::Tolerance();
    }      
    
@@ -578,7 +585,7 @@ Double_t TGeoXtru::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Do
 }
 
 //_____________________________________________________________________________
-Double_t TGeoXtru::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
+Double_t TGeoXtru::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
 {
 // compute distance from outside point to surface of the tube
 //   Warning("DistFromOutside", "not implemented");
@@ -834,7 +841,7 @@ void TGeoXtru::GetPlaneVertices(Int_t iz, Int_t ivert, Double_t *vert) const
    }
 }
 //_____________________________________________________________________________
-Bool_t TGeoXtru::IsPointInsidePlane(Double_t *point, Double_t *vert, Double_t *norm) const
+Bool_t TGeoXtru::IsPointInsidePlane(const Double_t *point, Double_t *vert, Double_t *norm) const
 {
 // Check if the quadrilateral defined by VERT contains a coplanar POINT.
    Double_t v1[3], v2[3];
@@ -960,7 +967,7 @@ void TGeoXtru::SetSegsAndPols(TBuffer3D &buff) const
 }
 
 //_____________________________________________________________________________
-Double_t TGeoXtru::SafetyToSector(Double_t *point, Int_t iz, Double_t safmin, Bool_t in)
+Double_t TGeoXtru::SafetyToSector(const Double_t *point, Int_t iz, Double_t safmin, Bool_t in)
 {
 // Compute safety to sector iz, returning also the closest segment index.
    ThreadData_t& td = GetThreadData();
@@ -1013,7 +1020,7 @@ Double_t TGeoXtru::SafetyToSector(Double_t *point, Int_t iz, Double_t safmin, Bo
       saf1 = (point[0]-vert[0])*norm[0]+(point[1]-vert[1])*norm[1]+(point[2]-vert[2])*norm[2];
       if (in) saf1 = -saf1;
 //      printf("segment %d: (%f,%f)-(%f,%f) norm=(%f,%f,%f): saf1=%f\n", iseg, vert[0],vert[1],vert[3],vert[4],norm[0],norm[1],norm[2],saf1);
-      if (saf1<0) continue;
+      if (saf1<-1.E-8) continue;
       safe = TMath::Max(safz, saf1);
       safe = TMath::Abs(safe);
       if (safe>safmin) continue;
@@ -1025,7 +1032,7 @@ Double_t TGeoXtru::SafetyToSector(Double_t *point, Int_t iz, Double_t safmin, Bo
 }
 
 //_____________________________________________________________________________
-Double_t TGeoXtru::Safety(Double_t *point, Bool_t in) const
+Double_t TGeoXtru::Safety(const Double_t *point, Bool_t in) const
 {
 // computes the closest distance from given point to this shape, according
 // to option. The matching point on the shape is stored in spoint.
@@ -1280,3 +1287,44 @@ const TBuffer3D & TGeoXtru::GetBuffer3D(Int_t reqSections, Bool_t localFrame) co
       
    return buffer;
 }
+
+//_____________________________________________________________________________
+void TGeoXtru::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
+{
+// Check the inside status for each of the points in the array.
+// Input: Array of point coordinates + vector size
+// Output: Array of Booleans for the inside of each point
+   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
+{
+// Compute the normal for an array o points so that norm.dot.dir is positive
+// Input: Arrays of point coordinates and directions + vector size
+// Output: Array of normal directions
+   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
+{
+// Compute distance from array of input points having directions specisied by dirs. Store output in dists
+   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
+}
+
+//_____________________________________________________________________________
+void TGeoXtru::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
+{
+// Compute safe distance from each of the points in the input array.
+// Input: Array of point coordinates, array of statuses for these points, size of the arrays
+// Output: Safety values
+   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
+}
diff --git a/geom/geom/src/TVirtualGeoTrack.cxx b/geom/geom/src/TVirtualGeoTrack.cxx
index 027ffe4..f421e00 100644
--- a/geom/geom/src/TVirtualGeoTrack.cxx
+++ b/geom/geom/src/TVirtualGeoTrack.cxx
@@ -89,6 +89,18 @@ TVirtualGeoTrack::~TVirtualGeoTrack()
 }
 
 //______________________________________________________________________________
+Int_t TVirtualGeoTrack::GetDaughterId(Int_t index) const
+{
+// Returns daughter id.
+   TVirtualGeoTrack *daughter = GetDaughter(index);
+   if (!daughter) {
+      Error("GetDaughterId", "No daughter track with index %d", index);
+      return -1;
+   }   
+   return daughter->GetId();
+}
+
+//______________________________________________________________________________
 TVirtualGeoTrack *TVirtualGeoTrack::FindTrackWithId(Int_t id) const
 {
 // Recursively search through this track for a daughter
diff --git a/graf2d/asimage/src/TASImage.cxx b/graf2d/asimage/src/TASImage.cxx
index 1bf82c8..3082468 100644
--- a/graf2d/asimage/src/TASImage.cxx
+++ b/graf2d/asimage/src/TASImage.cxx
@@ -5740,13 +5740,12 @@ void TASImage::DrawText(TText *text, Int_t x, Int_t y)
    Int_t wh = gPad->XtoPixel(gPad->GetX2());
    Int_t hh = gPad->YtoPixel(gPad->GetY1());
 
-   // set text size in pixels
-   Int_t ttfsize;
-
+   // set text size
+   Float_t ttfsize;
    if (wh < hh) {
-      ttfsize = (Int_t)(text->GetTextSize()*wh);
+      ttfsize = text->GetTextSize()*wh;
    } else {
-      ttfsize = (Int_t)(text->GetTextSize()*hh);
+      ttfsize = text->GetTextSize()*hh;
    }
    TTF::SetTextSize(ttfsize);
 
diff --git a/graf2d/asimage/src/libAfterImage/libpng/LICENSE b/graf2d/asimage/src/libAfterImage/libpng/LICENSE
index 5d70f16..a684fe5 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/LICENSE
+++ b/graf2d/asimage/src/libAfterImage/libpng/LICENSE
@@ -8,8 +8,10 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
 If you modify libpng you may insert additional notices immediately following
 this sentence.
 
-libpng versions 1.2.6, August 15, 2004, through 1.2.23, November 6, 2007, are
-Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are
+This code is released under the libpng license.
+
+libpng versions 1.2.6, August 15, 2004, through 1.2.50, July 10, 2012, are
+Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
 
@@ -106,4 +108,4 @@ certification mark of the Open Source Initiative.
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-November 6, 2007
+July 10, 2012
diff --git a/graf2d/asimage/src/libAfterImage/libpng/png.c b/graf2d/asimage/src/libAfterImage/libpng/png.c
index 04dea60..18d26db 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/png.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/png.c
@@ -1,22 +1,27 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.2.21 October 4, 2007
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.46 [February 25, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
  */
 
 #define PNG_INTERNAL
 #define PNG_NO_EXTERN
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef version_1_2_23 Your_png_h_is_not_version_1_2_23;
+typedef version_1_2_50 Your_png_h_is_not_version_1_2_50;
 
 /* Version information for C files.  This had better match the version
- * string defined in png.h.  */
+ * string defined in png.h.
+ */
 
 #ifdef PNG_USE_GLOBAL_ARRAYS
 /* png_libpng_ver was changed to a function in version 1.0.5c */
@@ -53,18 +58,18 @@ PNG_tRNS;
 PNG_zTXt;
 
 #ifdef PNG_READ_SUPPORTED
-/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
-/* start of interlace block */
+/* Start of interlace block */
 PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
 
-/* offset to next interlace block */
+/* Offset to next interlace block */
 PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
 
-/* start of interlace block in the y direction */
+/* Start of interlace block in the y direction */
 PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
 
-/* offset to next interlace block in the y direction */
+/* Offset to next interlace block in the y direction */
 PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
 
 /* Height of interlace block.  This is not currently used - if you need
@@ -73,7 +78,8 @@ PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
 */
 
 /* Mask to determine which pixels are valid in a pass */
-PNG_CONST int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+PNG_CONST int FARDATA png_pass_mask[] =
+    {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
 
 /* Mask to determine which pixels to overwrite while displaying */
 PNG_CONST int FARDATA png_pass_dsp_mask[]
@@ -92,8 +98,11 @@ PNG_CONST int FARDATA png_pass_dsp_mask[]
 void PNGAPI
 png_set_sig_bytes(png_structp png_ptr, int num_bytes)
 {
-   if(png_ptr == NULL) return;
-   png_debug(1, "in png_set_sig_bytes\n");
+   png_debug(1, "in png_set_sig_bytes");
+
+   if (png_ptr == NULL)
+      return;
+
    if (num_bytes > 8)
       png_error(png_ptr, "Too many bytes for PNG signature.");
 
@@ -144,7 +153,7 @@ png_check_sig(png_bytep sig, int num)
 #ifdef PNG_1_0_X
 voidpf PNGAPI
 #else
-voidpf /* private */
+voidpf /* PRIVATE */
 #endif
 png_zalloc(voidpf png_ptr, uInt items, uInt size)
 {
@@ -153,7 +162,8 @@ png_zalloc(voidpf png_ptr, uInt items, uInt size)
    png_uint_32 save_flags=p->flags;
    png_uint_32 num_bytes;
 
-   if(png_ptr == NULL) return (NULL);
+   if (png_ptr == NULL)
+      return (NULL);
    if (items > PNG_UINT_32_MAX/size)
    {
      png_warning (p, "Potential overflow in png_zalloc()");
@@ -183,11 +193,11 @@ png_zalloc(voidpf png_ptr, uInt items, uInt size)
    return ((voidpf)ptr);
 }
 
-/* function to free memory for zlib */
+/* Function to free memory for zlib */
 #ifdef PNG_1_0_X
 void PNGAPI
 #else
-void /* private */
+void /* PRIVATE */
 #endif
 png_zfree(voidpf png_ptr, voidpf ptr)
 {
@@ -240,8 +250,11 @@ png_create_info_struct(png_structp png_ptr)
 {
    png_infop info_ptr;
 
-   png_debug(1, "in png_create_info_struct\n");
-   if(png_ptr == NULL) return (NULL);
+   png_debug(1, "in png_create_info_struct");
+
+   if (png_ptr == NULL)
+      return (NULL);
+
 #ifdef PNG_USER_MEM_SUPPORTED
    info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
       png_ptr->malloc_fn, png_ptr->mem_ptr);
@@ -263,9 +276,12 @@ void PNGAPI
 png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
 {
    png_infop info_ptr = NULL;
-   if(png_ptr == NULL) return;
 
-   png_debug(1, "in png_destroy_info_struct\n");
+   png_debug(1, "in png_destroy_info_struct");
+
+   if (png_ptr == NULL)
+      return;
+
    if (info_ptr_ptr != NULL)
       info_ptr = *info_ptr_ptr;
 
@@ -302,19 +318,20 @@ png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
 {
    png_infop info_ptr = *ptr_ptr;
 
-   if(info_ptr == NULL) return;
+   png_debug(1, "in png_info_init_3");
 
-   png_debug(1, "in png_info_init_3\n");
+   if (info_ptr == NULL)
+      return;
 
-   if(png_sizeof(png_info) > png_info_struct_size)
-     {
-       png_destroy_struct(info_ptr);
-       info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
-       *ptr_ptr = info_ptr;
-     }
+   if (png_sizeof(png_info) > png_info_struct_size)
+   {
+      png_destroy_struct(info_ptr);
+      info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+      *ptr_ptr = info_ptr;
+   }
 
-   /* set everything to 0 */
-   png_memset(info_ptr, 0, png_sizeof (png_info));
+   /* Set everything to 0 */
+   png_memset(info_ptr, 0, png_sizeof(png_info));
 }
 
 #ifdef PNG_FREE_ME_SUPPORTED
@@ -322,12 +339,14 @@ void PNGAPI
 png_data_freer(png_structp png_ptr, png_infop info_ptr,
    int freer, png_uint_32 mask)
 {
-   png_debug(1, "in png_data_freer\n");
+   png_debug(1, "in png_data_freer");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
-   if(freer == PNG_DESTROY_WILL_FREE_DATA)
+
+   if (freer == PNG_DESTROY_WILL_FREE_DATA)
       info_ptr->free_me |= mask;
-   else if(freer == PNG_USER_WILL_FREE_DATA)
+   else if (freer == PNG_USER_WILL_FREE_DATA)
       info_ptr->free_me &= ~mask;
    else
       png_warning(png_ptr,
@@ -339,249 +358,251 @@ void PNGAPI
 png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
    int num)
 {
-   png_debug(1, "in png_free_data\n");
+   png_debug(1, "in png_free_data");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-#if defined(PNG_TEXT_SUPPORTED)
-/* free text item num or (if num == -1) all text items */
+#ifdef PNG_TEXT_SUPPORTED
+   /* Free text item num or (if num == -1) all text items */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
+   if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
 #else
-if (mask & PNG_FREE_TEXT)
+   if (mask & PNG_FREE_TEXT)
 #endif
-{
-   if (num != -1)
    {
-     if (info_ptr->text && info_ptr->text[num].key)
-     {
-         png_free(png_ptr, info_ptr->text[num].key);
-         info_ptr->text[num].key = NULL;
-     }
-   }
-   else
-   {
-       int i;
-       for (i = 0; i < info_ptr->num_text; i++)
-           png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
-       png_free(png_ptr, info_ptr->text);
-       info_ptr->text = NULL;
-       info_ptr->num_text=0;
+      if (num != -1)
+      {
+         if (info_ptr->text && info_ptr->text[num].key)
+         {
+            png_free(png_ptr, info_ptr->text[num].key);
+            info_ptr->text[num].key = NULL;
+         }
+      }
+      else
+      {
+         int i;
+         for (i = 0; i < info_ptr->num_text; i++)
+             png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
+         png_free(png_ptr, info_ptr->text);
+         info_ptr->text = NULL;
+         info_ptr->num_text=0;
+      }
    }
-}
 #endif
 
-#if defined(PNG_tRNS_SUPPORTED)
-/* free any tRNS entry */
+#ifdef PNG_tRNS_SUPPORTED
+   /* Free any tRNS entry */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
+   if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
 #else
-if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS))
+   if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS))
 #endif
-{
-    png_free(png_ptr, info_ptr->trans);
-    info_ptr->valid &= ~PNG_INFO_tRNS;
+   {
+      png_free(png_ptr, info_ptr->trans);
+      info_ptr->trans = NULL;
+      info_ptr->valid &= ~PNG_INFO_tRNS;
 #ifndef PNG_FREE_ME_SUPPORTED
-    png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
+      png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
 #endif
-    info_ptr->trans = NULL;
-}
+   }
 #endif
 
-#if defined(PNG_sCAL_SUPPORTED)
-/* free any sCAL entry */
+#ifdef PNG_sCAL_SUPPORTED
+   /* Free any sCAL entry */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
+   if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
 #else
-if (mask & PNG_FREE_SCAL)
+   if (mask & PNG_FREE_SCAL)
 #endif
-{
+   {
 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
-    png_free(png_ptr, info_ptr->scal_s_width);
-    png_free(png_ptr, info_ptr->scal_s_height);
-    info_ptr->scal_s_width = NULL;
-    info_ptr->scal_s_height = NULL;
+      png_free(png_ptr, info_ptr->scal_s_width);
+      png_free(png_ptr, info_ptr->scal_s_height);
+      info_ptr->scal_s_width = NULL;
+      info_ptr->scal_s_height = NULL;
 #endif
-    info_ptr->valid &= ~PNG_INFO_sCAL;
-}
+      info_ptr->valid &= ~PNG_INFO_sCAL;
+   }
 #endif
 
-#if defined(PNG_pCAL_SUPPORTED)
-/* free any pCAL entry */
+#ifdef PNG_pCAL_SUPPORTED
+   /* Free any pCAL entry */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
+   if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
 #else
-if (mask & PNG_FREE_PCAL)
+   if (mask & PNG_FREE_PCAL)
 #endif
-{
-    png_free(png_ptr, info_ptr->pcal_purpose);
-    png_free(png_ptr, info_ptr->pcal_units);
-    info_ptr->pcal_purpose = NULL;
-    info_ptr->pcal_units = NULL;
-    if (info_ptr->pcal_params != NULL)
-    {
-        int i;
-        for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
-        {
-          png_free(png_ptr, info_ptr->pcal_params[i]);
-          info_ptr->pcal_params[i]=NULL;
-        }
-        png_free(png_ptr, info_ptr->pcal_params);
-        info_ptr->pcal_params = NULL;
-    }
-    info_ptr->valid &= ~PNG_INFO_pCAL;
-}
+   {
+      png_free(png_ptr, info_ptr->pcal_purpose);
+      png_free(png_ptr, info_ptr->pcal_units);
+      info_ptr->pcal_purpose = NULL;
+      info_ptr->pcal_units = NULL;
+      if (info_ptr->pcal_params != NULL)
+         {
+            int i;
+            for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
+            {
+               png_free(png_ptr, info_ptr->pcal_params[i]);
+               info_ptr->pcal_params[i] = NULL;
+            }
+            png_free(png_ptr, info_ptr->pcal_params);
+            info_ptr->pcal_params = NULL;
+         }
+      info_ptr->valid &= ~PNG_INFO_pCAL;
+   }
 #endif
 
-#if defined(PNG_iCCP_SUPPORTED)
-/* free any iCCP entry */
+#ifdef PNG_iCCP_SUPPORTED
+   /* Free any iCCP entry */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
+   if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
 #else
-if (mask & PNG_FREE_ICCP)
+   if (mask & PNG_FREE_ICCP)
 #endif
-{
-    png_free(png_ptr, info_ptr->iccp_name);
-    png_free(png_ptr, info_ptr->iccp_profile);
-    info_ptr->iccp_name = NULL;
-    info_ptr->iccp_profile = NULL;
-    info_ptr->valid &= ~PNG_INFO_iCCP;
-}
+   {
+      png_free(png_ptr, info_ptr->iccp_name);
+      png_free(png_ptr, info_ptr->iccp_profile);
+      info_ptr->iccp_name = NULL;
+      info_ptr->iccp_profile = NULL;
+      info_ptr->valid &= ~PNG_INFO_iCCP;
+   }
 #endif
 
-#if defined(PNG_sPLT_SUPPORTED)
-/* free a given sPLT entry, or (if num == -1) all sPLT entries */
+#ifdef PNG_sPLT_SUPPORTED
+   /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
+   if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
 #else
-if (mask & PNG_FREE_SPLT)
+   if (mask & PNG_FREE_SPLT)
 #endif
-{
-   if (num != -1)
    {
-      if(info_ptr->splt_palettes)
+      if (num != -1)
+      {
+         if (info_ptr->splt_palettes)
+         {
+            png_free(png_ptr, info_ptr->splt_palettes[num].name);
+            png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+            info_ptr->splt_palettes[num].name = NULL;
+            info_ptr->splt_palettes[num].entries = NULL;
+         }
+      }
+      else
       {
-          png_free(png_ptr, info_ptr->splt_palettes[num].name);
-          png_free(png_ptr, info_ptr->splt_palettes[num].entries);
-          info_ptr->splt_palettes[num].name = NULL;
-          info_ptr->splt_palettes[num].entries = NULL;
+         if (info_ptr->splt_palettes_num)
+         {
+            int i;
+            for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+               png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+
+            png_free(png_ptr, info_ptr->splt_palettes);
+            info_ptr->splt_palettes = NULL;
+            info_ptr->splt_palettes_num = 0;
+         }
+         info_ptr->valid &= ~PNG_INFO_sPLT;
       }
    }
-   else
-   {
-       if(info_ptr->splt_palettes_num)
-       {
-         int i;
-         for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
-            png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+#endif
 
-         png_free(png_ptr, info_ptr->splt_palettes);
-         info_ptr->splt_palettes = NULL;
-         info_ptr->splt_palettes_num = 0;
-       }
-       info_ptr->valid &= ~PNG_INFO_sPLT;
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+   if (png_ptr->unknown_chunk.data)
+   {
+      png_free(png_ptr, png_ptr->unknown_chunk.data);
+      png_ptr->unknown_chunk.data = NULL;
    }
-}
-#endif
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-  if(png_ptr->unknown_chunk.data)
-  {
-    png_free(png_ptr, png_ptr->unknown_chunk.data);
-    png_ptr->unknown_chunk.data = NULL;
-  }
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
+   if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
 #else
-if (mask & PNG_FREE_UNKN)
+   if (mask & PNG_FREE_UNKN)
 #endif
-{
-   if (num != -1)
-   {
-       if(info_ptr->unknown_chunks)
-       {
-          png_free(png_ptr, info_ptr->unknown_chunks[num].data);
-          info_ptr->unknown_chunks[num].data = NULL;
-       }
-   }
-   else
    {
-       int i;
+      if (num != -1)
+      {
+          if (info_ptr->unknown_chunks)
+          {
+             png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+             info_ptr->unknown_chunks[num].data = NULL;
+          }
+      }
+      else
+      {
+         int i;
 
-       if(info_ptr->unknown_chunks_num)
-       {
-         for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
-            png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
+         if (info_ptr->unknown_chunks_num)
+         {
+            for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
+               png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
 
-         png_free(png_ptr, info_ptr->unknown_chunks);
-         info_ptr->unknown_chunks = NULL;
-         info_ptr->unknown_chunks_num = 0;
-       }
+            png_free(png_ptr, info_ptr->unknown_chunks);
+            info_ptr->unknown_chunks = NULL;
+            info_ptr->unknown_chunks_num = 0;
+         }
+      }
    }
-}
 #endif
 
-#if defined(PNG_hIST_SUPPORTED)
-/* free any hIST entry */
+#ifdef PNG_hIST_SUPPORTED
+   /* Free any hIST entry */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_HIST)  & info_ptr->free_me)
+   if ((mask & PNG_FREE_HIST)  & info_ptr->free_me)
 #else
-if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST))
+   if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST))
 #endif
-{
-    png_free(png_ptr, info_ptr->hist);
-    info_ptr->hist = NULL;
-    info_ptr->valid &= ~PNG_INFO_hIST;
+   {
+      png_free(png_ptr, info_ptr->hist);
+      info_ptr->hist = NULL;
+      info_ptr->valid &= ~PNG_INFO_hIST;
 #ifndef PNG_FREE_ME_SUPPORTED
-    png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
+      png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
 #endif
-}
+   }
 #endif
 
-/* free any PLTE entry that was internally allocated */
+   /* Free any PLTE entry that was internally allocated */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
+   if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
 #else
-if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE))
+   if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE))
 #endif
-{
-    png_zfree(png_ptr, info_ptr->palette);
-    info_ptr->palette = NULL;
-    info_ptr->valid &= ~PNG_INFO_PLTE;
+   {
+      png_zfree(png_ptr, info_ptr->palette);
+      info_ptr->palette = NULL;
+      info_ptr->valid &= ~PNG_INFO_PLTE;
 #ifndef PNG_FREE_ME_SUPPORTED
-    png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
+      png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
 #endif
-    info_ptr->num_palette = 0;
-}
+      info_ptr->num_palette = 0;
+   }
 
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
-/* free any image bits attached to the info structure */
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+   /* Free any image bits attached to the info structure */
 #ifdef PNG_FREE_ME_SUPPORTED
-if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
+   if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
 #else
-if (mask & PNG_FREE_ROWS)
+   if (mask & PNG_FREE_ROWS)
 #endif
-{
-    if(info_ptr->row_pointers)
-    {
-       int row;
-       for (row = 0; row < (int)info_ptr->height; row++)
-       {
-          png_free(png_ptr, info_ptr->row_pointers[row]);
-          info_ptr->row_pointers[row]=NULL;
-       }
-       png_free(png_ptr, info_ptr->row_pointers);
-       info_ptr->row_pointers=NULL;
-    }
-    info_ptr->valid &= ~PNG_INFO_IDAT;
-}
+   {
+      if (info_ptr->row_pointers)
+      {
+         int row;
+         for (row = 0; row < (int)info_ptr->height; row++)
+         {
+            png_free(png_ptr, info_ptr->row_pointers[row]);
+            info_ptr->row_pointers[row] = NULL;
+         }
+         png_free(png_ptr, info_ptr->row_pointers);
+         info_ptr->row_pointers = NULL;
+      }
+      info_ptr->valid &= ~PNG_INFO_IDAT;
+   }
 #endif
 
 #ifdef PNG_FREE_ME_SUPPORTED
-   if(num == -1)
-     info_ptr->free_me &= ~mask;
+   if (num == -1)
+      info_ptr->free_me &= ~mask;
    else
-     info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL);
+      info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL);
 #endif
 }
 
@@ -592,16 +613,16 @@ if (mask & PNG_FREE_ROWS)
 void /* PRIVATE */
 png_info_destroy(png_structp png_ptr, png_infop info_ptr)
 {
-   png_debug(1, "in png_info_destroy\n");
+   png_debug(1, "in png_info_destroy");
 
    png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    if (png_ptr->num_chunk_list)
    {
-       png_free(png_ptr, png_ptr->chunk_list);
-       png_ptr->chunk_list=NULL;
-       png_ptr->num_chunk_list=0;
+      png_free(png_ptr, png_ptr->chunk_list);
+      png_ptr->chunk_list = NULL;
+      png_ptr->num_chunk_list = 0;
    }
 #endif
 
@@ -616,12 +637,13 @@ png_info_destroy(png_structp png_ptr, png_infop info_ptr)
 png_voidp PNGAPI
 png_get_io_ptr(png_structp png_ptr)
 {
-   if(png_ptr == NULL) return (NULL);
+   if (png_ptr == NULL)
+      return (NULL);
    return (png_ptr->io_ptr);
 }
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_STDIO_SUPPORTED
 /* Initialize the default input/output functions for the PNG file.  If you
  * use your own read or write routines, you can call either png_set_read_fn()
  * or png_set_write_fn() instead of png_init_io().  If you have defined
@@ -631,13 +653,16 @@ png_get_io_ptr(png_structp png_ptr)
 void PNGAPI
 png_init_io(png_structp png_ptr, png_FILE_p fp)
 {
-   png_debug(1, "in png_init_io\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_init_io");
+
+   if (png_ptr == NULL)
+      return;
+
    png_ptr->io_ptr = (png_voidp)fp;
 }
 #endif
 
-#if defined(PNG_TIME_RFC1123_SUPPORTED)
+#ifdef PNG_TIME_RFC1123_SUPPORTED
 /* Convert the supplied time into an RFC 1123 string suitable for use in
  * a "Creation Time" or other text-based time string.
  */
@@ -648,28 +673,29 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
         {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
 
-   if(png_ptr == NULL) return (NULL);
+   if (png_ptr == NULL)
+      return (NULL);
    if (png_ptr->time_buffer == NULL)
    {
       png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
          png_sizeof(char)));
    }
 
-#if defined(_WIN32_WCE)
+#ifdef _WIN32_WCE
    {
       wchar_t time_buf[29];
       wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"),
           ptime->day % 32, short_months[(ptime->month - 1) % 12],
         ptime->year, ptime->hour % 24, ptime->minute % 60,
           ptime->second % 61);
-      WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29,
-          NULL, NULL);
+      WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer,
+          29, NULL, NULL);
    }
 #else
 #ifdef USE_FAR_KEYWORD
    {
       char near_time_buf[29];
-      png_snprintf6(near_time_buf,29,"%d %s %d %02d:%02d:%02d +0000",
+      png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000",
           ptime->day % 32, short_months[(ptime->month - 1) % 12],
           ptime->year, ptime->hour % 24, ptime->minute % 60,
           ptime->second % 61);
@@ -677,7 +703,7 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
           29*png_sizeof(char));
    }
 #else
-   png_snprintf6(png_ptr->time_buffer,29,"%d %s %d %02d:%02d:%02d +0000",
+   png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000",
        ptime->day % 32, short_months[(ptime->month - 1) % 12],
        ptime->year, ptime->hour % 24, ptime->minute % 60,
        ptime->second % 61);
@@ -692,11 +718,24 @@ png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
 png_charp PNGAPI
 png_get_copyright(png_structp png_ptr)
 {
-   png_ptr = png_ptr;  /* silence compiler warning about unused png_ptr */
-   return ((png_charp) "\n libpng version 1.2.23 - November 6, 2007\n\
-   Copyright (c) 1998-2007 Glenn Randers-Pehrson\n\
-   Copyright (c) 1996-1997 Andreas Dilger\n\
-   Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n");
+   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
+#ifdef PNG_STRING_COPYRIGHT
+      return PNG_STRING_COPYRIGHT
+#else
+#ifdef __STDC__
+   return ((png_charp) PNG_STRING_NEWLINE \
+     "libpng version 1.2.50 - July 10, 2012" PNG_STRING_NEWLINE \
+     "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+     "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
+     "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
+     PNG_STRING_NEWLINE);
+#else
+      return ((png_charp) "libpng version 1.2.50 - July 10, 2012\
+      Copyright (c) 1998-2011 Glenn Randers-Pehrson\
+      Copyright (c) 1996-1997 Andreas Dilger\
+      Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
+#endif
+#endif
 }
 
 /* The following return the library version as a short string in the
@@ -711,7 +750,7 @@ png_charp PNGAPI
 png_get_libpng_ver(png_structp png_ptr)
 {
    /* Version of *.c files used when building libpng */
-   png_ptr = png_ptr;  /* silence compiler warning about unused png_ptr */
+   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
    return ((png_charp) PNG_LIBPNG_VER_STRING);
 }
 
@@ -719,7 +758,7 @@ png_charp PNGAPI
 png_get_header_ver(png_structp png_ptr)
 {
    /* Version of *.h files used when building libpng */
-   png_ptr = png_ptr;  /* silence compiler warning about unused png_ptr */
+   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
    return ((png_charp) PNG_LIBPNG_VER_STRING);
 }
 
@@ -727,12 +766,16 @@ png_charp PNGAPI
 png_get_header_version(png_structp png_ptr)
 {
    /* Returns longer string containing both version and date */
-   png_ptr = png_ptr;  /* silence compiler warning about unused png_ptr */
+   png_ptr = png_ptr;  /* Silence compiler warning about unused png_ptr */
+#ifdef __STDC__
    return ((png_charp) PNG_HEADER_VERSION_STRING
 #ifndef PNG_READ_SUPPORTED
    "     (NO READ SUPPORT)"
 #endif
-   "\n");
+   PNG_STRING_NEWLINE);
+#else
+   return ((png_charp) PNG_HEADER_VERSION_STRING);
+#endif
 }
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
@@ -740,15 +783,15 @@ png_get_header_version(png_structp png_ptr)
 int PNGAPI
 png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
 {
-   /* check chunk_name and return "keep" value if it's on the list, else 0 */
+   /* Check chunk_name and return "keep" value if it's on the list, else 0 */
    int i;
    png_bytep p;
-   if(png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0)
+   if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0)
       return 0;
-   p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5;
-   for (i = png_ptr->num_chunk_list; i; i--, p-=5)
+   p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5;
+   for (i = png_ptr->num_chunk_list; i; i--, p -= 5)
       if (!png_memcmp(chunk_name, p, 4))
-        return ((int)*(p+4));
+        return ((int)*(p + 4));
    return 0;
 }
 #endif
@@ -757,7 +800,8 @@ png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
 int PNGAPI
 png_reset_zstream(png_structp png_ptr)
 {
-   if (png_ptr == NULL) return Z_STREAM_ERROR;
+   if (png_ptr == NULL)
+      return Z_STREAM_ERROR;
    return (inflateReset(&png_ptr->zstream));
 }
 #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
@@ -772,12 +816,12 @@ png_access_version_number(void)
 
 
 #if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED)
-#if !defined(PNG_1_0_X)
-/* this function was added to libpng 1.2.0 */
+#ifndef PNG_1_0_X
+/* This function was added to libpng 1.2.0 */
 int PNGAPI
 png_mmx_support(void)
 {
-   /* obsolete, to be removed from libpng-1.4.0 */
+   /* Obsolete, to be removed from libpng-1.4.0 */
     return -1;
 }
 #endif /* PNG_1_0_X */
@@ -790,9 +834,267 @@ png_mmx_support(void)
 png_size_t PNGAPI
 png_convert_size(size_t size)
 {
-  if (size > (png_size_t)-1)
-     PNG_ABORT();  /* We haven't got access to png_ptr, so no png_error() */
-  return ((png_size_t)size);
+   if (size > (png_size_t)-1)
+      PNG_ABORT();  /* We haven't got access to png_ptr, so no png_error() */
+   return ((png_size_t)size);
 }
 #endif /* PNG_SIZE_T */
+
+/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+
+/*
+ *    Multiply two 32-bit numbers, V1 and V2, using 32-bit
+ *    arithmetic, to produce a 64 bit result in the HI/LO words.
+ *
+ *                  A B
+ *                x C D
+ *               ------
+ *              AD || BD
+ *        AC || CB || 0
+ *
+ *    where A and B are the high and low 16-bit words of V1,
+ *    C and D are the 16-bit words of V2, AD is the product of
+ *    A and D, and X || Y is (X << 16) + Y.
+*/
+
+void /* PRIVATE */
+png_64bit_product (long v1, long v2, unsigned long *hi_product,
+   unsigned long *lo_product)
+{
+   int a, b, c, d;
+   long lo, hi, x, y;
+
+   a = (v1 >> 16) & 0xffff;
+   b = v1 & 0xffff;
+   c = (v2 >> 16) & 0xffff;
+   d = v2 & 0xffff;
+
+   lo = b * d;                   /* BD */
+   x = a * d + c * b;            /* AD + CB */
+   y = ((lo >> 16) & 0xffff) + x;
+
+   lo = (lo & 0xffff) | ((y & 0xffff) << 16);
+   hi = (y >> 16) & 0xffff;
+
+   hi += a * c;                  /* AC */
+
+   *hi_product = (unsigned long)hi;
+   *lo_product = (unsigned long)lo;
+}
+
+int /* PRIVATE */
+png_check_cHRM_fixed(png_structp png_ptr,
+   png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
+   png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
+   png_fixed_point blue_x, png_fixed_point blue_y)
+{
+   int ret = 1;
+   unsigned long xy_hi,xy_lo,yx_hi,yx_lo;
+
+   png_debug(1, "in function png_check_cHRM_fixed");
+
+   if (png_ptr == NULL)
+      return 0;
+
+   if (white_x < 0 || white_y <= 0 ||
+         red_x < 0 ||   red_y <  0 ||
+       green_x < 0 || green_y <  0 ||
+        blue_x < 0 ||  blue_y <  0)
+   {
+      png_warning(png_ptr,
+        "Ignoring attempt to set negative chromaticity value");
+      ret = 0;
+   }
+   if (white_x > (png_fixed_point) PNG_UINT_31_MAX ||
+       white_y > (png_fixed_point) PNG_UINT_31_MAX ||
+         red_x > (png_fixed_point) PNG_UINT_31_MAX ||
+         red_y > (png_fixed_point) PNG_UINT_31_MAX ||
+       green_x > (png_fixed_point) PNG_UINT_31_MAX ||
+       green_y > (png_fixed_point) PNG_UINT_31_MAX ||
+        blue_x > (png_fixed_point) PNG_UINT_31_MAX ||
+        blue_y > (png_fixed_point) PNG_UINT_31_MAX )
+   {
+      png_warning(png_ptr,
+        "Ignoring attempt to set chromaticity value exceeding 21474.83");
+      ret = 0;
+   }
+   if (white_x > 100000L - white_y)
+   {
+      png_warning(png_ptr, "Invalid cHRM white point");
+      ret = 0;
+   }
+   if (red_x > 100000L - red_y)
+   {
+      png_warning(png_ptr, "Invalid cHRM red point");
+      ret = 0;
+   }
+   if (green_x > 100000L - green_y)
+   {
+      png_warning(png_ptr, "Invalid cHRM green point");
+      ret = 0;
+   }
+   if (blue_x > 100000L - blue_y)
+   {
+      png_warning(png_ptr, "Invalid cHRM blue point");
+      ret = 0;
+   }
+
+   png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo);
+   png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo);
+
+   if (xy_hi == yx_hi && xy_lo == yx_lo)
+   {
+      png_warning(png_ptr,
+         "Ignoring attempt to set cHRM RGB triangle with zero area");
+      ret = 0;
+   }
+
+   return ret;
+}
+#endif /* PNG_CHECK_cHRM_SUPPORTED */
+#endif /* PNG_cHRM_SUPPORTED */
+
+void /* PRIVATE */
+png_check_IHDR(png_structp png_ptr,
+   png_uint_32 width, png_uint_32 height, int bit_depth,
+   int color_type, int interlace_type, int compression_type,
+   int filter_type)
+{
+   int error = 0;
+
+   /* Check for width and height valid values */
+   if (width == 0)
+   {
+      png_warning(png_ptr, "Image width is zero in IHDR");
+      error = 1;
+   }
+
+   if (height == 0)
+   {
+      png_warning(png_ptr, "Image height is zero in IHDR");
+      error = 1;
+   }
+
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+   if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX)
+#else
+   if (width > PNG_USER_WIDTH_MAX)
+#endif
+   {
+      png_warning(png_ptr, "Image width exceeds user limit in IHDR");
+      error = 1;
+   }
+
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+   if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX)
+#else
+   if (height > PNG_USER_HEIGHT_MAX)
+#endif
+   {
+      png_warning(png_ptr, "Image height exceeds user limit in IHDR");
+      error = 1;
+   }
+
+   if (width > PNG_UINT_31_MAX)
+   {
+      png_warning(png_ptr, "Invalid image width in IHDR");
+      error = 1;
+   }
+
+   if ( height > PNG_UINT_31_MAX)
+   {
+      png_warning(png_ptr, "Invalid image height in IHDR");
+      error = 1;
+   }
+
+   if ( width > (PNG_UINT_32_MAX
+                 >> 3)      /* 8-byte RGBA pixels */
+                 - 64       /* bigrowbuf hack */
+                 - 1        /* filter byte */
+                 - 7*8      /* rounding of width to multiple of 8 pixels */
+                 - 8)       /* extra max_pixel_depth pad */
+      png_warning(png_ptr, "Width is too large for libpng to process pixels");
+
+   /* Check other values */
+   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
+       bit_depth != 8 && bit_depth != 16)
+   {
+      png_warning(png_ptr, "Invalid bit depth in IHDR");
+      error = 1;
+   }
+
+   if (color_type < 0 || color_type == 1 ||
+       color_type == 5 || color_type > 6)
+   {
+      png_warning(png_ptr, "Invalid color type in IHDR");
+      error = 1;
+   }
+
+   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
+       ((color_type == PNG_COLOR_TYPE_RGB ||
+         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
+   {
+      png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
+      error = 1;
+   }
+
+   if (interlace_type >= PNG_INTERLACE_LAST)
+   {
+      png_warning(png_ptr, "Unknown interlace method in IHDR");
+      error = 1;
+   }
+
+   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+   {
+      png_warning(png_ptr, "Unknown compression method in IHDR");
+      error = 1;
+   }
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+   /* Accept filter_method 64 (intrapixel differencing) only if
+    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+    * 2. Libpng did not read a PNG signature (this filter_method is only
+    *    used in PNG datastreams that are embedded in MNG datastreams) and
+    * 3. The application called png_permit_mng_features with a mask that
+    *    included PNG_FLAG_MNG_FILTER_64 and
+    * 4. The filter_method is 64 and
+    * 5. The color_type is RGB or RGBA
+    */
+   if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
+       png_ptr->mng_features_permitted)
+      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
+
+   if (filter_type != PNG_FILTER_TYPE_BASE)
+   {
+      if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+         (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
+         ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
+         (color_type == PNG_COLOR_TYPE_RGB ||
+         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
+      {
+         png_warning(png_ptr, "Unknown filter method in IHDR");
+         error = 1;
+      }
+
+      if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
+      {
+         png_warning(png_ptr, "Invalid filter method in IHDR");
+         error = 1;
+      }
+   }
+
+#else
+   if (filter_type != PNG_FILTER_TYPE_BASE)
+   {
+      png_warning(png_ptr, "Unknown filter method in IHDR");
+      error = 1;
+   }
+#endif
+
+   if (error == 1)
+      png_error(png_ptr, "Invalid IHDR data");
+}
 #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
diff --git a/graf2d/asimage/src/libAfterImage/libpng/png.h b/graf2d/asimage/src/libAfterImage/libpng/png.h
index f958be6..8cb8282 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/png.h
+++ b/graf2d/asimage/src/libAfterImage/libpng/png.h
@@ -1,15 +1,16 @@
-
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.2.23 - November 6, 2007
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * libpng version 1.2.50 - July 10, 2012
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license (See LICENSE, below)
+ *
  * Authors and maintainers:
  *  libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *  libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *  libpng versions 0.97, January 1998, through 1.2.23 - November 6, 2007: Glenn
+ *  libpng versions 0.97, January 1998, through 1.2.50 - July 10, 2012: Glenn
  *  See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
@@ -172,6 +173,117 @@
  *    1.2.23beta01-05         13    10223  12.so.0.23[.0]
  *    1.2.23rc01              13    10223  12.so.0.23[.0]
  *    1.2.23                  13    10223  12.so.0.23[.0]
+ *    1.2.24beta01-02         13    10224  12.so.0.24[.0]
+ *    1.2.24rc01              13    10224  12.so.0.24[.0]
+ *    1.2.24                  13    10224  12.so.0.24[.0]
+ *    1.2.25beta01-06         13    10225  12.so.0.25[.0]
+ *    1.2.25rc01-02           13    10225  12.so.0.25[.0]
+ *    1.0.31                  10    10031  10.so.0.31[.0]
+ *    1.2.25                  13    10225  12.so.0.25[.0]
+ *    1.2.26beta01-06         13    10226  12.so.0.26[.0]
+ *    1.2.26rc01              13    10226  12.so.0.26[.0]
+ *    1.2.26                  13    10226  12.so.0.26[.0]
+ *    1.0.32                  10    10032  10.so.0.32[.0]
+ *    1.2.27beta01-06         13    10227  12.so.0.27[.0]
+ *    1.2.27rc01              13    10227  12.so.0.27[.0]
+ *    1.0.33                  10    10033  10.so.0.33[.0]
+ *    1.2.27                  13    10227  12.so.0.27[.0]
+ *    1.0.34                  10    10034  10.so.0.34[.0]
+ *    1.2.28                  13    10228  12.so.0.28[.0]
+ *    1.2.29beta01-03         13    10229  12.so.0.29[.0]
+ *    1.2.29rc01              13    10229  12.so.0.29[.0]
+ *    1.0.35                  10    10035  10.so.0.35[.0]
+ *    1.2.29                  13    10229  12.so.0.29[.0]
+ *    1.0.37                  10    10037  10.so.0.37[.0]
+ *    1.2.30beta01-04         13    10230  12.so.0.30[.0]
+ *    1.0.38rc01-08           10    10038  10.so.0.38[.0]
+ *    1.2.30rc01-08           13    10230  12.so.0.30[.0]
+ *    1.0.38                  10    10038  10.so.0.38[.0]
+ *    1.2.30                  13    10230  12.so.0.30[.0]
+ *    1.0.39rc01-03           10    10039  10.so.0.39[.0]
+ *    1.2.31rc01-03           13    10231  12.so.0.31[.0]
+ *    1.0.39                  10    10039  10.so.0.39[.0]
+ *    1.2.31                  13    10231  12.so.0.31[.0]
+ *    1.2.32beta01-02         13    10232  12.so.0.32[.0]
+ *    1.0.40rc01              10    10040  10.so.0.40[.0]
+ *    1.2.32rc01              13    10232  12.so.0.32[.0]
+ *    1.0.40                  10    10040  10.so.0.40[.0]
+ *    1.2.32                  13    10232  12.so.0.32[.0]
+ *    1.2.33beta01-02         13    10233  12.so.0.33[.0]
+ *    1.2.33rc01-02           13    10233  12.so.0.33[.0]
+ *    1.0.41rc01              10    10041  10.so.0.41[.0]
+ *    1.2.33                  13    10233  12.so.0.33[.0]
+ *    1.0.41                  10    10041  10.so.0.41[.0]
+ *    1.2.34beta01-07         13    10234  12.so.0.34[.0]
+ *    1.0.42rc01              10    10042  10.so.0.42[.0]
+ *    1.2.34rc01              13    10234  12.so.0.34[.0]
+ *    1.0.42                  10    10042  10.so.0.42[.0]
+ *    1.2.34                  13    10234  12.so.0.34[.0]
+ *    1.2.35beta01-03         13    10235  12.so.0.35[.0]
+ *    1.0.43rc01-02           10    10043  10.so.0.43[.0]
+ *    1.2.35rc01-02           13    10235  12.so.0.35[.0]
+ *    1.0.43                  10    10043  10.so.0.43[.0]
+ *    1.2.35                  13    10235  12.so.0.35[.0]
+ *    1.2.36beta01-05         13    10236  12.so.0.36[.0]
+ *    1.2.36rc01              13    10236  12.so.0.36[.0]
+ *    1.0.44                  10    10044  10.so.0.44[.0]
+ *    1.2.36                  13    10236  12.so.0.36[.0]
+ *    1.2.37beta01-03         13    10237  12.so.0.37[.0]
+ *    1.2.37rc01              13    10237  12.so.0.37[.0]
+ *    1.2.37                  13    10237  12.so.0.37[.0]
+ *    1.0.45                  10    10045  12.so.0.45[.0]
+ *    1.0.46                  10    10046  10.so.0.46[.0]
+ *    1.2.38beta01            13    10238  12.so.0.38[.0]
+ *    1.2.38rc01-03           13    10238  12.so.0.38[.0]
+ *    1.0.47                  10    10047  10.so.0.47[.0]
+ *    1.2.38                  13    10238  12.so.0.38[.0]
+ *    1.2.39beta01-05         13    10239  12.so.0.39[.0]
+ *    1.2.39rc01              13    10239  12.so.0.39[.0]
+ *    1.0.48                  10    10048  10.so.0.48[.0]
+ *    1.2.39                  13    10239  12.so.0.39[.0]
+ *    1.2.40beta01            13    10240  12.so.0.40[.0]
+ *    1.2.40rc01              13    10240  12.so.0.40[.0]
+ *    1.0.49                  10    10049  10.so.0.49[.0]
+ *    1.2.40                  13    10240  12.so.0.40[.0]
+ *    1.2.41beta01-18         13    10241  12.so.0.41[.0]
+ *    1.0.51rc01              10    10051  10.so.0.51[.0]
+ *    1.2.41rc01-03           13    10241  12.so.0.41[.0]
+ *    1.0.51                  10    10051  10.so.0.51[.0]
+ *    1.2.41                  13    10241  12.so.0.41[.0]
+ *    1.2.42beta01-02         13    10242  12.so.0.42[.0]
+ *    1.2.42rc01-05           13    10242  12.so.0.42[.0]
+ *    1.0.52                  10    10052  10.so.0.52[.0]
+ *    1.2.42                  13    10242  12.so.0.42[.0]
+ *    1.2.43beta01-05         13    10243  12.so.0.43[.0]
+ *    1.0.53rc01-02           10    10053  10.so.0.53[.0]
+ *    1.2.43rc01-02           13    10243  12.so.0.43[.0]
+ *    1.0.53                  10    10053  10.so.0.53[.0]
+ *    1.2.43                  13    10243  12.so.0.43[.0]
+ *    1.2.44beta01-03         13    10244  12.so.0.44[.0]
+ *    1.2.44rc01-03           13    10244  12.so.0.44[.0]
+ *    1.2.44                  13    10244  12.so.0.44[.0]
+ *    1.2.45beta01-03         13    10245  12.so.0.45[.0]
+ *    1.0.55rc01              10    10055  10.so.0.55[.0]
+ *    1.2.45rc01              13    10245  12.so.0.45[.0]
+ *    1.0.55                  10    10055  10.so.0.55[.0]
+ *    1.2.45                  13    10245  12.so.0.45[.0]
+ *    1.2.46rc01-02           13    10246  12.so.0.46[.0]
+ *    1.0.56                  10    10056  10.so.0.56[.0]
+ *    1.2.46                  13    10246  12.so.0.46[.0]
+ *    1.2.47beta01            13    10247  12.so.0.47[.0]
+ *    1.2.47rc01              13    10247  12.so.0.47[.0]
+ *    1.0.57rc01              10    10057  10.so.0.57[.0]
+ *    1.2.47                  13    10247  12.so.0.47[.0]
+ *    1.0.57                  10    10057  10.so.0.57[.0]
+ *    1.2.48beta01            13    10248  12.so.0.48[.0]
+ *    1.2.48rc01-02           13    10248  12.so.0.48[.0]
+ *    1.0.58                  10    10058  10.so.0.58[.0]
+ *    1.2.48                  13    10248  12.so.0.48[.0]
+ *    1.2.49rc01              13    10249  12.so.0.49[.0]
+ *    1.0.59                  10    10059  10.so.0.59[.0]
+ *    1.2.49                  13    10249  12.so.0.49[.0]
+ *    1.0.60                  10    10060  10.so.0.60[.0]
+ *    1.2.50                  13    10250  12.so.0.50[.0]
  *
  *    Henceforth the source version will match the shared-library major
  *    and minor numbers; the shared-library major version number will be
@@ -181,7 +293,7 @@
  *    to the source version x.y.z (leading zeros in y and z).  Beta versions
  *    were given the previous public release number plus a letter, until
  *    version 1.0.6j; from then on they were given the upcoming public
- *    release number plus "betaNN" or "rcN".
+ *    release number plus "betaNN" or "rcNN".
  *
  *    Binary incompatibility exists only when applications make direct access
  *    to the info_ptr or png_ptr members through png.h, and the compiled
@@ -201,8 +313,10 @@
  * If you modify libpng you may insert additional notices immediately following
  * this sentence.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.2.23, November 6, 2007, are
- * Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are
+ * This code is released under the libpng license.
+ *
+ * libpng versions 1.2.6, August 15, 2004, through 1.2.50, July 10, 2012, are
+ * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
  *
@@ -313,13 +427,13 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    November 6, 2007
+ *    July 10, 2012
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.2.23 are Y2K compliant.  It is my belief that earlier
+ *    upward through 1.2.50 are Y2K compliant.  It is my belief that earlier
  *    versions were also Y2K compliant.
  *
  *    Libpng only has three year fields.  One is a 2-byte unsigned integer
@@ -375,9 +489,9 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.2.23"
+#define PNG_LIBPNG_VER_STRING "1.2.50"
 #define PNG_HEADER_VERSION_STRING \
-   " libpng version 1.2.23 - November 6, 2007\n"
+   " libpng version 1.2.50 - July 10, 2012\n"
 
 #define PNG_LIBPNG_VER_SONUM   0
 #define PNG_LIBPNG_VER_DLLNUM  13
@@ -385,9 +499,10 @@
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   2
-#define PNG_LIBPNG_VER_RELEASE 23
+#define PNG_LIBPNG_VER_RELEASE 50
 /* This should match the numeric part of the final component of
- * PNG_LIBPNG_VER_STRING, omitting any leading zero: */
+ * PNG_LIBPNG_VER_STRING, omitting any leading zero:
+ */
 
 #define PNG_LIBPNG_VER_BUILD  0
 
@@ -397,7 +512,7 @@
 #define PNG_LIBPNG_BUILD_RC       3
 #define PNG_LIBPNG_BUILD_STABLE   4
 #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7
-  
+
 /* Release-Specific Flags */
 #define PNG_LIBPNG_BUILD_PATCH    8 /* Can be OR'ed with
                                        PNG_LIBPNG_BUILD_STABLE only */
@@ -412,11 +527,12 @@
  * We must not include leading zeros.
  * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
- * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release */
-#define PNG_LIBPNG_VER 10223 /* 1.2.23 */
+ * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
+ */
+#define PNG_LIBPNG_VER 10250 /* 1.2.50 */
 
 #ifndef PNG_VERSION_INFO_ONLY
-/* include the compression library's header */
+/* Include the compression library's header */
 # ifdef _WIN32
 #  include "..\zlib\zlib.h"
 # else
@@ -424,7 +540,7 @@
 # endif
 #endif
 
-/* include all user configurable info, including optional assembler routines */
+/* Include all user configurable info, including optional assembler routines */
 #include "pngconf.h"
 
 /*
@@ -432,19 +548,19 @@
 /* Ref MSDN: Private as priority over Special
  * VS_FF_PRIVATEBUILD File *was not* built using standard release
  * procedures. If this value is given, the StringFileInfo block must
- * contain a PrivateBuild string. 
+ * contain a PrivateBuild string.
  *
  * VS_FF_SPECIALBUILD File *was* built by the original company using
  * standard release procedures but is a variation of the standard
  * file of the same version number. If this value is given, the
- * StringFileInfo block must contain a SpecialBuild string. 
+ * StringFileInfo block must contain a SpecialBuild string.
  */
 
-#if defined(PNG_USER_PRIVATEBUILD)
+#ifdef PNG_USER_PRIVATEBUILD
 #  define PNG_LIBPNG_BUILD_TYPE \
           (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE)
 #else
-#  if defined(PNG_LIBPNG_SPECIALBUILD)
+#  ifdef PNG_LIBPNG_SPECIALBUILD
 #    define PNG_LIBPNG_BUILD_TYPE \
             (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL)
 #  else
@@ -499,14 +615,14 @@ extern "C" {
 #define png_write_status_ptr_NULL NULL
 #endif
 
-/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+/* Variables declared in png.c - only it needs to define PNG_NO_EXTERN */
 #if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
 /* Version information for C files, stored in png.c.  This had better match
  * the version above.
  */
 #ifdef PNG_USE_GLOBAL_ARRAYS
 PNG_EXPORT_VAR (PNG_CONST char) png_libpng_ver[18];
-  /* need room for 99.99.99beta99z */
+  /* Need room for 99.99.99beta99z */
 #else
 #define png_libpng_ver png_get_header_ver(NULL)
 #endif
@@ -625,7 +741,8 @@ typedef png_text FAR * FAR * png_textpp;
 #endif
 
 /* Supported compression types for text in PNG files (tEXt, and zTXt).
- * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */
+ * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed.
+ */
 #define PNG_TEXT_COMPRESSION_NONE_WR -3
 #define PNG_TEXT_COMPRESSION_zTXt_WR -2
 #define PNG_TEXT_COMPRESSION_NONE    -1
@@ -652,7 +769,8 @@ typedef struct png_time_struct
 typedef png_time FAR * png_timep;
 typedef png_time FAR * FAR * png_timepp;
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
 /* png_unknown_chunk is a structure to hold queued chunks for which there is
  * no specific support.  The idea is that we can use this to queue
  * up private chunks for output even though the library doesn't actually
@@ -714,26 +832,26 @@ typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp;
  */
 typedef struct png_info_struct
 {
-   /* the following are necessary for every PNG file */
-   png_uint_32 width;       /* width of image in pixels (from IHDR) */
-   png_uint_32 height;      /* height of image in pixels (from IHDR) */
-   png_uint_32 valid;       /* valid chunk data (see PNG_INFO_ below) */
-   png_uint_32 rowbytes;    /* bytes needed to hold an untransformed row */
-   png_colorp palette;      /* array of color values (valid & PNG_INFO_PLTE) */
-   png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
-   png_uint_16 num_trans;   /* number of transparent palette color (tRNS) */
-   png_byte bit_depth;      /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
-   png_byte color_type;     /* see PNG_COLOR_TYPE_ below (from IHDR) */
+   /* The following are necessary for every PNG file */
+   png_uint_32 width PNG_DEPSTRUCT;       /* width of image in pixels (from IHDR) */
+   png_uint_32 height PNG_DEPSTRUCT;      /* height of image in pixels (from IHDR) */
+   png_uint_32 valid PNG_DEPSTRUCT;       /* valid chunk data (see PNG_INFO_ below) */
+   png_uint_32 rowbytes PNG_DEPSTRUCT;    /* bytes needed to hold an untransformed row */
+   png_colorp palette PNG_DEPSTRUCT;      /* array of color values (valid & PNG_INFO_PLTE) */
+   png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in "palette" (PLTE) */
+   png_uint_16 num_trans PNG_DEPSTRUCT;   /* number of transparent palette color (tRNS) */
+   png_byte bit_depth PNG_DEPSTRUCT;      /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
+   png_byte color_type PNG_DEPSTRUCT;     /* see PNG_COLOR_TYPE_ below (from IHDR) */
    /* The following three should have been named *_method not *_type */
-   png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
-   png_byte filter_type;    /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
-   png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+   png_byte compression_type PNG_DEPSTRUCT; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
+   png_byte filter_type PNG_DEPSTRUCT;    /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
+   png_byte interlace_type PNG_DEPSTRUCT; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
 
    /* The following is informational only on read, and not used on writes. */
-   png_byte channels;       /* number of data channels per pixel (1, 2, 3, 4) */
-   png_byte pixel_depth;    /* number of bits per pixel */
-   png_byte spare_byte;     /* to align the data, and for future use */
-   png_byte signature[8];   /* magic bytes read by libpng from start of file */
+   png_byte channels PNG_DEPSTRUCT;       /* number of data channels per pixel (1, 2, 3, 4) */
+   png_byte pixel_depth PNG_DEPSTRUCT;    /* number of bits per pixel */
+   png_byte spare_byte PNG_DEPSTRUCT;     /* to align the data, and for future use */
+   png_byte signature[8] PNG_DEPSTRUCT;   /* magic bytes read by libpng from start of file */
 
    /* The rest of the data is optional.  If you are reading, check the
     * valid field to see if the information in these are valid.  If you
@@ -746,16 +864,16 @@ typedef struct png_info_struct
     * on which the image was created, normally in the range [1.0, 2.5].
     * Data is valid if (valid & PNG_INFO_gAMA) is non-zero.
     */
-   float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
+   float gamma PNG_DEPSTRUCT; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
 #endif
 
-#if defined(PNG_sRGB_SUPPORTED)
+#ifdef PNG_sRGB_SUPPORTED
     /* GR-P, 0.96a */
     /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */
-   png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */
+   png_byte srgb_intent PNG_DEPSTRUCT; /* sRGB rendering intent [0, 1, 2, or 3] */
 #endif
 
-#if defined(PNG_TEXT_SUPPORTED)
+#ifdef PNG_TEXT_SUPPORTED
    /* The tEXt, and zTXt chunks contain human-readable textual data in
     * uncompressed, compressed, and optionally compressed forms, respectively.
     * The data in "text" is an array of pointers to uncompressed,
@@ -764,26 +882,26 @@ typedef struct png_info_struct
     * unique, and the text string may be empty.  Any number of text chunks may
     * be in an image.
     */
-   int num_text; /* number of comments read/to write */
-   int max_text; /* current size of text array */
-   png_textp text; /* array of comments read/to write */
+   int num_text PNG_DEPSTRUCT; /* number of comments read/to write */
+   int max_text PNG_DEPSTRUCT; /* current size of text array */
+   png_textp text PNG_DEPSTRUCT; /* array of comments read/to write */
 #endif /* PNG_TEXT_SUPPORTED */
 
-#if defined(PNG_tIME_SUPPORTED)
+#ifdef PNG_tIME_SUPPORTED
    /* The tIME chunk holds the last time the displayed image data was
     * modified.  See the png_time struct for the contents of this struct.
     */
-   png_time mod_time;
+   png_time mod_time PNG_DEPSTRUCT;
 #endif
 
-#if defined(PNG_sBIT_SUPPORTED)
+#ifdef PNG_sBIT_SUPPORTED
    /* The sBIT chunk specifies the number of significant high-order bits
     * in the pixel data.  Values are in the range [1, bit_depth], and are
     * only specified for the channels in the pixel data.  The contents of
     * the low-order bits is not specified.  Data is valid if
     * (valid & PNG_INFO_sBIT) is non-zero.
     */
-   png_color_8 sig_bit; /* significant bits in color channels */
+   png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in color channels */
 #endif
 
 #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \
@@ -797,8 +915,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
     * single color specified that should be treated as fully transparent.
     * Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
     */
-   png_bytep trans; /* transparent values for paletted image */
-   png_color_16 trans_values; /* transparent color for non-palette image */
+   png_bytep trans PNG_DEPSTRUCT; /* transparent values for paletted image */
+   png_color_16 trans_values PNG_DEPSTRUCT; /* transparent color for non-palette image */
 #endif
 
 #if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
@@ -808,38 +926,38 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
     * in "background" are normally in the same color space/depth as the
     * pixel data.  Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
     */
-   png_color_16 background;
+   png_color_16 background PNG_DEPSTRUCT;
 #endif
 
-#if defined(PNG_oFFs_SUPPORTED)
+#ifdef PNG_oFFs_SUPPORTED
    /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards
     * and downwards from the top-left corner of the display, page, or other
     * application-specific co-ordinate space.  See the PNG_OFFSET_ defines
     * below for the unit types.  Valid if (valid & PNG_INFO_oFFs) non-zero.
     */
-   png_int_32 x_offset; /* x offset on page */
-   png_int_32 y_offset; /* y offset on page */
-   png_byte offset_unit_type; /* offset units type */
+   png_int_32 x_offset PNG_DEPSTRUCT; /* x offset on page */
+   png_int_32 y_offset PNG_DEPSTRUCT; /* y offset on page */
+   png_byte offset_unit_type PNG_DEPSTRUCT; /* offset units type */
 #endif
 
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
    /* The pHYs chunk gives the physical pixel density of the image for
     * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
     * defines below).  Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
     */
-   png_uint_32 x_pixels_per_unit; /* horizontal pixel density */
-   png_uint_32 y_pixels_per_unit; /* vertical pixel density */
-   png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
+   png_uint_32 x_pixels_per_unit PNG_DEPSTRUCT; /* horizontal pixel density */
+   png_uint_32 y_pixels_per_unit PNG_DEPSTRUCT; /* vertical pixel density */
+   png_byte phys_unit_type PNG_DEPSTRUCT; /* resolution type (see PNG_RESOLUTION_ below) */
 #endif
 
-#if defined(PNG_hIST_SUPPORTED)
+#ifdef PNG_hIST_SUPPORTED
    /* The hIST chunk contains the relative frequency or importance of the
     * various palette entries, so that a viewer can intelligently select a
     * reduced-color palette, if required.  Data is an array of "num_palette"
     * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
     * is non-zero.
     */
-   png_uint_16p hist;
+   png_uint_16p hist PNG_DEPSTRUCT;
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
@@ -850,18 +968,18 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
     * [0.0, 0.8].  Data valid if (valid & PNG_INFO_cHRM) non-zero.
     */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-   float x_white;
-   float y_white;
-   float x_red;
-   float y_red;
-   float x_green;
-   float y_green;
-   float x_blue;
-   float y_blue;
+   float x_white PNG_DEPSTRUCT;
+   float y_white PNG_DEPSTRUCT;
+   float x_red PNG_DEPSTRUCT;
+   float y_red PNG_DEPSTRUCT;
+   float x_green PNG_DEPSTRUCT;
+   float y_green PNG_DEPSTRUCT;
+   float x_blue PNG_DEPSTRUCT;
+   float y_blue PNG_DEPSTRUCT;
 #endif
 #endif
 
-#if defined(PNG_pCAL_SUPPORTED)
+#ifdef PNG_pCAL_SUPPORTED
    /* The pCAL chunk describes a transformation between the stored pixel
     * values and original physical data values used to create the image.
     * The integer range [0, 2^bit_depth - 1] maps to the floating-point
@@ -873,42 +991,43 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
     * implemented, and for a description of the ASCII parameter strings.
     * Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
     */
-   png_charp pcal_purpose;  /* pCAL chunk description string */
-   png_int_32 pcal_X0;      /* minimum value */
-   png_int_32 pcal_X1;      /* maximum value */
-   png_charp pcal_units;    /* Latin-1 string giving physical units */
-   png_charpp pcal_params;  /* ASCII strings containing parameter values */
-   png_byte pcal_type;      /* equation type (see PNG_EQUATION_ below) */
-   png_byte pcal_nparams;   /* number of parameters given in pcal_params */
+   png_charp pcal_purpose PNG_DEPSTRUCT;  /* pCAL chunk description string */
+   png_int_32 pcal_X0 PNG_DEPSTRUCT;      /* minimum value */
+   png_int_32 pcal_X1 PNG_DEPSTRUCT;      /* maximum value */
+   png_charp pcal_units PNG_DEPSTRUCT;    /* Latin-1 string giving physical units */
+   png_charpp pcal_params PNG_DEPSTRUCT;  /* ASCII strings containing parameter values */
+   png_byte pcal_type PNG_DEPSTRUCT;      /* equation type (see PNG_EQUATION_ below) */
+   png_byte pcal_nparams PNG_DEPSTRUCT;   /* number of parameters given in pcal_params */
 #endif
 
 /* New members added in libpng-1.0.6 */
 #ifdef PNG_FREE_ME_SUPPORTED
-   png_uint_32 free_me;     /* flags items libpng is responsible for freeing */
+   png_uint_32 free_me PNG_DEPSTRUCT;     /* flags items libpng is responsible for freeing */
 #endif
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-   /* storage for unknown chunks that the library doesn't recognize. */
-   png_unknown_chunkp unknown_chunks;
-   png_size_t unknown_chunks_num;
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+   /* Storage for unknown chunks that the library doesn't recognize. */
+   png_unknown_chunkp unknown_chunks PNG_DEPSTRUCT;
+   png_size_t unknown_chunks_num PNG_DEPSTRUCT;
 #endif
 
-#if defined(PNG_iCCP_SUPPORTED)
+#ifdef PNG_iCCP_SUPPORTED
    /* iCCP chunk data. */
-   png_charp iccp_name;     /* profile name */
-   png_charp iccp_profile;  /* International Color Consortium profile data */
+   png_charp iccp_name PNG_DEPSTRUCT;     /* profile name */
+   png_charp iccp_profile PNG_DEPSTRUCT;  /* International Color Consortium profile data */
                             /* Note to maintainer: should be png_bytep */
-   png_uint_32 iccp_proflen;  /* ICC profile data length */
-   png_byte iccp_compression; /* Always zero */
+   png_uint_32 iccp_proflen PNG_DEPSTRUCT;  /* ICC profile data length */
+   png_byte iccp_compression PNG_DEPSTRUCT; /* Always zero */
 #endif
 
-#if defined(PNG_sPLT_SUPPORTED)
-   /* data on sPLT chunks (there may be more than one). */
-   png_sPLT_tp splt_palettes;
-   png_uint_32 splt_palettes_num;
+#ifdef PNG_sPLT_SUPPORTED
+   /* Data on sPLT chunks (there may be more than one). */
+   png_sPLT_tp splt_palettes PNG_DEPSTRUCT;
+   png_uint_32 splt_palettes_num PNG_DEPSTRUCT;
 #endif
 
-#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_sCAL_SUPPORTED
    /* The sCAL chunk describes the actual physical dimensions of the
     * subject matter of the graphic.  The chunk contains a unit specification
     * a byte value, and two ASCII strings representing floating-point
@@ -916,36 +1035,36 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
     * in the image.  This external representation is converted to double
     * here.  Data values are valid if (valid & PNG_INFO_sCAL) is non-zero.
     */
-   png_byte scal_unit;         /* unit of physical scale */
+   png_byte scal_unit PNG_DEPSTRUCT;         /* unit of physical scale */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-   double scal_pixel_width;    /* width of one pixel */
-   double scal_pixel_height;   /* height of one pixel */
+   double scal_pixel_width PNG_DEPSTRUCT;    /* width of one pixel */
+   double scal_pixel_height PNG_DEPSTRUCT;   /* height of one pixel */
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   png_charp scal_s_width;     /* string containing height */
-   png_charp scal_s_height;    /* string containing width */
+   png_charp scal_s_width PNG_DEPSTRUCT;     /* string containing height */
+   png_charp scal_s_height PNG_DEPSTRUCT;    /* string containing width */
 #endif
 #endif
 
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
+#ifdef PNG_INFO_IMAGE_SUPPORTED
    /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */
    /* Data valid if (valid & PNG_INFO_IDAT) non-zero */
-   png_bytepp row_pointers;        /* the image bits */
+   png_bytepp row_pointers PNG_DEPSTRUCT;        /* the image bits */
 #endif
 
 #if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED)
-   png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */
+   png_fixed_point int_gamma PNG_DEPSTRUCT; /* gamma of image, if (valid & PNG_INFO_gAMA) */
 #endif
 
 #if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED)
-   png_fixed_point int_x_white;
-   png_fixed_point int_y_white;
-   png_fixed_point int_x_red;
-   png_fixed_point int_y_red;
-   png_fixed_point int_x_green;
-   png_fixed_point int_y_green;
-   png_fixed_point int_x_blue;
-   png_fixed_point int_y_blue;
+   png_fixed_point int_x_white PNG_DEPSTRUCT;
+   png_fixed_point int_y_white PNG_DEPSTRUCT;
+   png_fixed_point int_x_red PNG_DEPSTRUCT;
+   png_fixed_point int_y_red PNG_DEPSTRUCT;
+   png_fixed_point int_x_green PNG_DEPSTRUCT;
+   png_fixed_point int_y_green PNG_DEPSTRUCT;
+   png_fixed_point int_x_blue PNG_DEPSTRUCT;
+   png_fixed_point int_y_blue PNG_DEPSTRUCT;
 #endif
 
 } png_info;
@@ -1098,10 +1217,10 @@ typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp,
     png_row_infop, png_bytep));
 #endif
 
-#if defined(PNG_USER_CHUNKS_SUPPORTED)
+#ifdef PNG_USER_CHUNKS_SUPPORTED
 typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp));
 #endif
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
 typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp));
 #endif
 
@@ -1118,7 +1237,12 @@ typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp));
 #define PNG_TRANSFORM_SWAP_ALPHA     0x0100    /* read and write */
 #define PNG_TRANSFORM_SWAP_ENDIAN    0x0200    /* read and write */
 #define PNG_TRANSFORM_INVERT_ALPHA   0x0400    /* read and write */
-#define PNG_TRANSFORM_STRIP_FILLER   0x0800    /* WRITE only */
+#define PNG_TRANSFORM_STRIP_FILLER   0x0800    /* write only, deprecated */
+/* Added to libpng-1.2.34 */
+#define PNG_TRANSFORM_STRIP_FILLER_BEFORE 0x0800  /* write only */
+#define PNG_TRANSFORM_STRIP_FILLER_AFTER  0x1000  /* write only */
+/* Added to libpng-1.2.41 */
+#define PNG_TRANSFORM_GRAY_TO_RGB   0x2000      /* read only */
 
 /* Flags for MNG supported features */
 #define PNG_FLAG_MNG_EMPTY_PLTE     0x01
@@ -1140,296 +1264,316 @@ struct png_struct_def
 #ifdef PNG_SETJMP_SUPPORTED
    jmp_buf jmpbuf;            /* used in png_error */
 #endif
-   png_error_ptr error_fn;    /* function for printing errors and aborting */
-   png_error_ptr warning_fn;  /* function for printing warnings */
-   png_voidp error_ptr;       /* user supplied struct for error functions */
-   png_rw_ptr write_data_fn;  /* function for writing output data */
-   png_rw_ptr read_data_fn;   /* function for reading input data */
-   png_voidp io_ptr;          /* ptr to application struct for I/O functions */
+   png_error_ptr error_fn PNG_DEPSTRUCT;    /* function for printing errors and aborting */
+   png_error_ptr warning_fn PNG_DEPSTRUCT;  /* function for printing warnings */
+   png_voidp error_ptr PNG_DEPSTRUCT;       /* user supplied struct for error functions */
+   png_rw_ptr write_data_fn PNG_DEPSTRUCT;  /* function for writing output data */
+   png_rw_ptr read_data_fn PNG_DEPSTRUCT;   /* function for reading input data */
+   png_voidp io_ptr PNG_DEPSTRUCT;          /* ptr to application struct for I/O functions */
 
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
-   png_user_transform_ptr read_user_transform_fn; /* user read transform */
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+   png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read transform */
 #endif
 
-#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-   png_user_transform_ptr write_user_transform_fn; /* user write transform */
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+   png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write transform */
 #endif
 
 /* These were added in libpng-1.0.2 */
-#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-   png_voidp user_transform_ptr; /* user supplied struct for user transform */
-   png_byte user_transform_depth;    /* bit depth of user transformed pixels */
-   png_byte user_transform_channels; /* channels in user transformed pixels */
-#endif
-#endif
-
-   png_uint_32 mode;          /* tells us where we are in the PNG file */
-   png_uint_32 flags;         /* flags indicating various things to libpng */
-   png_uint_32 transformations; /* which transformations to perform */
-
-   z_stream zstream;          /* pointer to decompression structure (below) */
-   png_bytep zbuf;            /* buffer for zlib */
-   png_size_t zbuf_size;      /* size of zbuf */
-   int zlib_level;            /* holds zlib compression level */
-   int zlib_method;           /* holds zlib compression method */
-   int zlib_window_bits;      /* holds zlib compression window bits */
-   int zlib_mem_level;        /* holds zlib compression memory level */
-   int zlib_strategy;         /* holds zlib compression strategy */
-
-   png_uint_32 width;         /* width of image in pixels */
-   png_uint_32 height;        /* height of image in pixels */
-   png_uint_32 num_rows;      /* number of rows in current pass */
-   png_uint_32 usr_width;     /* width of row at start of write */
-   png_uint_32 rowbytes;      /* size of row in bytes */
-   png_uint_32 irowbytes;     /* size of current interlaced row in bytes */
-   png_uint_32 iwidth;        /* width of current interlaced row in pixels */
-   png_uint_32 row_number;    /* current row in interlace pass */
-   png_bytep prev_row;        /* buffer to save previous (unfiltered) row */
-   png_bytep row_buf;         /* buffer to save current (unfiltered) row */
-   png_bytep sub_row;         /* buffer to save "sub" row when filtering */
-   png_bytep up_row;          /* buffer to save "up" row when filtering */
-   png_bytep avg_row;         /* buffer to save "avg" row when filtering */
-   png_bytep paeth_row;       /* buffer to save "Paeth" row when filtering */
-   png_row_info row_info;     /* used for transformation routines */
-
-   png_uint_32 idat_size;     /* current IDAT size for read */
-   png_uint_32 crc;           /* current chunk CRC value */
-   png_colorp palette;        /* palette from the input file */
-   png_uint_16 num_palette;   /* number of color entries in palette */
-   png_uint_16 num_trans;     /* number of transparency values */
-   png_byte chunk_name[5];    /* null-terminated name of current chunk */
-   png_byte compression;      /* file compression type (always 0) */
-   png_byte filter;           /* file filter type (always 0) */
-   png_byte interlaced;       /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
-   png_byte pass;             /* current interlace pass (0 - 6) */
-   png_byte do_filter;        /* row filter flags (see PNG_FILTER_ below ) */
-   png_byte color_type;       /* color type of file */
-   png_byte bit_depth;        /* bit depth of file */
-   png_byte usr_bit_depth;    /* bit depth of users row */
-   png_byte pixel_depth;      /* number of bits per pixel */
-   png_byte channels;         /* number of channels in file */
-   png_byte usr_channels;     /* channels at start of write */
-   png_byte sig_bytes;        /* magic bytes read/written from start of file */
+   png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct for user transform */
+   png_byte user_transform_depth PNG_DEPSTRUCT;    /* bit depth of user transformed pixels */
+   png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user transformed pixels */
+#endif
+#endif
+
+   png_uint_32 mode PNG_DEPSTRUCT;          /* tells us where we are in the PNG file */
+   png_uint_32 flags PNG_DEPSTRUCT;         /* flags indicating various things to libpng */
+   png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations to perform */
+
+   z_stream zstream PNG_DEPSTRUCT;          /* pointer to decompression structure (below) */
+   png_bytep zbuf PNG_DEPSTRUCT;            /* buffer for zlib */
+   png_size_t zbuf_size PNG_DEPSTRUCT;      /* size of zbuf */
+   int zlib_level PNG_DEPSTRUCT;            /* holds zlib compression level */
+   int zlib_method PNG_DEPSTRUCT;           /* holds zlib compression method */
+   int zlib_window_bits PNG_DEPSTRUCT;      /* holds zlib compression window bits */
+   int zlib_mem_level PNG_DEPSTRUCT;        /* holds zlib compression memory level */
+   int zlib_strategy PNG_DEPSTRUCT;         /* holds zlib compression strategy */
+
+   png_uint_32 width PNG_DEPSTRUCT;         /* width of image in pixels */
+   png_uint_32 height PNG_DEPSTRUCT;        /* height of image in pixels */
+   png_uint_32 num_rows PNG_DEPSTRUCT;      /* number of rows in current pass */
+   png_uint_32 usr_width PNG_DEPSTRUCT;     /* width of row at start of write */
+   png_uint_32 rowbytes PNG_DEPSTRUCT;      /* size of row in bytes */
+#if 0 /* Replaced with the following in libpng-1.2.43 */
+   png_size_t irowbytes PNG_DEPSTRUCT;
+#endif
+/* Added in libpng-1.2.43 */
+#ifdef PNG_USER_LIMITS_SUPPORTED
+   /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown
+    * chunks that can be stored (0 means unlimited).
+    */
+   png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT;
+#endif
+   png_uint_32 iwidth PNG_DEPSTRUCT;        /* width of current interlaced row in pixels */
+   png_uint_32 row_number PNG_DEPSTRUCT;    /* current row in interlace pass */
+   png_bytep prev_row PNG_DEPSTRUCT;        /* buffer to save previous (unfiltered) row */
+   png_bytep row_buf PNG_DEPSTRUCT;         /* buffer to save current (unfiltered) row */
+#ifndef PNG_NO_WRITE_FILTER
+   png_bytep sub_row PNG_DEPSTRUCT;         /* buffer to save "sub" row when filtering */
+   png_bytep up_row PNG_DEPSTRUCT;          /* buffer to save "up" row when filtering */
+   png_bytep avg_row PNG_DEPSTRUCT;         /* buffer to save "avg" row when filtering */
+   png_bytep paeth_row PNG_DEPSTRUCT;       /* buffer to save "Paeth" row when filtering */
+#endif
+   png_row_info row_info PNG_DEPSTRUCT;     /* used for transformation routines */
+
+   png_uint_32 idat_size PNG_DEPSTRUCT;     /* current IDAT size for read */
+   png_uint_32 crc PNG_DEPSTRUCT;           /* current chunk CRC value */
+   png_colorp palette PNG_DEPSTRUCT;        /* palette from the input file */
+   png_uint_16 num_palette PNG_DEPSTRUCT;   /* number of color entries in palette */
+   png_uint_16 num_trans PNG_DEPSTRUCT;     /* number of transparency values */
+   png_byte chunk_name[5] PNG_DEPSTRUCT;    /* null-terminated name of current chunk */
+   png_byte compression PNG_DEPSTRUCT;      /* file compression type (always 0) */
+   png_byte filter PNG_DEPSTRUCT;           /* file filter type (always 0) */
+   png_byte interlaced PNG_DEPSTRUCT;       /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+   png_byte pass PNG_DEPSTRUCT;             /* current interlace pass (0 - 6) */
+   png_byte do_filter PNG_DEPSTRUCT;        /* row filter flags (see PNG_FILTER_ below ) */
+   png_byte color_type PNG_DEPSTRUCT;       /* color type of file */
+   png_byte bit_depth PNG_DEPSTRUCT;        /* bit depth of file */
+   png_byte usr_bit_depth PNG_DEPSTRUCT;    /* bit depth of users row */
+   png_byte pixel_depth PNG_DEPSTRUCT;      /* number of bits per pixel */
+   png_byte channels PNG_DEPSTRUCT;         /* number of channels in file */
+   png_byte usr_channels PNG_DEPSTRUCT;     /* channels at start of write */
+   png_byte sig_bytes PNG_DEPSTRUCT;        /* magic bytes read/written from start of file */
 
 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
 #ifdef PNG_LEGACY_SUPPORTED
-   png_byte filler;           /* filler byte for pixel expansion */
+   png_byte filler PNG_DEPSTRUCT;           /* filler byte for pixel expansion */
 #else
-   png_uint_16 filler;           /* filler bytes for pixel expansion */
+   png_uint_16 filler PNG_DEPSTRUCT;           /* filler bytes for pixel expansion */
 #endif
 #endif
 
-#if defined(PNG_bKGD_SUPPORTED)
-   png_byte background_gamma_type;
+#ifdef PNG_bKGD_SUPPORTED
+   png_byte background_gamma_type PNG_DEPSTRUCT;
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
-   float background_gamma;
+   float background_gamma PNG_DEPSTRUCT;
 #  endif
-   png_color_16 background;   /* background color in screen gamma space */
-#if defined(PNG_READ_GAMMA_SUPPORTED)
-   png_color_16 background_1; /* background normalized to gamma 1.0 */
+   png_color_16 background PNG_DEPSTRUCT;   /* background color in screen gamma space */
+#ifdef PNG_READ_GAMMA_SUPPORTED
+   png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized to gamma 1.0 */
 #endif
 #endif /* PNG_bKGD_SUPPORTED */
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
-   png_flush_ptr output_flush_fn;/* Function for flushing output */
-   png_uint_32 flush_dist;    /* how many rows apart to flush, 0 - no flush */
-   png_uint_32 flush_rows;    /* number of rows written since last flush */
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+   png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing output */
+   png_uint_32 flush_dist PNG_DEPSTRUCT;    /* how many rows apart to flush, 0 - no flush */
+   png_uint_32 flush_rows PNG_DEPSTRUCT;    /* number of rows written since last flush */
 #endif
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   int gamma_shift;      /* number of "insignificant" bits 16-bit gamma */
+   int gamma_shift PNG_DEPSTRUCT;      /* number of "insignificant" bits 16-bit gamma */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-   float gamma;          /* file gamma value */
-   float screen_gamma;   /* screen gamma value (display_exponent) */
+   float gamma PNG_DEPSTRUCT;          /* file gamma value */
+   float screen_gamma PNG_DEPSTRUCT;   /* screen gamma value (display_exponent) */
 #endif
 #endif
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   png_bytep gamma_table;     /* gamma table for 8-bit depth files */
-   png_bytep gamma_from_1;    /* converts from 1.0 to screen */
-   png_bytep gamma_to_1;      /* converts from file to 1.0 */
-   png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
-   png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
-   png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
+   png_bytep gamma_table PNG_DEPSTRUCT;     /* gamma table for 8-bit depth files */
+   png_bytep gamma_from_1 PNG_DEPSTRUCT;    /* converts from 1.0 to screen */
+   png_bytep gamma_to_1 PNG_DEPSTRUCT;      /* converts from file to 1.0 */
+   png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit depth files */
+   png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */
+   png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */
 #endif
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
-   png_color_8 sig_bit;       /* significant bits in each available channel */
+   png_color_8 sig_bit PNG_DEPSTRUCT;       /* significant bits in each available channel */
 #endif
 
 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
-   png_color_8 shift;         /* shift for significant bit tranformation */
+   png_color_8 shift PNG_DEPSTRUCT;         /* shift for significant bit tranformation */
 #endif
 
 #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
  || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   png_bytep trans;           /* transparency values for paletted files */
-   png_color_16 trans_values; /* transparency values for non-paletted files */
+   png_bytep trans PNG_DEPSTRUCT;           /* transparency values for paletted files */
+   png_color_16 trans_values PNG_DEPSTRUCT; /* transparency values for non-paletted files */
 #endif
 
-   png_read_status_ptr read_row_fn;   /* called after each row is decoded */
-   png_write_status_ptr write_row_fn; /* called after each row is encoded */
+   png_read_status_ptr read_row_fn PNG_DEPSTRUCT;   /* called after each row is decoded */
+   png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each row is encoded */
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-   png_progressive_info_ptr info_fn; /* called after header data fully read */
-   png_progressive_row_ptr row_fn;   /* called after each prog. row is decoded */
-   png_progressive_end_ptr end_fn;   /* called after image is complete */
-   png_bytep save_buffer_ptr;        /* current location in save_buffer */
-   png_bytep save_buffer;            /* buffer for previously read data */
-   png_bytep current_buffer_ptr;     /* current location in current_buffer */
-   png_bytep current_buffer;         /* buffer for recently used data */
-   png_uint_32 push_length;          /* size of current input chunk */
-   png_uint_32 skip_length;          /* bytes to skip in input data */
-   png_size_t save_buffer_size;      /* amount of data now in save_buffer */
-   png_size_t save_buffer_max;       /* total size of save_buffer */
-   png_size_t buffer_size;           /* total amount of available input data */
-   png_size_t current_buffer_size;   /* amount of data now in current_buffer */
-   int process_mode;                 /* what push library is currently doing */
-   int cur_palette;                  /* current push library palette index */
-
-#  if defined(PNG_TEXT_SUPPORTED)
-     png_size_t current_text_size;   /* current size of text input data */
-     png_size_t current_text_left;   /* how much text left to read in input */
-     png_charp current_text;         /* current text chunk buffer */
-     png_charp current_text_ptr;     /* current location in current_text */
+   png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header data fully read */
+   png_progressive_row_ptr row_fn PNG_DEPSTRUCT;   /* called after each prog. row is decoded */
+   png_progressive_end_ptr end_fn PNG_DEPSTRUCT;   /* called after image is complete */
+   png_bytep save_buffer_ptr PNG_DEPSTRUCT;        /* current location in save_buffer */
+   png_bytep save_buffer PNG_DEPSTRUCT;            /* buffer for previously read data */
+   png_bytep current_buffer_ptr PNG_DEPSTRUCT;     /* current location in current_buffer */
+   png_bytep current_buffer PNG_DEPSTRUCT;         /* buffer for recently used data */
+   png_uint_32 push_length PNG_DEPSTRUCT;          /* size of current input chunk */
+   png_uint_32 skip_length PNG_DEPSTRUCT;          /* bytes to skip in input data */
+   png_size_t save_buffer_size PNG_DEPSTRUCT;      /* amount of data now in save_buffer */
+   png_size_t save_buffer_max PNG_DEPSTRUCT;       /* total size of save_buffer */
+   png_size_t buffer_size PNG_DEPSTRUCT;           /* total amount of available input data */
+   png_size_t current_buffer_size PNG_DEPSTRUCT;   /* amount of data now in current_buffer */
+   int process_mode PNG_DEPSTRUCT;                 /* what push library is currently doing */
+   int cur_palette PNG_DEPSTRUCT;                  /* current push library palette index */
+
+#  ifdef PNG_TEXT_SUPPORTED
+     png_size_t current_text_size PNG_DEPSTRUCT;   /* current size of text input data */
+     png_size_t current_text_left PNG_DEPSTRUCT;   /* how much text left to read in input */
+     png_charp current_text PNG_DEPSTRUCT;         /* current text chunk buffer */
+     png_charp current_text_ptr PNG_DEPSTRUCT;     /* current location in current_text */
 #  endif /* PNG_TEXT_SUPPORTED */
 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 
 #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
 /* for the Borland special 64K segment handler */
-   png_bytepp offset_table_ptr;
-   png_bytep offset_table;
-   png_uint_16 offset_table_number;
-   png_uint_16 offset_table_count;
-   png_uint_16 offset_table_count_free;
+   png_bytepp offset_table_ptr PNG_DEPSTRUCT;
+   png_bytep offset_table PNG_DEPSTRUCT;
+   png_uint_16 offset_table_number PNG_DEPSTRUCT;
+   png_uint_16 offset_table_count PNG_DEPSTRUCT;
+   png_uint_16 offset_table_count_free PNG_DEPSTRUCT;
 #endif
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
-   png_bytep palette_lookup;         /* lookup table for dithering */
-   png_bytep dither_index;           /* index translation for palette files */
+#ifdef PNG_READ_DITHER_SUPPORTED
+   png_bytep palette_lookup PNG_DEPSTRUCT;         /* lookup table for dithering */
+   png_bytep dither_index PNG_DEPSTRUCT;           /* index translation for palette files */
 #endif
 
 #if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED)
-   png_uint_16p hist;                /* histogram */
+   png_uint_16p hist PNG_DEPSTRUCT;                /* histogram */
 #endif
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
-   png_byte heuristic_method;        /* heuristic for row filter selection */
-   png_byte num_prev_filters;        /* number of weights for previous rows */
-   png_bytep prev_filters;           /* filter type(s) of previous row(s) */
-   png_uint_16p filter_weights;      /* weight(s) for previous line(s) */
-   png_uint_16p inv_filter_weights;  /* 1/weight(s) for previous line(s) */
-   png_uint_16p filter_costs;        /* relative filter calculation cost */
-   png_uint_16p inv_filter_costs;    /* 1/relative filter calculation cost */
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+   png_byte heuristic_method PNG_DEPSTRUCT;        /* heuristic for row filter selection */
+   png_byte num_prev_filters PNG_DEPSTRUCT;        /* number of weights for previous rows */
+   png_bytep prev_filters PNG_DEPSTRUCT;           /* filter type(s) of previous row(s) */
+   png_uint_16p filter_weights PNG_DEPSTRUCT;      /* weight(s) for previous line(s) */
+   png_uint_16p inv_filter_weights PNG_DEPSTRUCT;  /* 1/weight(s) for previous line(s) */
+   png_uint_16p filter_costs PNG_DEPSTRUCT;        /* relative filter calculation cost */
+   png_uint_16p inv_filter_costs PNG_DEPSTRUCT;    /* 1/relative filter calculation cost */
 #endif
 
-#if defined(PNG_TIME_RFC1123_SUPPORTED)
-   png_charp time_buffer;            /* String to hold RFC 1123 time text */
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+   png_charp time_buffer PNG_DEPSTRUCT;            /* String to hold RFC 1123 time text */
 #endif
 
 /* New members added in libpng-1.0.6 */
 
 #ifdef PNG_FREE_ME_SUPPORTED
-   png_uint_32 free_me;       /* flags items libpng is responsible for freeing */
+   png_uint_32 free_me PNG_DEPSTRUCT;   /* flags items libpng is responsible for freeing */
 #endif
 
-#if defined(PNG_USER_CHUNKS_SUPPORTED)
-   png_voidp user_chunk_ptr;
-   png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+   png_voidp user_chunk_ptr PNG_DEPSTRUCT;
+   png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read chunk handler */
 #endif
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-   int num_chunk_list;
-   png_bytep chunk_list;
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+   int num_chunk_list PNG_DEPSTRUCT;
+   png_bytep chunk_list PNG_DEPSTRUCT;
 #endif
 
 /* New members added in libpng-1.0.3 */
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-   png_byte rgb_to_gray_status;
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+   png_byte rgb_to_gray_status PNG_DEPSTRUCT;
    /* These were changed from png_byte in libpng-1.0.6 */
-   png_uint_16 rgb_to_gray_red_coeff;
-   png_uint_16 rgb_to_gray_green_coeff;
-   png_uint_16 rgb_to_gray_blue_coeff;
+   png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT;
+   png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT;
+   png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT;
 #endif
 
 /* New member added in libpng-1.0.4 (renamed in 1.0.9) */
 #if defined(PNG_MNG_FEATURES_SUPPORTED) || \
     defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
     defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
-/* changed from png_byte to png_uint_32 at version 1.2.0 */
+/* Changed from png_byte to png_uint_32 at version 1.2.0 */
 #ifdef PNG_1_0_X
-   png_byte mng_features_permitted;
+   png_byte mng_features_permitted PNG_DEPSTRUCT;
 #else
-   png_uint_32 mng_features_permitted;
+   png_uint_32 mng_features_permitted PNG_DEPSTRUCT;
 #endif /* PNG_1_0_X */
 #endif
 
 /* New member added in libpng-1.0.7 */
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   png_fixed_point int_gamma;
+   png_fixed_point int_gamma PNG_DEPSTRUCT;
 #endif
 
 /* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-   png_byte filter_type;
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+   png_byte filter_type PNG_DEPSTRUCT;
 #endif
 
-#if defined(PNG_1_0_X)
+#ifdef PNG_1_0_X
 /* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */
-   png_uint_32 row_buf_size;
+   png_uint_32 row_buf_size PNG_DEPSTRUCT;
 #endif
 
 /* New members added in libpng-1.2.0 */
-#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
-#  if !defined(PNG_1_0_X)
-#    if defined(PNG_MMX_CODE_SUPPORTED)
-   png_byte     mmx_bitdepth_threshold;
-   png_uint_32  mmx_rowbytes_threshold;
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+#  ifndef PNG_1_0_X
+#    ifdef PNG_MMX_CODE_SUPPORTED
+   png_byte     mmx_bitdepth_threshold PNG_DEPSTRUCT;
+   png_uint_32  mmx_rowbytes_threshold PNG_DEPSTRUCT;
 #    endif
-   png_uint_32  asm_flags;
+   png_uint_32  asm_flags PNG_DEPSTRUCT;
 #  endif
 #endif
 
 /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
 #ifdef PNG_USER_MEM_SUPPORTED
-   png_voidp mem_ptr;                /* user supplied struct for mem functions */
-   png_malloc_ptr malloc_fn;         /* function for allocating memory */
-   png_free_ptr free_fn;             /* function for freeing memory */
+   png_voidp mem_ptr PNG_DEPSTRUCT;            /* user supplied struct for mem functions */
+   png_malloc_ptr malloc_fn PNG_DEPSTRUCT;     /* function for allocating memory */
+   png_free_ptr free_fn PNG_DEPSTRUCT;         /* function for freeing memory */
 #endif
 
 /* New member added in libpng-1.0.13 and 1.2.0 */
-   png_bytep big_row_buf;         /* buffer to save current (unfiltered) row */
+   png_bytep big_row_buf PNG_DEPSTRUCT;        /* buffer to save current (unfiltered) row */
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
+#ifdef PNG_READ_DITHER_SUPPORTED
 /* The following three members were added at version 1.0.14 and 1.2.4 */
-   png_bytep dither_sort;            /* working sort array */
-   png_bytep index_to_palette;       /* where the original index currently is */
-                                     /* in the palette */
-   png_bytep palette_to_index;       /* which original index points to this */
-                                     /* palette color */
+   png_bytep dither_sort PNG_DEPSTRUCT;        /* working sort array */
+   png_bytep index_to_palette PNG_DEPSTRUCT;   /* where the original index currently is */
+                                 /* in the palette */
+   png_bytep palette_to_index PNG_DEPSTRUCT;   /* which original index points to this */
+                                 /* palette color */
 #endif
 
 /* New members added in libpng-1.0.16 and 1.2.6 */
-   png_byte compression_type;
+   png_byte compression_type PNG_DEPSTRUCT;
 
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   png_uint_32 user_width_max;
-   png_uint_32 user_height_max;
+#ifdef PNG_USER_LIMITS_SUPPORTED
+   png_uint_32 user_width_max PNG_DEPSTRUCT;
+   png_uint_32 user_height_max PNG_DEPSTRUCT;
 #endif
 
 /* New member added in libpng-1.0.25 and 1.2.17 */
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-   /* storage for unknown chunk that the library doesn't recognize. */
-   png_unknown_chunk unknown_chunk;
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+   /* Storage for unknown chunk that the library doesn't recognize. */
+   png_unknown_chunk unknown_chunk PNG_DEPSTRUCT;
 #endif
+
+/* New members added in libpng-1.2.26 */
+  png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT;
+  png_uint_32 old_prev_row_size PNG_DEPSTRUCT;
+
+/* New member added in libpng-1.2.30 */
+  png_charp chunkdata PNG_DEPSTRUCT;  /* buffer for reading chunk data */
+
+
 };
 
 
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef png_structp version_1_2_23;
+typedef png_structp version_1_2_50;
 
 typedef png_struct FAR * FAR * png_structpp;
 
@@ -1459,17 +1603,17 @@ extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start,
 /* Simple signature checking function.  This is the same as calling
  * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
  */
-extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num));
+extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)) PNG_DEPRECATED;
 
 /* Allocate and initialize png_ptr struct for reading, and any other memory. */
 extern PNG_EXPORT(png_structp,png_create_read_struct)
    PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
-   png_error_ptr error_fn, png_error_ptr warn_fn));
+   png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED;
 
 /* Allocate and initialize png_ptr struct for writing, and any other memory */
 extern PNG_EXPORT(png_structp,png_create_write_struct)
    PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
-   png_error_ptr error_fn, png_error_ptr warn_fn));
+   png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED;
 
 #ifdef PNG_WRITE_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size)
@@ -1489,11 +1633,11 @@ extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr));
 extern PNG_EXPORT(png_structp,png_create_read_struct_2)
    PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
-   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED;
 extern PNG_EXPORT(png_structp,png_create_write_struct_2)
    PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
-   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED;
 #endif
 
 /* Write a PNG chunk - size, type, (optional) data, CRC. */
@@ -1513,11 +1657,12 @@ extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr));
 
 /* Allocate and initialize the info structure */
 extern PNG_EXPORT(png_infop,png_create_info_struct)
-   PNGARG((png_structp png_ptr));
+   PNGARG((png_structp png_ptr)) PNG_ALLOCATED;
 
 #if defined(PNG_1_0_X) || defined (PNG_1_2_X)
 /* Initialize the info structure (old interface - DEPRECATED) */
-extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr));
+extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr))
+    PNG_DEPRECATED;
 #undef png_info_init
 #define png_info_init(info_ptr) png_info_init_3(&info_ptr,\
     png_sizeof(png_info));
@@ -1532,34 +1677,31 @@ extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr,
 extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr,
    png_infop info_ptr));
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
-/* read the information before the actual image data. */
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Read the information before the actual image data. */
 extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr,
    png_infop info_ptr));
 #endif
 
-#if defined(PNG_TIME_RFC1123_SUPPORTED)
+#ifdef PNG_TIME_RFC1123_SUPPORTED
 extern PNG_EXPORT(png_charp,png_convert_to_rfc1123)
    PNGARG((png_structp png_ptr, png_timep ptime));
 #endif
 
-#if !defined(_WIN32_WCE)
-/* "time.h" functions are not supported on WindowsCE */
-#if defined(PNG_WRITE_tIME_SUPPORTED)
-/* convert from a struct tm to png_time */
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+/* Convert from a struct tm to png_time */
 extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime,
    struct tm FAR * ttime));
 
-/* convert from time_t to png_time.  Uses gmtime() */
+/* Convert from time_t to png_time.  Uses gmtime() */
 extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime,
    time_t ttime));
-#endif /* PNG_WRITE_tIME_SUPPORTED */
-#endif /* _WIN32_WCE */
+#endif /* PNG_CONVERT_tIME_SUPPORTED */
 
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
 /* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
 extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr));
-#if !defined(PNG_1_0_X)
+#ifndef PNG_1_0_X
 extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp
   png_ptr));
 #endif
@@ -1567,7 +1709,8 @@ extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr));
 extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr));
 #if defined(PNG_1_0_X) || defined (PNG_1_2_X)
 /* Deprecated */
-extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp
+    png_ptr)) PNG_DEPRECATED;
 #endif
 #endif
 
@@ -1576,12 +1719,12 @@ extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr));
 extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr));
 #endif
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
 /* Expand the grayscale to 24-bit RGB if necessary. */
 extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr));
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
 /* Reduce RGB to grayscale. */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr,
@@ -1596,7 +1739,7 @@ extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp
 extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth,
    png_colorp palette));
 
-#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
 extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr));
 #endif
 
@@ -1618,7 +1761,7 @@ extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr,
 #define PNG_FILLER_BEFORE 0
 #define PNG_FILLER_AFTER 1
 /* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */
-#if !defined(PNG_1_0_X)
+#ifndef PNG_1_0_X
 extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr,
    png_uint_32 filler, int flags));
 #endif
@@ -1656,7 +1799,7 @@ extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr));
 extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr));
 #endif
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
 /* Handle alpha and tRNS by replacing with a background color. */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr,
@@ -1669,19 +1812,19 @@ extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr,
 #define PNG_BACKGROUND_GAMMA_UNIQUE  3
 #endif
 
-#if defined(PNG_READ_16_TO_8_SUPPORTED)
-/* strip the second byte of information from a 16-bit depth file. */
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+/* Strip the second byte of information from a 16-bit depth file. */
 extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr));
 #endif
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
+#ifdef PNG_READ_DITHER_SUPPORTED
 /* Turn on dithering, and reduce the palette to the number of colors available. */
 extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr,
    png_colorp palette, int num_palette, int maximum_colors,
    png_uint_16p histogram, int full_dither));
 #endif
 
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
 /* Handle gamma correction. Screen_gamma=(display_exponent) */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr,
@@ -1695,85 +1838,85 @@ extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr,
 /* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */
 /* Deprecated and will be removed.  Use png_permit_mng_features() instead. */
 extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr,
-   int empty_plte_permitted));
+   int empty_plte_permitted)) PNG_DEPRECATED;
 #endif
 #endif
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
 /* Set how many lines between output flushes - 0 for no flushing */
 extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows));
 /* Flush the current PNG output buffer */
 extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr));
 #endif
 
-/* optional update palette with requested transformations */
+/* Optional update palette with requested transformations */
 extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr));
 
-/* optional call to update the users info structure */
+/* Optional call to update the users info structure */
 extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr,
    png_infop info_ptr));
 
 #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
-/* read one or more rows of image data. */
+/* Read one or more rows of image data. */
 extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr,
    png_bytepp row, png_bytepp display_row, png_uint_32 num_rows));
 #endif
 
 #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
-/* read a row of data. */
+/* Read a row of data. */
 extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr,
    png_bytep row,
    png_bytep display_row));
 #endif
 
 #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
-/* read the whole image into memory at once. */
+/* Read the whole image into memory at once. */
 extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr,
    png_bytepp image));
 #endif
 
-/* write a row of image data */
+/* Write a row of image data */
 extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr,
    png_bytep row));
 
-/* write a few rows of image data */
+/* Write a few rows of image data */
 extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr,
    png_bytepp row, png_uint_32 num_rows));
 
-/* write the image data */
+/* Write the image data */
 extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr,
    png_bytepp image));
 
-/* writes the end of the PNG file. */
+/* Writes the end of the PNG file. */
 extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr,
    png_infop info_ptr));
 
 #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
-/* read the end of the PNG file. */
+/* Read the end of the PNG file. */
 extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr,
    png_infop info_ptr));
 #endif
 
-/* free any memory associated with the png_info_struct */
+/* Free any memory associated with the png_info_struct */
 extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr,
    png_infopp info_ptr_ptr));
 
-/* free any memory associated with the png_struct and the png_info_structs */
+/* Free any memory associated with the png_struct and the png_info_structs */
 extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp
    png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr));
 
-/* free all memory used by the read (old method - NOT DLL EXPORTED) */
+/* Free all memory used by the read (old method - NOT DLL EXPORTED) */
 extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_infop end_info_ptr));
+   png_infop end_info_ptr)) PNG_DEPRECATED;
 
-/* free any memory associated with the png_struct and the png_info_structs */
+/* Free any memory associated with the png_struct and the png_info_structs */
 extern PNG_EXPORT(void,png_destroy_write_struct)
    PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr));
 
-/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
-extern void png_write_destroy PNGARG((png_structp png_ptr));
+/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
+extern void png_write_destroy PNGARG((png_structp png_ptr)) PNG_DEPRECATED;
 
-/* set the libpng method of handling chunk CRC errors */
+/* Set the libpng method of handling chunk CRC errors */
 extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr,
    int crit_action, int ancil_action));
 
@@ -1801,7 +1944,7 @@ extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr,
  * header file (zlib.h) for an explination of the compression functions.
  */
 
-/* set the filtering method(s) used by libpng.  Currently, the only valid
+/* Set the filtering method(s) used by libpng.  Currently, the only valid
  * value for "method" is 0.
  */
 extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method,
@@ -1906,7 +2049,7 @@ extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr,
  * more information.
  */
 
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_STDIO_SUPPORTED
 /* Initialize the input/output for the PNG file to the default functions. */
 extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp));
 #endif
@@ -1929,6 +2072,11 @@ extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr));
  * If buffered output is not used, then output_flush_fn can be set to NULL.
  * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
  * output_flush_fn will be ignored (and thus can be NULL).
+ * It is probably a mistake to use NULL for output_flush_fn if
+ * write_data_fn is not also NULL unless you have built libpng with
+ * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's
+ * default flush function, which uses the standard *FILE structure, will
+ * be used.
  */
 extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr,
    png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
@@ -1993,15 +2141,15 @@ extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr,
    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
    png_progressive_end_ptr end_fn));
 
-/* returns the user pointer associated with the push read functions */
+/* Returns the user pointer associated with the push read functions */
 extern PNG_EXPORT(png_voidp,png_get_progressive_ptr)
    PNGARG((png_structp png_ptr));
 
-/* function to be called when data becomes available */
+/* Function to be called when data becomes available */
 extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_bytep buffer, png_size_t buffer_size));
 
-/* function that combines rows.  Not very much different than the
+/* Function that combines rows.  Not very much different than the
  * png_combine_row() call.  Is this even used?????
  */
 extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr,
@@ -2009,20 +2157,20 @@ extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr,
 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 
 extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr,
-   png_uint_32 size));
+   png_uint_32 size)) PNG_ALLOCATED;
 
-#if defined(PNG_1_0_X)
+#ifdef PNG_1_0_X
 #  define png_malloc_warn png_malloc
 #else
 /* Added at libpng version 1.2.4 */
 extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr,
-   png_uint_32 size));
+   png_uint_32 size)) PNG_ALLOCATED;
 #endif
 
-/* frees a pointer allocated by png_malloc() */
+/* Frees a pointer allocated by png_malloc() */
 extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr));
 
-#if defined(PNG_1_0_X)
+#ifdef PNG_1_0_X
 /* Function to allocate memory for zlib. */
 extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items,
    uInt size));
@@ -2036,11 +2184,12 @@ extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_uint_32 free_me, int num));
 #ifdef PNG_FREE_ME_SUPPORTED
 /* Reassign responsibility for freeing existing data, whether allocated
- * by libpng or by the application */
+ * by libpng or by the application
+ */
 extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int freer, png_uint_32 mask));
 #endif
-/* assignments for png_data_freer */
+/* Assignments for png_data_freer */
 #define PNG_DESTROY_WILL_FREE_DATA 1
 #define PNG_SET_WILL_FREE_DATA 1
 #define PNG_USER_WILL_FREE_DATA 2
@@ -2061,16 +2210,16 @@ extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr,
 
 #ifdef PNG_USER_MEM_SUPPORTED
 extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr,
-   png_uint_32 size));
+   png_uint_32 size)) PNG_ALLOCATED;
 extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr,
    png_voidp ptr));
 #endif
 
 extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr,
-   png_voidp s1, png_voidp s2, png_uint_32 size));
+   png_voidp s1, png_voidp s2, png_uint_32 size)) PNG_DEPRECATED;
 
 extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr,
-   png_voidp s1, int value, png_uint_32 size));
+   png_voidp s1, int value, png_uint_32 size)) PNG_DEPRECATED;
 
 #if defined(USE_FAR_KEYWORD)  /* memory model conversion function */
 extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
@@ -2080,14 +2229,14 @@ extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
 #ifndef PNG_NO_ERROR_TEXT
 /* Fatal error in PNG image of libpng - can't continue */
 extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr,
-   png_const_charp error_message));
+   png_const_charp error_message)) PNG_NORETURN;
 
 /* The same, but the chunk name is prepended to the error string. */
 extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr,
-   png_const_charp error_message));
+   png_const_charp error_message)) PNG_NORETURN;
 #else
 /* Fatal error in PNG image of libpng - can't continue */
-extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN;
 #endif
 
 #ifndef PNG_NO_WARNINGS
@@ -2122,13 +2271,15 @@ png_infop info_ptr, png_uint_32 flag));
 extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr,
 png_infop info_ptr));
 
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
+#ifdef PNG_INFO_IMAGE_SUPPORTED
 /* Returns row_pointers, which is an array of pointers to scanlines that was
-returned from png_read_png(). */
+ * returned from png_read_png().
+ */
 extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr,
 png_infop info_ptr));
 /* Set row_pointers, which is an array of pointers to scanlines for use
-by png_write_png(). */
+ * by png_write_png().
+ */
 extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_bytepp row_pointers));
 #endif
@@ -2196,17 +2347,17 @@ png_ptr, png_infop info_ptr));
 extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr,
 png_infop info_ptr));
 
-#if defined(PNG_bKGD_SUPPORTED)
+#ifdef PNG_bKGD_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_color_16p *background));
 #endif
 
-#if defined(PNG_bKGD_SUPPORTED)
+#ifdef PNG_bKGD_SUPPORTED
 extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_color_16p background));
 #endif
 
-#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_cHRM_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr,
    png_infop info_ptr, double *white_x, double *white_y, double *red_x,
@@ -2222,7 +2373,7 @@ extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr,
 #endif
 #endif
 
-#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_cHRM_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr,
    png_infop info_ptr, double white_x, double white_y, double red_x,
@@ -2237,7 +2388,7 @@ extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr,
 #endif
 #endif
 
-#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_gAMA_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr,
    png_infop info_ptr, double *file_gamma));
@@ -2246,7 +2397,7 @@ extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_fixed_point *int_file_gamma));
 #endif
 
-#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_gAMA_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr,
    png_infop info_ptr, double file_gamma));
@@ -2255,12 +2406,12 @@ extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_fixed_point int_file_gamma));
 #endif
 
-#if defined(PNG_hIST_SUPPORTED)
+#ifdef PNG_hIST_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_uint_16p *hist));
 #endif
 
-#if defined(PNG_hIST_SUPPORTED)
+#ifdef PNG_hIST_SUPPORTED
 extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_uint_16p hist));
 #endif
@@ -2275,36 +2426,36 @@ extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr,
    int color_type, int interlace_method, int compression_method,
    int filter_method));
 
-#if defined(PNG_oFFs_SUPPORTED)
+#ifdef PNG_oFFs_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
    int *unit_type));
 #endif
 
-#if defined(PNG_oFFs_SUPPORTED)
+#ifdef PNG_oFFs_SUPPORTED
 extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y,
    int unit_type));
 #endif
 
-#if defined(PNG_pCAL_SUPPORTED)
+#ifdef PNG_pCAL_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1,
    int *type, int *nparams, png_charp *units, png_charpp *params));
 #endif
 
-#if defined(PNG_pCAL_SUPPORTED)
+#ifdef PNG_pCAL_SUPPORTED
 extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1,
    int type, int nparams, png_charp units, png_charpp params));
 #endif
 
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
 #endif
 
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
 extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
 #endif
@@ -2315,53 +2466,53 @@ extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr,
 extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_colorp palette, int num_palette));
 
-#if defined(PNG_sBIT_SUPPORTED)
+#ifdef PNG_sBIT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_color_8p *sig_bit));
 #endif
 
-#if defined(PNG_sBIT_SUPPORTED)
+#ifdef PNG_sBIT_SUPPORTED
 extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_color_8p sig_bit));
 #endif
 
-#if defined(PNG_sRGB_SUPPORTED)
+#ifdef PNG_sRGB_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int *intent));
 #endif
 
-#if defined(PNG_sRGB_SUPPORTED)
+#ifdef PNG_sRGB_SUPPORTED
 extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int intent));
 extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int intent));
 #endif
 
-#if defined(PNG_iCCP_SUPPORTED)
+#ifdef PNG_iCCP_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_charpp name, int *compression_type,
    png_charpp profile, png_uint_32 *proflen));
    /* Note to maintainer: profile should be png_bytepp */
 #endif
 
-#if defined(PNG_iCCP_SUPPORTED)
+#ifdef PNG_iCCP_SUPPORTED
 extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_charp name, int compression_type,
    png_charp profile, png_uint_32 proflen));
    /* Note to maintainer: profile should be png_bytep */
 #endif
 
-#if defined(PNG_sPLT_SUPPORTED)
+#ifdef PNG_sPLT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_sPLT_tpp entries));
 #endif
 
-#if defined(PNG_sPLT_SUPPORTED)
+#ifdef PNG_sPLT_SUPPORTED
 extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_sPLT_tp entries, int nentries));
 #endif
 
-#if defined(PNG_TEXT_SUPPORTED)
+#ifdef PNG_TEXT_SUPPORTED
 /* png_get_text also returns the number of text chunks in *num_text */
 extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_textp *text_ptr, int *num_text));
@@ -2375,37 +2526,37 @@ extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr,
  *  they will never be NULL pointers.
  */
 
-#if defined(PNG_TEXT_SUPPORTED)
+#ifdef PNG_TEXT_SUPPORTED
 extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_textp text_ptr, int num_text));
 #endif
 
-#if defined(PNG_tIME_SUPPORTED)
+#ifdef PNG_tIME_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_timep *mod_time));
 #endif
 
-#if defined(PNG_tIME_SUPPORTED)
+#ifdef PNG_tIME_SUPPORTED
 extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_timep mod_time));
 #endif
 
-#if defined(PNG_tRNS_SUPPORTED)
+#ifdef PNG_tRNS_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_bytep *trans, int *num_trans,
    png_color_16p *trans_values));
 #endif
 
-#if defined(PNG_tRNS_SUPPORTED)
+#ifdef PNG_tRNS_SUPPORTED
 extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_bytep trans, int num_trans,
    png_color_16p trans_values));
 #endif
 
-#if defined(PNG_tRNS_SUPPORTED)
+#ifdef PNG_tRNS_SUPPORTED
 #endif
 
-#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_sCAL_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int *unit, double *width, double *height));
@@ -2417,7 +2568,7 @@ extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr,
 #endif
 #endif /* PNG_sCAL_SUPPORTED */
 
-#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_sCAL_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int unit, double width, double height));
@@ -2429,8 +2580,8 @@ extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr,
 #endif
 #endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-/* provide a list of chunks and how they are to be handled, if the built-in
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+/* Provide a list of chunks and how they are to be handled, if the built-in
    handling or default unknown chunk handling is not desired.  Any chunks not
    listed will be handled in the default manner.  The IHDR and IEND chunks
    must not be listed.
@@ -2441,6 +2592,10 @@ extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr,
 */
 extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp
    png_ptr, int keep, png_bytep chunk_list, int num_chunks));
+PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep
+   chunk_name));
+#endif
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
 extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr,
    png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns));
 extern PNG_EXPORT(void, png_set_unknown_chunk_location)
@@ -2448,18 +2603,15 @@ extern PNG_EXPORT(void, png_set_unknown_chunk_location)
 extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp
    png_ptr, png_infop info_ptr, png_unknown_chunkpp entries));
 #endif
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep
-   chunk_name));
-#endif
 
 /* Png_free_data() will turn off the "valid" flag for anything it frees.
-   If you need to turn it off for a chunk that your application has freed,
-   you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */
+ * If you need to turn it off for a chunk that your application has freed,
+ * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
+ */
 extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr,
    png_infop info_ptr, int mask));
 
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
+#ifdef PNG_INFO_IMAGE_SUPPORTED
 /* The "params" pointer is currently not used and is for future expansion. */
 extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr,
                         png_infop info_ptr,
@@ -2481,34 +2633,90 @@ extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr,
 #if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
 #include <crtdbg.h>
 #if (PNG_DEBUG > 1)
-#define png_debug(l,m)  _RPT0(_CRT_WARN,m)
-#define png_debug1(l,m,p1)  _RPT1(_CRT_WARN,m,p1)
-#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2)
+#ifndef _DEBUG
+#  define _DEBUG
+#endif
+#ifndef png_debug
+#define png_debug(l,m)  _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE)
+#endif
+#ifndef png_debug1
+#define png_debug1(l,m,p1)  _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1)
+#endif
+#ifndef png_debug2
+#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2)
+#endif
 #endif
 #else /* PNG_DEBUG_FILE || !_MSC_VER */
 #ifndef PNG_DEBUG_FILE
 #define PNG_DEBUG_FILE stderr
 #endif /* PNG_DEBUG_FILE */
+
 #if (PNG_DEBUG > 1)
-#define png_debug(l,m) \
-{ \
-     int num_tabs=l; \
-     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
-       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
-}
-#define png_debug1(l,m,p1) \
-{ \
-     int num_tabs=l; \
-     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
-       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
-}
-#define png_debug2(l,m,p1,p2) \
-{ \
-     int num_tabs=l; \
-     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
-       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
-}
+/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on non-ISO
+ * compilers.
+ */
+#  ifdef __STDC__
+#    ifndef png_debug
+#      define png_debug(l,m) \
+       { \
+       int num_tabs=l; \
+       fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
+       }
+#    endif
+#    ifndef png_debug1
+#      define png_debug1(l,m,p1) \
+       { \
+       int num_tabs=l; \
+       fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
+       }
+#    endif
+#    ifndef png_debug2
+#      define png_debug2(l,m,p1,p2) \
+       { \
+       int num_tabs=l; \
+       fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
+       }
+#    endif
+#  else /* __STDC __ */
+#    ifndef png_debug
+#      define png_debug(l,m) \
+       { \
+       int num_tabs=l; \
+       char format[256]; \
+       snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
+         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
+         m,PNG_STRING_NEWLINE); \
+       fprintf(PNG_DEBUG_FILE,format); \
+       }
+#    endif
+#    ifndef png_debug1
+#      define png_debug1(l,m,p1) \
+       { \
+       int num_tabs=l; \
+       char format[256]; \
+       snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
+         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
+         m,PNG_STRING_NEWLINE); \
+       fprintf(PNG_DEBUG_FILE,format,p1); \
+       }
+#    endif
+#    ifndef png_debug2
+#      define png_debug2(l,m,p1,p2) \
+       { \
+       int num_tabs=l; \
+       char format[256]; \
+       snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
+         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
+         m,PNG_STRING_NEWLINE); \
+       fprintf(PNG_DEBUG_FILE,format,p1,p2); \
+       }
+#    endif
+#  endif /* __STDC __ */
 #endif /* (PNG_DEBUG > 1) */
+
 #endif /* _MSC_VER */
 #endif /* (PNG_DEBUG > 0) */
 #endif /* PNG_DEBUG */
@@ -2539,8 +2747,8 @@ extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp
 #define PNG_HANDLE_CHUNK_ALWAYS       3
 
 /* Added to version 1.2.0 */
-#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
-#if defined(PNG_MMX_CODE_SUPPORTED)
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+#ifdef PNG_MMX_CODE_SUPPORTED
 #define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED  0x01  /* not user-settable */
 #define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU    0x02  /* not user-settable */
 #define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  0x04
@@ -2568,7 +2776,7 @@ extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp
 #define PNG_SELECT_WRITE  2
 #endif /* PNG_MMX_CODE_SUPPORTED */
 
-#if !defined(PNG_1_0_X)
+#ifndef PNG_1_0_X
 /* pngget.c */
 extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask)
    PNGARG((int flag_select, int *compilerID));
@@ -2600,20 +2808,20 @@ extern PNG_EXPORT(void,png_set_mmx_thresholds)
 
 #endif /* PNG_1_0_X */
 
-#if !defined(PNG_1_0_X)
+#ifndef PNG_1_0_X
 /* png.c, pnggccrd.c, or pngvcrd.c */
 extern PNG_EXPORT(int,png_mmx_support) PNGARG((void));
+#endif /* PNG_1_0_X */
 #endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
 
 /* Strip the prepended error numbers ("#nnn ") from error and warning
- * messages before passing them to the error or warning handler. */
+ * messages before passing them to the error or warning handler.
+ */
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
 extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp
    png_ptr, png_uint_32 strip_mode));
 #endif
 
-#endif /* PNG_1_0_X */
-
 /* Added at libpng-1.2.6 */
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
 extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp
@@ -2623,8 +2831,9 @@ extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp
 extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp
    png_ptr));
 #endif
-
-/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */
+/* Maintainer: Put new public prototypes here ^, in libpng.3, and in
+ * project defs
+ */
 
 #ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
 /* With these routines we avoid an integer divide, which will be slower on
@@ -2653,7 +2862,7 @@ extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp
                         (png_uint_32)(alpha)) + (png_uint_32)32768L);        \
        (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
 
-#else  /* standard method using integer division */
+#else  /* Standard method using integer division */
 
 #  define png_composite(composite, fg, alpha, bg)                            \
      (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) +    \
@@ -2675,7 +2884,7 @@ extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp
  * routine also assumes we are using two's complement format for negative
  * values, which is almost certainly true.
  */
-#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED)
+#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
 #  define png_get_uint_32(buf) ( *((png_uint_32p) (buf)))
 #  define png_get_uint_16(buf) ( *((png_uint_16p) (buf)))
 #  define png_get_int_32(buf)  ( *((png_int_32p)  (buf)))
@@ -2721,7 +2930,7 @@ extern PNG_EXPORT(void,png_save_uint_16)
 #define PNG_AFTER_IDAT              0x08 /* Have complete zlib datastream */
 #define PNG_HAVE_IEND               0x10
 
-#if defined(PNG_INTERNAL)
+#ifdef PNG_INTERNAL
 
 /* More modes of operation.  Note that after an init, mode is set to
  * zero automatically when the structure is created.
@@ -2736,7 +2945,7 @@ extern PNG_EXPORT(void,png_save_uint_16)
 #define PNG_HAVE_PNG_SIGNATURE    0x1000
 #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
 
-/* flags for the transformations the PNG library does on the image data */
+/* Flags for the transformations the PNG library does on the image data */
 #define PNG_BGR                0x0001
 #define PNG_INTERLACE          0x0002
 #define PNG_PACK               0x0004
@@ -2764,13 +2973,14 @@ extern PNG_EXPORT(void,png_save_uint_16)
                        /*    0x800000L     Unused */
 #define PNG_ADD_ALPHA       0x1000000L  /* Added to libpng-1.2.7 */
 #define PNG_EXPAND_tRNS     0x2000000L  /* Added to libpng-1.2.9 */
-                       /*   0x4000000L  unused */
+#define PNG_PREMULTIPLY_ALPHA 0x4000000L  /* Added to libpng-1.2.41 */
+                                          /* by volker */
                        /*   0x8000000L  unused */
                        /*  0x10000000L  unused */
                        /*  0x20000000L  unused */
                        /*  0x40000000L  unused */
 
-/* flags for png_create_struct */
+/* Flags for png_create_struct */
 #define PNG_STRUCT_PNG   0x0001
 #define PNG_STRUCT_INFO  0x0002
 
@@ -2780,7 +2990,7 @@ extern PNG_EXPORT(void,png_save_uint_16)
 #define PNG_COST_SHIFT 3
 #define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
 
-/* flags for the png_ptr->flags rather than declaring a byte for each one */
+/* Flags for the png_ptr->flags rather than declaring a byte for each one */
 #define PNG_FLAG_ZLIB_CUSTOM_STRATEGY     0x0001
 #define PNG_FLAG_ZLIB_CUSTOM_LEVEL        0x0002
 #define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL    0x0004
@@ -2822,7 +3032,7 @@ extern PNG_EXPORT(void,png_save_uint_16)
 #define PNG_FLAG_CRC_MASK           (PNG_FLAG_CRC_ANCILLARY_MASK | \
                                      PNG_FLAG_CRC_CRITICAL_MASK)
 
-/* save typing and make code easier to understand */
+/* Save typing and make code easier to understand */
 
 #define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
    abs((int)((c1).green) - (int)((c2).green)) + \
@@ -2835,15 +3045,16 @@ extern PNG_EXPORT(void,png_save_uint_16)
     (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) )
 
 /* PNG_OUT_OF_RANGE returns true if value is outside the range
-   ideal-delta..ideal+delta.  Each argument is evaluated twice.
-   "ideal" and "delta" should be constants, normally simple
-   integers, "value" a variable. Added to libpng-1.2.6 JB */
+ * ideal-delta..ideal+delta.  Each argument is evaluated twice.
+ * "ideal" and "delta" should be constants, normally simple
+ * integers, "value" a variable. Added to libpng-1.2.6 JB
+ */
 #define PNG_OUT_OF_RANGE(value, ideal, delta) \
         ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) )
 
-/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+/* Variables declared in png.c - only it needs to define PNG_NO_EXTERN */
 #if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
-/* place to hold the signature string for a PNG file. */
+/* Place to hold the signature string for a PNG file. */
 #ifdef PNG_USE_GLOBAL_ARRAYS
    PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8];
 #else
@@ -2904,7 +3115,8 @@ PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5];
 /* Initialize png_ptr struct for reading, and allocate any other memory.
  * (old interface - DEPRECATED - use png_create_read_struct instead).
  */
-extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr))
+    PNG_DEPRECATED;
 #undef png_read_init
 #define png_read_init(png_ptr) png_read_init_3(&png_ptr, \
     PNG_LIBPNG_VER_STRING,  png_sizeof(png_struct));
@@ -2922,7 +3134,8 @@ extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr,
 /* Initialize png_ptr struct for writing, and allocate any other memory.
  * (old interface - DEPRECATED - use png_create_write_struct instead).
  */
-extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr))
+    PNG_DEPRECATED;
 #undef png_write_init
 #define png_write_init(png_ptr) png_write_init_3(&png_ptr, \
     PNG_LIBPNG_VER_STRING, png_sizeof(png_struct));
@@ -2935,102 +3148,107 @@ extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr,
     png_info_size));
 
 /* Allocate memory for an internal libpng struct */
-PNG_EXTERN png_voidp png_create_struct PNGARG((int type));
+PNG_EXTERN png_voidp png_create_struct PNGARG((int type)) PNG_PRIVATE;
 
 /* Free memory from internal libpng struct */
-PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
+PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)) PNG_PRIVATE;
 
 PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr
-  malloc_fn, png_voidp mem_ptr));
+  malloc_fn, png_voidp mem_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
-   png_free_ptr free_fn, png_voidp mem_ptr));
+   png_free_ptr free_fn, png_voidp mem_ptr)) PNG_PRIVATE;
 
 /* Free any memory that info_ptr points to and reset struct. */
 PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 
 #ifndef PNG_1_0_X
 /* Function to allocate memory for zlib. */
-PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size));
+PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items,
+   uInt size)) PNG_PRIVATE;
 
 /* Function to free memory for zlib */
-PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr));
+PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)) PNG_PRIVATE;
 
 #ifdef PNG_SIZE_T
 /* Function to convert a sizeof an item to png_sizeof item */
-   PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size));
+   PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size))
+      PNG_PRIVATE;
 #endif
 
 /* Next four functions are used internally as callbacks.  PNGAPI is required
- * but not PNG_EXPORT.  PNGAPI added at libpng version 1.2.3. */
+ * but not PNG_EXPORT.  PNGAPI added at libpng version 1.2.3.
+ */
 
 PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr,
-   png_bytep data, png_size_t length));
+   png_bytep data, png_size_t length)) PNG_PRIVATE;
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr,
-   png_bytep buffer, png_size_t length));
+   png_bytep buffer, png_size_t length)) PNG_PRIVATE;
 #endif
 
 PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr,
-   png_bytep data, png_size_t length));
+   png_bytep data, png_size_t length)) PNG_PRIVATE;
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
-#if !defined(PNG_NO_STDIO)
-PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr));
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED
+PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr))
+   PNG_PRIVATE;
 #endif
 #endif
 #else /* PNG_1_0_X */
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr,
-   png_bytep buffer, png_size_t length));
+   png_bytep buffer, png_size_t length)) PNG_PRIVATE;
 #endif
 #endif /* PNG_1_0_X */
 
 /* Reset the CRC variable */
-PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
 /* Write the "data" buffer to whatever output you are using. */
 PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data,
-   png_size_t length));
+   png_size_t length)) PNG_PRIVATE;
 
 /* Read data from whatever input you are using into the "data" buffer */
 PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data,
-   png_size_t length));
+   png_size_t length)) PNG_PRIVATE;
 
 /* Read bytes into buf, and update png_ptr->crc */
 PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf,
-   png_size_t length));
+   png_size_t length)) PNG_PRIVATE;
 
 /* Decompress data in a chunk that uses compression */
 #if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \
     defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
-PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr,
-   int comp_type, png_charp chunkdata, png_size_t chunklength,
-   png_size_t prefix_length, png_size_t *data_length));
+PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr,
+   int comp_type, png_size_t chunklength,
+   png_size_t prefix_length, png_size_t *data_length)) PNG_PRIVATE;
 #endif
 
 /* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
-PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip));
+PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)
+   PNG_PRIVATE);
 
 /* Read the CRC from the file and compare it to the libpng calculated CRC */
-PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr));
+PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
 /* Calculate the CRC over a section of data.  Note that we are only
  * passing a maximum of 64K on systems that have this as a memory limit,
  * since this is the maximum buffer size we can specify.
  */
 PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr,
-   png_size_t length));
+   png_size_t length)) PNG_PRIVATE;
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
-PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 #endif
 
-/* simple function to write the signature */
-PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr));
+/* Simple function to write the signature */
+PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
-/* write various chunks */
+/* Write various chunks */
 
 /* Write the IHDR chunk, and update the png_struct with the necessary
  * information.
@@ -3038,481 +3256,498 @@ PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr));
 PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width,
    png_uint_32 height,
    int bit_depth, int color_type, int compression_method, int filter_method,
-   int interlace_method));
+   int interlace_method)) PNG_PRIVATE;
 
 PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette,
-   png_uint_32 num_pal));
+   png_uint_32 num_pal)) PNG_PRIVATE;
 
 PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data,
-   png_size_t length));
+   png_size_t length)) PNG_PRIVATE;
 
-PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
-#if defined(PNG_WRITE_gAMA_SUPPORTED)
+#ifdef PNG_WRITE_gAMA_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma));
+PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma))
+    PNG_PRIVATE;
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point
-    file_gamma));
+PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr,
+    png_fixed_point file_gamma)) PNG_PRIVATE;
 #endif
 #endif
 
-#if defined(PNG_WRITE_sBIT_SUPPORTED)
+#ifdef PNG_WRITE_sBIT_SUPPORTED
 PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit,
-   int color_type));
+   int color_type)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_cHRM_SUPPORTED)
+#ifdef PNG_WRITE_cHRM_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr,
    double white_x, double white_y,
    double red_x, double red_y, double green_x, double green_y,
-   double blue_x, double blue_y));
+   double blue_x, double blue_y)) PNG_PRIVATE;
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
 PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
    png_fixed_point int_white_x, png_fixed_point int_white_y,
    png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
    int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
-   png_fixed_point int_blue_y));
+   png_fixed_point int_blue_y)) PNG_PRIVATE;
 #endif
 #endif
 
-#if defined(PNG_WRITE_sRGB_SUPPORTED)
+#ifdef PNG_WRITE_sRGB_SUPPORTED
 PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr,
-   int intent));
+   int intent)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_iCCP_SUPPORTED)
+#ifdef PNG_WRITE_iCCP_SUPPORTED
 PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr,
    png_charp name, int compression_type,
-   png_charp profile, int proflen));
+   png_charp profile, int proflen)) PNG_PRIVATE;
    /* Note to maintainer: profile should be png_bytep */
 #endif
 
-#if defined(PNG_WRITE_sPLT_SUPPORTED)
+#ifdef PNG_WRITE_sPLT_SUPPORTED
 PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr,
-   png_sPLT_tp palette));
+   png_sPLT_tp palette)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_tRNS_SUPPORTED)
+#ifdef PNG_WRITE_tRNS_SUPPORTED
 PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans,
-   png_color_16p values, int number, int color_type));
+   png_color_16p values, int number, int color_type)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_bKGD_SUPPORTED)
+#ifdef PNG_WRITE_bKGD_SUPPORTED
 PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr,
-   png_color_16p values, int color_type));
+   png_color_16p values, int color_type)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_hIST_SUPPORTED)
+#ifdef PNG_WRITE_hIST_SUPPORTED
 PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist,
-   int num_hist));
+   int num_hist)) PNG_PRIVATE;
 #endif
 
 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
     defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
 PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
-   png_charp key, png_charpp new_key));
+   png_charp key, png_charpp new_key)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_tEXt_SUPPORTED)
+#ifdef PNG_WRITE_tEXt_SUPPORTED
 PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key,
-   png_charp text, png_size_t text_len));
+   png_charp text, png_size_t text_len)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_zTXt_SUPPORTED)
+#ifdef PNG_WRITE_zTXt_SUPPORTED
 PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key,
-   png_charp text, png_size_t text_len, int compression));
+   png_charp text, png_size_t text_len, int compression)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_iTXt_SUPPORTED)
+#ifdef PNG_WRITE_iTXt_SUPPORTED
 PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr,
    int compression, png_charp key, png_charp lang, png_charp lang_key,
-   png_charp text));
+   png_charp text)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_TEXT_SUPPORTED)  /* Added at version 1.0.14 and 1.2.4 */
+#ifdef PNG_TEXT_SUPPORTED  /* Added at version 1.0.14 and 1.2.4 */
 PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_textp text_ptr, int num_text));
+   png_infop info_ptr, png_textp text_ptr, int num_text)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_oFFs_SUPPORTED)
+#ifdef PNG_WRITE_oFFs_SUPPORTED
 PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr,
-   png_int_32 x_offset, png_int_32 y_offset, int unit_type));
+   png_int_32 x_offset, png_int_32 y_offset, int unit_type)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_pCAL_SUPPORTED)
+#ifdef PNG_WRITE_pCAL_SUPPORTED
 PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose,
    png_int_32 X0, png_int_32 X1, int type, int nparams,
-   png_charp units, png_charpp params));
+   png_charp units, png_charpp params)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_pHYs_SUPPORTED)
+#ifdef PNG_WRITE_pHYs_SUPPORTED
 PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr,
    png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
-   int unit_type));
+   int unit_type)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_tIME_SUPPORTED)
+#ifdef PNG_WRITE_tIME_SUPPORTED
 PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr,
-   png_timep mod_time));
+   png_timep mod_time)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_sCAL_SUPPORTED)
+#ifdef PNG_WRITE_sCAL_SUPPORTED
 #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
 PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr,
-   int unit, double width, double height));
+   int unit, double width, double height)) PNG_PRIVATE;
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
 PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
-   int unit, png_charp width, png_charp height));
+   int unit, png_charp width, png_charp height)) PNG_PRIVATE;
 #endif
 #endif
 #endif
 
 /* Called when finished processing a row of data */
-PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
 /* Internal use only.   Called before first row of data */
-PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
-#if defined(PNG_READ_GAMMA_SUPPORTED)
-PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr));
+#ifdef PNG_READ_GAMMA_SUPPORTED
+PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 #endif
 
-/* combine a row of data, dealing with alpha, etc. if requested */
+/* Combine a row of data, dealing with alpha, etc. if requested */
 PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
-   int mask));
+   int mask)) PNG_PRIVATE;
 
-#if defined(PNG_READ_INTERLACING_SUPPORTED)
-/* expand an interlaced row */
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+/* Expand an interlaced row */
 /* OLD pre-1.0.9 interface:
 PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info,
-   png_bytep row, int pass, png_uint_32 transformations));
+   png_bytep row, int pass, png_uint_32 transformations)) PNG_PRIVATE;
  */
-PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 #endif
 
 /* GRR TO DO (2.0 or whenever):  simplify other internal calling interfaces */
 
-#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
-/* grab pixels out of a row for an interlaced pass */
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+/* Grab pixels out of a row for an interlaced pass */
 PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
-   png_bytep row, int pass));
+   png_bytep row, int pass)) PNG_PRIVATE;
 #endif
 
-/* unfilter a row */
+/* Unfilter a row */
 PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr,
-   png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter));
+   png_row_infop row_info, png_bytep row, png_bytep prev_row,
+   int filter)) PNG_PRIVATE;
 
 /* Choose the best filter to use and filter the row data */
 PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr,
-   png_row_infop row_info));
+   png_row_infop row_info)) PNG_PRIVATE;
 
 /* Write out the filtered row. */
 PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr,
-   png_bytep filtered_row));
-/* finish a row while reading, dealing with interlacing passes, etc. */
+   png_bytep filtered_row)) PNG_PRIVATE;
+/* Finish a row while reading, dealing with interlacing passes, etc. */
 PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr));
 
-/* initialize the row buffers, etc. */
-PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr));
-/* optional call to update the users info structure */
+/* Initialize the row buffers, etc. */
+PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+/* Optional call to update the users info structure */
 PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 
-/* these are the functions that do the transformations */
-#if defined(PNG_READ_FILLER_SUPPORTED)
+/* These are the functions that do the transformations */
+#ifdef PNG_READ_FILLER_SUPPORTED
 PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
-   png_bytep row, png_uint_32 filler, png_uint_32 flags));
+   png_bytep row, png_uint_32 filler, png_uint_32 flags)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
 PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info,
-   png_bytep row));
+   png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
 PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info,
-   png_bytep row));
+   png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
 PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info,
-   png_bytep row));
+   png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
 PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info,
-   png_bytep row));
+   png_bytep row)) PNG_PRIVATE;
 #endif
 
 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
 PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info,
-   png_bytep row, png_uint_32 flags));
+   png_bytep row, png_uint_32 flags)) PNG_PRIVATE;
 #endif
 
 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row));
+PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info,
+    png_bytep row)) PNG_PRIVATE;
 #endif
 
 #if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row));
+PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info,
+    png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
 PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop
-   row_info, png_bytep row));
+   row_info, png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
 PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info,
-   png_bytep row));
+   png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_PACK_SUPPORTED)
-PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row));
+#ifdef PNG_READ_PACK_SUPPORTED
+PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info,
+    png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_SHIFT_SUPPORTED)
+#ifdef PNG_READ_SHIFT_SUPPORTED
 PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row,
-   png_color_8p sig_bits));
+   png_color_8p sig_bits)) PNG_PRIVATE;
 #endif
 
 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row));
+PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info,
+    png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_16_TO_8_SUPPORTED)
-PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row));
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info,
+    png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
+#ifdef PNG_READ_DITHER_SUPPORTED
 PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info,
-   png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup));
+   png_bytep row, png_bytep palette_lookup,
+    png_bytep dither_lookup)) PNG_PRIVATE;
 
-#  if defined(PNG_CORRECT_PALETTE_SUPPORTED)
+#  ifdef PNG_CORRECT_PALETTE_SUPPORTED
 PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr,
-   png_colorp palette, int num_palette));
+   png_colorp palette, int num_palette)) PNG_PRIVATE;
 #  endif
 #endif
 
 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row));
+PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info,
+    png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_PACK_SUPPORTED)
+#ifdef PNG_WRITE_PACK_SUPPORTED
 PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info,
-   png_bytep row, png_uint_32 bit_depth));
+   png_bytep row, png_uint_32 bit_depth)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
 PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row,
-   png_color_8p bit_depth));
+   png_color_8p bit_depth)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+#ifdef PNG_READ_GAMMA_SUPPORTED
 PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
    png_color_16p trans_values, png_color_16p background,
    png_color_16p background_1,
    png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
    png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
-   png_uint_16pp gamma_16_to_1, int gamma_shift));
+   png_uint_16pp gamma_16_to_1, int gamma_shift)) PNG_PRIVATE;
 #else
 PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
-   png_color_16p trans_values, png_color_16p background));
+   png_color_16p trans_values, png_color_16p background)) PNG_PRIVATE;
 #endif
 #endif
 
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
 PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row,
    png_bytep gamma_table, png_uint_16pp gamma_16_table,
-   int gamma_shift));
+   int gamma_shift)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
 PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info,
-   png_bytep row, png_colorp palette, png_bytep trans, int num_trans));
+   png_bytep row, png_colorp palette, png_bytep trans,
+   int num_trans)) PNG_PRIVATE;
 PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
-   png_bytep row, png_color_16p trans_value));
+   png_bytep row, png_color_16p trans_value)) PNG_PRIVATE;
 #endif
 
 /* The following decodes the appropriate chunks, and does error correction,
  * then calls the appropriate callback for the chunk if it is valid.
  */
 
-/* decode the IHDR chunk */
+/* Decode the IHDR chunk */
 PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 
-#if defined(PNG_READ_bKGD_SUPPORTED)
+#ifdef PNG_READ_bKGD_SUPPORTED
 PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_cHRM_SUPPORTED)
+#ifdef PNG_READ_cHRM_SUPPORTED
 PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_gAMA_SUPPORTED)
+#ifdef PNG_READ_gAMA_SUPPORTED
 PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_READ_hIST_SUPPORTED
 PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_iCCP_SUPPORTED)
+#ifdef PNG_READ_iCCP_SUPPORTED
 extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length));
 #endif /* PNG_READ_iCCP_SUPPORTED */
 
-#if defined(PNG_READ_iTXt_SUPPORTED)
+#ifdef PNG_READ_iTXt_SUPPORTED
 PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_oFFs_SUPPORTED)
+#ifdef PNG_READ_oFFs_SUPPORTED
 PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#ifdef PNG_READ_pCAL_SUPPORTED
 PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_pHYs_SUPPORTED)
+#ifdef PNG_READ_pHYs_SUPPORTED
 PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_sBIT_SUPPORTED)
+#ifdef PNG_READ_sBIT_SUPPORTED
 PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#ifdef PNG_READ_sCAL_SUPPORTED
 PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_sPLT_SUPPORTED)
+#ifdef PNG_READ_sPLT_SUPPORTED
 extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif /* PNG_READ_sPLT_SUPPORTED */
 
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
 PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_tEXt_SUPPORTED)
+#ifdef PNG_READ_tEXt_SUPPORTED
 PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_tIME_SUPPORTED)
+#ifdef PNG_READ_tIME_SUPPORTED
 PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_tRNS_SUPPORTED)
+#ifdef PNG_READ_tRNS_SUPPORTED
 PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_READ_zTXt_SUPPORTED)
+#ifdef PNG_READ_zTXt_SUPPORTED
 PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
-   png_uint_32 length));
+   png_uint_32 length)) PNG_PRIVATE;
 #endif
 
 PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 length));
+   png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
 
 PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
-   png_bytep chunk_name));
+   png_bytep chunk_name)) PNG_PRIVATE;
 
-/* handle the transformations for reading and writing */
-PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr));
+/* Handle the transformations for reading and writing */
+PNG_EXTERN void png_do_read_transformations
+   PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_do_write_transformations
+   PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
-PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_init_read_transformations
+   PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
-PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
-   png_uint_32 length));
-PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr));
+   png_uint_32 length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
-   png_bytep buffer, png_size_t buffer_length));
-PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr));
+   png_bytep buffer, png_size_t buffer_length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr,
-   png_bytep buffer, png_size_t buffer_length));
-PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr));
+   png_bytep buffer, png_size_t buffer_length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 length));
+   png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
 PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
-PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row));
+   png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr,
+   png_bytep row)) PNG_PRIVATE;
 PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
-PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr));
-#if defined(PNG_READ_tEXt_SUPPORTED)
+   png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_read_push_finish_row
+   PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+#ifdef PNG_READ_tEXt_SUPPORTED
 PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 length));
+   png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
 PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 #endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
+#ifdef PNG_READ_zTXt_SUPPORTED
 PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 length));
+   png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
 PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 #endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
+#ifdef PNG_READ_iTXt_SUPPORTED
 PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr,
-   png_infop info_ptr, png_uint_32 length));
+   png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
 PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr,
-   png_infop info_ptr));
+   png_infop info_ptr)) PNG_PRIVATE;
 #endif
 
 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 
 #ifdef PNG_MNG_FEATURES_SUPPORTED
 PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info,
-   png_bytep row));
+   png_bytep row)) PNG_PRIVATE;
 PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info,
-   png_bytep row));
+   png_bytep row)) PNG_PRIVATE;
 #endif
 
-#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
-#if defined(PNG_MMX_CODE_SUPPORTED)
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+#ifdef PNG_MMX_CODE_SUPPORTED
 /* png.c */ /* PRIVATE */
-PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)) PNG_PRIVATE;
 #endif
 #endif
 
+
+/* The following six functions will be exported in libpng-1.4.0. */
 #if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
 PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr,
 png_infop info_ptr));
@@ -3529,12 +3764,43 @@ png_infop info_ptr));
 PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr,
 png_infop info_ptr));
 
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
 PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr,
 png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
 #endif /* PNG_pHYs_SUPPORTED */
 #endif  /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
 
+/* Read the chunk header (length + type name) */
+PNG_EXTERN png_uint_32 png_read_chunk_header
+   PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+/* Added at libpng version 1.2.34 */
+#ifdef PNG_cHRM_SUPPORTED
+PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr,
+   png_fixed_point int_white_x, png_fixed_point int_white_y,
+   png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+   int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+   png_fixed_point int_blue_y)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+/* Added at libpng version 1.2.34 */
+PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2,
+   unsigned long *hi_product, unsigned long *lo_product)) PNG_PRIVATE;
+#endif
+#endif
+
+/* Added at libpng version 1.2.41 */
+PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr,
+   png_uint_32 width, png_uint_32 height, int bit_depth,
+   int color_type, int interlace_type, int compression_type,
+   int filter_type)) PNG_PRIVATE;
+
+/* Added at libpng version 1.2.41 */
+PNG_EXTERN png_voidp png_calloc PNGARG((png_structp png_ptr,
+   png_uint_32 size));
+
 /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
 
 #endif /* PNG_INTERNAL */
@@ -3544,5 +3810,5 @@ png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
 #endif
 
 #endif /* PNG_VERSION_INFO_ONLY */
-/* do not put anything past this line */
+/* Do not put anything past this line */
 #endif /* PNG_H */
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngconf.h b/graf2d/asimage/src/libAfterImage/libpng/pngconf.h
index 28b08c4..042a5e9 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngconf.h
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngconf.h
@@ -1,11 +1,14 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.2.23 - November 6, 2007
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * libpng version 1.2.50 - July 10, 2012
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
  */
 
 /* Any machine specific code is near the front of this file, so if you
@@ -19,7 +22,7 @@
 
 #define PNG_1_2_X
 
-/* 
+/*
  * PNG_USER_CONFIG has to be defined on the compiler command line. This
  * includes the resource compiler for Windows DLL configurations.
  */
@@ -39,7 +42,7 @@
 
 /*
  * Added at libpng-1.2.8
- *  
+ *
  * If you create a private DLL you need to define in "pngusr.h" the followings:
  * #define PNG_USER_PRIVATEBUILD <Describes by whom and why this version of
  *        the DLL was built>
@@ -50,8 +53,8 @@
  *        number and must match your private DLL name>
  *  e.g. // private DLL "libpng13gx.dll"
  *       #define PNG_USER_DLLFNAME_POSTFIX "gx"
- * 
- * The following macros are also at your disposal if you want to complete the 
+ *
+ * The following macros are also at your disposal if you want to complete the
  * DLL VERSIONINFO structure.
  * - PNG_USER_VERSIONINFO_COMMENTS
  * - PNG_USER_VERSIONINFO_COMPANYNAME
@@ -112,8 +115,33 @@
 #  define PNG_WRITE_SUPPORTED
 #endif
 
+/* Enabled in 1.2.41. */
+#ifdef PNG_ALLOW_BENIGN_ERRORS
+#  define png_benign_error png_warning
+#  define png_chunk_benign_error png_chunk_warning
+#else
+#  ifndef PNG_BENIGN_ERRORS_SUPPORTED
+#    define png_benign_error png_error
+#    define png_chunk_benign_error png_chunk_error
+#  endif
+#endif
+
+/* Added in libpng-1.2.41 */
+#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED)
+#  define PNG_WARNINGS_SUPPORTED
+#endif
+
+#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED)
+#  define PNG_ERROR_TEXT_SUPPORTED
+#endif
+
+#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED)
+#  define PNG_CHECK_cHRM_SUPPORTED
+#endif
+
 /* Enabled by default in 1.2.0.  You can disable this if you don't need to
-   support PNGs that are embedded in MNG datastreams */
+ * support PNGs that are embedded in MNG datastreams
+ */
 #if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES)
 #  ifndef PNG_MNG_FEATURES_SUPPORTED
 #    define PNG_MNG_FEATURES_SUPPORTED
@@ -147,9 +175,9 @@
  * 'Cygwin' defines/defaults:
  *   PNG_BUILD_DLL -- (ignored) building the dll
  *   (no define)   -- (ignored) building an application, linking to the dll
- *   PNG_STATIC    -- (ignored) building the static lib, or building an 
+ *   PNG_STATIC    -- (ignored) building the static lib, or building an
  *                    application that links to the static lib.
- *   ALL_STATIC    -- (ignored) building various static libs, or building an 
+ *   ALL_STATIC    -- (ignored) building various static libs, or building an
  *                    application that links to the static libs.
  * Thus,
  * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and
@@ -162,57 +190,57 @@
  *   PNG_BUILD_DLL
  *   PNG_STATIC
  *   (nothing) == PNG_USE_DLL
- * 
+ *
  * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent
- *   of auto-import in binutils, we no longer need to worry about 
+ *   of auto-import in binutils, we no longer need to worry about
  *   __declspec(dllexport) / __declspec(dllimport) and friends.  Therefore,
  *   we don't need to worry about PNG_STATIC or ALL_STATIC when it comes
- *   to __declspec() stuff.  However, we DO need to worry about 
+ *   to __declspec() stuff.  However, we DO need to worry about
  *   PNG_BUILD_DLL and PNG_STATIC because those change some defaults
  *   such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed.
  */
-#if defined(__CYGWIN__)
-#  if defined(ALL_STATIC)
-#    if defined(PNG_BUILD_DLL)
+#ifdef __CYGWIN__
+#  ifdef ALL_STATIC
+#    ifdef PNG_BUILD_DLL
 #      undef PNG_BUILD_DLL
 #    endif
-#    if defined(PNG_USE_DLL)
+#    ifdef PNG_USE_DLL
 #      undef PNG_USE_DLL
 #    endif
-#    if defined(PNG_DLL)
+#    ifdef PNG_DLL
 #      undef PNG_DLL
 #    endif
-#    if !defined(PNG_STATIC)
+#    ifndef PNG_STATIC
 #      define PNG_STATIC
 #    endif
 #  else
-#    if defined (PNG_BUILD_DLL)
-#      if defined(PNG_STATIC)
+#    ifdef PNG_BUILD_DLL
+#      ifdef PNG_STATIC
 #        undef PNG_STATIC
 #      endif
-#      if defined(PNG_USE_DLL)
+#      ifdef PNG_USE_DLL
 #        undef PNG_USE_DLL
 #      endif
-#      if !defined(PNG_DLL)
+#      ifndef PNG_DLL
 #        define PNG_DLL
 #      endif
 #    else
-#      if defined(PNG_STATIC)
-#        if defined(PNG_USE_DLL)
+#      ifdef PNG_STATIC
+#        ifdef PNG_USE_DLL
 #          undef PNG_USE_DLL
 #        endif
-#        if defined(PNG_DLL)
+#        ifdef PNG_DLL
 #          undef PNG_DLL
 #        endif
 #      else
-#        if !defined(PNG_USE_DLL)
+#        ifndef PNG_USE_DLL
 #          define PNG_USE_DLL
 #        endif
-#        if !defined(PNG_DLL)
+#        ifndef PNG_DLL
 #          define PNG_DLL
 #        endif
-#      endif  
-#    endif  
+#      endif
+#    endif
 #  endif
 #endif
 
@@ -229,10 +257,16 @@
  * #define PNG_NO_STDIO
  */
 
-#if defined(_WIN32_WCE)
+#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED)
+#  define PNG_STDIO_SUPPORTED
+#endif
+
+#ifdef _WIN32_WCE
 #  include <windows.h>
    /* Console I/O functions are not supported on WindowsCE */
 #  define PNG_NO_CONSOLE_IO
+   /* abort() may not be supported on some/all Windows CE platforms */
+#  define PNG_ABORT() exit(-1)
 #  ifdef PNG_DEBUG
 #    undef PNG_DEBUG
 #  endif
@@ -256,12 +290,16 @@
 #      endif
 #    endif
 #  else
-#    if !defined(_WIN32_WCE)
+#    ifndef _WIN32_WCE
 /* "stdio.h" functions are not supported on WindowsCE */
 #      include <stdio.h>
 #    endif
 #  endif
 
+#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED)
+#  define PNG_CONSOLE_IO_SUPPORTED
+#endif
+
 /* This macro protects us against machines that don't have function
  * prototypes (ie K&R style headers).  If your compiler does not handle
  * function prototypes, define this macro and use the included ansi2knr.
@@ -312,28 +350,38 @@
 #ifdef PNG_SETJMP_SUPPORTED
 /* This is an attempt to force a single setjmp behaviour on Linux.  If
  * the X config stuff didn't define _BSD_SOURCE we wouldn't need this.
+ *
+ * You can bypass this test if you know that your application uses exactly
+ * the same setjmp.h that was included when libpng was built.  Only define
+ * PNG_SKIP_SETJMP_CHECK while building your application, prior to the
+ * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK
+ * while building a separate libpng library for general use.
  */
 
-#  ifdef __linux__
-#    ifdef _BSD_SOURCE
-#      define PNG_SAVE_BSD_SOURCE
-#      undef _BSD_SOURCE
-#    endif
-#    ifdef _SETJMP_H
-     /* If you encounter a compiler error here, see the explanation
-      * near the end of INSTALL.
-      */
-         __png.h__ already includes setjmp.h;
-         __dont__ include it again.;
-#    endif
-#  endif /* __linux__ */
+#  ifndef PNG_SKIP_SETJMP_CHECK
+#    ifdef __linux__
+#      ifdef _BSD_SOURCE
+#        define PNG_SAVE_BSD_SOURCE
+#        undef _BSD_SOURCE
+#      endif
+#      ifdef _SETJMP_H
+       /* If you encounter a compiler error here, see the explanation
+        * near the end of INSTALL.
+        */
+           __pngconf.h__ in libpng already includes setjmp.h;
+           __dont__ include it again.;
+#      endif
+#    endif /* __linux__ */
+#  endif /* PNG_SKIP_SETJMP_CHECK */
 
    /* include setjmp.h for error handling */
 #  include <setjmp.h>
 
 #  ifdef __linux__
 #    ifdef PNG_SAVE_BSD_SOURCE
-#      define _BSD_SOURCE
+#      ifndef _BSD_SOURCE
+#        define _BSD_SOURCE
+#      endif
 #      undef PNG_SAVE_BSD_SOURCE
 #    endif
 #  endif /* __linux__ */
@@ -363,8 +411,8 @@
  * them inside an appropriate ifdef/endif pair for portability.
  */
 
-#if defined(PNG_FLOATING_POINT_SUPPORTED)
-#  if defined(MACOS)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+#  ifdef MACOS
      /* We need to check that <math.h> hasn't already been included earlier
       * as it seems it doesn't agree with <fp.h>, yet we should really use
       * <fp.h> if possible.
@@ -475,7 +523,7 @@
  * iTXt support was added.  iTXt support was turned off by default through
  * libpng-1.2.x, to support old apps that malloc the png_text structure
  * instead of calling png_set_text() and letting libpng malloc it.  It
- * was turned on by default in libpng-1.3.0.
+ * will be turned on by default in libpng-1.4.0.
  */
 
 #if defined(PNG_1_0_X) || defined (PNG_1_2_X)
@@ -509,6 +557,7 @@
 #  define PNG_NO_FREE_ME
 #  define PNG_NO_READ_UNKNOWN_CHUNKS
 #  define PNG_NO_WRITE_UNKNOWN_CHUNKS
+#  define PNG_NO_HANDLE_AS_UNKNOWN
 #  define PNG_NO_READ_USER_CHUNKS
 #  define PNG_NO_READ_iCCP
 #  define PNG_NO_WRITE_iCCP
@@ -538,7 +587,7 @@
 #  define PNG_FREE_ME_SUPPORTED
 #endif
 
-#if defined(PNG_READ_SUPPORTED)
+#ifdef PNG_READ_SUPPORTED
 
 #if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \
       !defined(PNG_NO_READ_TRANSFORMS)
@@ -602,11 +651,20 @@
 #  endif
 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
 
+/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */
 #if !defined(PNG_NO_PROGRESSIVE_READ) && \
- !defined(PNG_PROGRESSIVE_READ_SUPPORTED) /* if you don't do progressive   */
-#  define PNG_PROGRESSIVE_READ_SUPPORTED  /* reading.  This is not talking */
-#endif                            /* about interlacing capability!  You'll */
-           /* still have interlacing unless you change the following line: */
+ !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED)  /* if you don't do progressive */
+#  define PNG_PROGRESSIVE_READ_SUPPORTED     /* reading.  This is not talking */
+#endif                               /* about interlacing capability!  You'll */
+            /* still have interlacing unless you change the following define: */
+#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */
+
+/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */
+#if !defined(PNG_NO_SEQUENTIAL_READ) && \
+    !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \
+    !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED)
+#  define PNG_SEQUENTIAL_READ_SUPPORTED
+#endif
 
 #define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */
 
@@ -626,7 +684,7 @@
 
 #endif /* PNG_READ_SUPPORTED */
 
-#if defined(PNG_WRITE_SUPPORTED)
+#ifdef PNG_WRITE_SUPPORTED
 
 # if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \
     !defined(PNG_NO_WRITE_TRANSFORMS)
@@ -658,9 +716,11 @@
 #  ifndef PNG_NO_WRITE_SWAP_ALPHA
 #    define PNG_WRITE_SWAP_ALPHA_SUPPORTED
 #  endif
+#ifndef PNG_1_0_X
 #  ifndef PNG_NO_WRITE_INVERT_ALPHA
 #    define PNG_WRITE_INVERT_ALPHA_SUPPORTED
 #  endif
+#endif
 #  ifndef PNG_NO_WRITE_USER_TRANSFORM
 #    define PNG_WRITE_USER_TRANSFORM_SUPPORTED
 #  endif
@@ -729,7 +789,7 @@
 #  define PNG_EASY_ACCESS_SUPPORTED
 #endif
 
-/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 
+/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0
  * and removed from version 1.2.20.  The following will be removed
  * from libpng-1.4.0
 */
@@ -752,7 +812,7 @@
 #    endif
 #  endif
 
-#  if defined(__APPLE__)
+#  ifdef __APPLE__
 #    if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
 #      define PNG_NO_MMX_CODE
 #    endif
@@ -771,21 +831,29 @@
 #endif
 /* end of obsolete code to be removed from libpng-1.4.0 */
 
-#if !defined(PNG_1_0_X)
+/* Added at libpng-1.2.0 */
+#ifndef PNG_1_0_X
 #if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED)
 #  define PNG_USER_MEM_SUPPORTED
 #endif
 #endif /* PNG_1_0_X */
 
 /* Added at libpng-1.2.6 */
-#if !defined(PNG_1_0_X)
-#ifndef PNG_SET_USER_LIMITS_SUPPORTED
-#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED)
-#  define PNG_SET_USER_LIMITS_SUPPORTED
-#endif
-#endif
+#ifndef PNG_1_0_X
+#  ifndef PNG_SET_USER_LIMITS_SUPPORTED
+#    ifndef PNG_NO_SET_USER_LIMITS
+#      define PNG_SET_USER_LIMITS_SUPPORTED
+#    endif
+#  endif
 #endif /* PNG_1_0_X */
 
+/* Added at libpng-1.0.53 and 1.2.43 */
+#ifndef PNG_USER_LIMITS_SUPPORTED
+#  ifndef PNG_NO_USER_LIMITS
+#    define PNG_USER_LIMITS_SUPPORTED
+#  endif
+#endif
+
 /* Added at libpng-1.0.16 and 1.2.6.  To accept all valid PNGS no matter
  * how large, set these limits to 0x7fffffffL
  */
@@ -796,6 +864,33 @@
 #  define PNG_USER_HEIGHT_MAX 1000000L
 #endif
 
+/* Added at libpng-1.2.43.  To accept all valid PNGs no matter
+ * how large, set these two limits to 0.
+ */
+#ifndef PNG_USER_CHUNK_CACHE_MAX
+#  define PNG_USER_CHUNK_CACHE_MAX 0
+#endif
+
+/* Added at libpng-1.2.43 */
+#ifndef PNG_USER_CHUNK_MALLOC_MAX
+#  define PNG_USER_CHUNK_MALLOC_MAX 0
+#endif
+
+#ifndef PNG_LITERAL_SHARP
+#  define PNG_LITERAL_SHARP 0x23
+#endif
+#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
+#  define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
+#endif
+#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET
+#  define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d
+#endif
+
+/* Added at libpng-1.2.34 */
+#ifndef PNG_STRING_NEWLINE
+#define PNG_STRING_NEWLINE "\n"
+#endif
+
 /* These are currently experimental features, define them if you want */
 
 /* very little testing */
@@ -820,6 +915,11 @@
 #define PNG_NO_POINTER_INDEXING
 */
 
+#if !defined(PNG_NO_POINTER_INDEXING) && \
+    !defined(PNG_POINTER_INDEXING_SUPPORTED)
+#  define PNG_POINTER_INDEXING_SUPPORTED
+#endif
+
 /* These functions are turned off by default, as they will be phased out. */
 /*
 #define  PNG_USELESS_TESTS_SUPPORTED
@@ -923,14 +1023,22 @@
 #  define PNG_READ_zTXt_SUPPORTED
 #  define PNG_zTXt_SUPPORTED
 #endif
+#ifndef PNG_NO_READ_OPT_PLTE
+#  define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */
+#endif                      /* optional PLTE chunk in RGB and RGBA images */
+#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \
+    defined(PNG_READ_zTXt_SUPPORTED)
+#  define PNG_READ_TEXT_SUPPORTED
+#  define PNG_TEXT_SUPPORTED
+#endif
+
+#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
+
 #ifndef PNG_NO_READ_UNKNOWN_CHUNKS
 #  define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
 #  ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
 #    define PNG_UNKNOWN_CHUNKS_SUPPORTED
 #  endif
-#  ifndef PNG_NO_HANDLE_AS_UNKNOWN
-#    define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#  endif
 #endif
 #if !defined(PNG_NO_READ_USER_CHUNKS) && \
      defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
@@ -943,17 +1051,14 @@
 #    undef PNG_NO_HANDLE_AS_UNKNOWN
 #  endif
 #endif
-#ifndef PNG_NO_READ_OPT_PLTE
-#  define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */
-#endif                      /* optional PLTE chunk in RGB and RGBA images */
-#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \
-    defined(PNG_READ_zTXt_SUPPORTED)
-#  define PNG_READ_TEXT_SUPPORTED
-#  define PNG_TEXT_SUPPORTED
-#endif
 
-#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
+#ifndef PNG_NO_HANDLE_AS_UNKNOWN
+#  ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#    define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#  endif
+#endif
 
+#ifdef PNG_WRITE_SUPPORTED
 #ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
 
 #ifdef PNG_NO_WRITE_TEXT
@@ -1065,17 +1170,6 @@
 #    define PNG_zTXt_SUPPORTED
 #  endif
 #endif
-#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS
-#  define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-#  ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
-#    define PNG_UNKNOWN_CHUNKS_SUPPORTED
-#  endif
-#  ifndef PNG_NO_HANDLE_AS_UNKNOWN
-#     ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#       define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#     endif
-#  endif
-#endif
 #if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \
     defined(PNG_WRITE_zTXt_SUPPORTED)
 #  define PNG_WRITE_TEXT_SUPPORTED
@@ -1084,8 +1178,37 @@
 #  endif
 #endif
 
+#ifdef PNG_WRITE_tIME_SUPPORTED
+#  ifndef PNG_NO_CONVERT_tIME
+#    ifndef _WIN32_WCE
+/*   The "tm" structure is not supported on WindowsCE */
+#      ifndef PNG_CONVERT_tIME_SUPPORTED
+#        define PNG_CONVERT_tIME_SUPPORTED
+#      endif
+#   endif
+#  endif
+#endif
+
 #endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */
 
+#if !defined(PNG_NO_WRITE_FILTER) && !defined(PNG_WRITE_FILTER_SUPPORTED)
+#  define PNG_WRITE_FILTER_SUPPORTED
+#endif
+
+#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS
+#  define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+#  ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#    define PNG_UNKNOWN_CHUNKS_SUPPORTED
+#  endif
+#endif
+
+#ifndef PNG_NO_HANDLE_AS_UNKNOWN
+#  ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#    define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#  endif
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
+
 /* Turn this off to disable png_read_png() and
  * png_write_png() and leave the row_pointers member
  * out of the info structure.
@@ -1094,12 +1217,10 @@
 #  define PNG_INFO_IMAGE_SUPPORTED
 #endif
 
-/* need the time information for reading tIME chunks */
-#if defined(PNG_tIME_SUPPORTED)
-#  if !defined(_WIN32_WCE)
+/* Need the time information for converting tIME chunks */
+#ifdef PNG_CONVERT_tIME_SUPPORTED
      /* "time.h" functions are not supported on WindowsCE */
 #    include <time.h>
-#  endif
 #endif
 
 /* Some typedefs to get us started.  These should be safe on most of the
@@ -1121,10 +1242,10 @@ typedef unsigned char png_byte;
    change (I'm not sure if you will or not, so I thought I'd be safe) */
 #ifdef PNG_SIZE_T
    typedef PNG_SIZE_T png_size_t;
-#  define png_sizeof(x) png_convert_size(sizeof (x))
+#  define png_sizeof(x) png_convert_size(sizeof(x))
 #else
    typedef size_t png_size_t;
-#  define png_sizeof(x) sizeof (x)
+#  define png_sizeof(x) sizeof(x)
 #endif
 
 /* The following is needed for medium model support.  It cannot be in the
@@ -1168,8 +1289,8 @@ typedef unsigned char png_byte;
  */
 
 /* MSC Medium model */
-#if defined(FAR)
-#  if defined(M_I86MM)
+#ifdef FAR
+#  ifdef M_I86MM
 #    define USE_FAR_KEYWORD
 #    define FARDATA FAR
 #    include <dos.h>
@@ -1202,7 +1323,7 @@ typedef char            FAR * png_charp;
 typedef png_fixed_point FAR * png_fixed_point_p;
 
 #ifndef PNG_NO_STDIO
-#if defined(_WIN32_WCE)
+#ifdef _WIN32_WCE
 typedef HANDLE                png_FILE_p;
 #else
 typedef FILE                * png_FILE_p;
@@ -1231,7 +1352,7 @@ typedef char            FAR * FAR * FAR * png_charppp;
 
 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
 /* SPC -  Is this stuff deprecated? */
-/* It'll be removed as of libpng-1.3.0 - GR-P */
+/* It'll be removed as of libpng-1.4.0 - GR-P */
 /* libpng typedefs for types in zlib. If zlib changes
  * or another compression library is used, then change these.
  * Eliminates need to change all the source files.
@@ -1266,17 +1387,17 @@ typedef z_stream FAR *  png_zstreamp;
  * When building a static lib, default to no GLOBAL ARRAYS, but allow
  * command-line override
  */
-#if defined(__CYGWIN__)
-#  if !defined(PNG_STATIC)
-#    if defined(PNG_USE_GLOBAL_ARRAYS)
+#ifdef __CYGWIN__
+#  ifndef PNG_STATIC
+#    ifdef PNG_USE_GLOBAL_ARRAYS
 #      undef PNG_USE_GLOBAL_ARRAYS
 #    endif
-#    if !defined(PNG_USE_LOCAL_ARRAYS)
+#    ifndef PNG_USE_LOCAL_ARRAYS
 #      define PNG_USE_LOCAL_ARRAYS
 #    endif
 #  else
 #    if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS)
-#      if defined(PNG_USE_GLOBAL_ARRAYS)
+#      ifdef PNG_USE_GLOBAL_ARRAYS
 #        undef PNG_USE_GLOBAL_ARRAYS
 #      endif
 #    endif
@@ -1299,12 +1420,12 @@ typedef z_stream FAR *  png_zstreamp;
 #  endif
 #endif
 
-#if defined(__CYGWIN__)
+#ifdef __CYGWIN__
 #  undef PNGAPI
 #  define PNGAPI __cdecl
 #  undef PNG_IMPEXP
 #  define PNG_IMPEXP
-#endif  
+#endif
 
 /* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall",
  * you may get warnings regarding the linkage of png_zalloc and png_zfree.
@@ -1340,7 +1461,7 @@ typedef z_stream FAR *  png_zstreamp;
 #     define PNG_IMPEXP
 #  endif
 
-#  if !defined(PNG_IMPEXP)
+#  ifndef PNG_IMPEXP
 
 #     define PNG_EXPORT_TYPE1(type,symbol)  PNG_IMPEXP type PNGAPI symbol
 #     define PNG_EXPORT_TYPE2(type,symbol)  type PNG_IMPEXP PNGAPI symbol
@@ -1351,7 +1472,7 @@ typedef z_stream FAR *  png_zstreamp;
 #           define PNG_EXPORT PNG_EXPORT_TYPE1
 #        else
 #           define PNG_EXPORT PNG_EXPORT_TYPE2
-#           if defined(PNG_BUILD_DLL)
+#           ifdef PNG_BUILD_DLL
 #              define PNG_IMPEXP __export
 #           else
 #              define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in
@@ -1361,8 +1482,8 @@ typedef z_stream FAR *  png_zstreamp;
 #        endif
 #     endif
 
-#     if !defined(PNG_IMPEXP)
-#        if defined(PNG_BUILD_DLL)
+#     ifndef PNG_IMPEXP
+#        ifdef PNG_BUILD_DLL
 #           define PNG_IMPEXP __declspec(dllexport)
 #        else
 #           define PNG_IMPEXP __declspec(dllimport)
@@ -1408,6 +1529,70 @@ typedef z_stream FAR *  png_zstreamp;
 #  endif
 #endif
 
+#ifdef PNG_PEDANTIC_WARNINGS
+#  ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
+#    define PNG_PEDANTIC_WARNINGS_SUPPORTED
+#  endif
+#endif
+
+#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
+/* Support for compiler specific function attributes.  These are used
+ * so that where compiler support is available incorrect use of API
+ * functions in png.h will generate compiler warnings.  Added at libpng
+ * version 1.2.41.
+ */
+#  ifdef __GNUC__
+#    ifndef PNG_USE_RESULT
+#      define PNG_USE_RESULT __attribute__((__warn_unused_result__))
+#    endif
+#    ifndef PNG_NORETURN
+#      define PNG_NORETURN   __attribute__((__noreturn__))
+#    endif
+#    ifndef PNG_ALLOCATED
+#      define PNG_ALLOCATED  __attribute__((__malloc__))
+#    endif
+
+    /* This specifically protects structure members that should only be
+     * accessed from within the library, therefore should be empty during
+     * a library build.
+     */
+#    ifndef PNG_DEPRECATED
+#      define PNG_DEPRECATED __attribute__((__deprecated__))
+#    endif
+#    ifndef PNG_DEPSTRUCT
+#      define PNG_DEPSTRUCT  __attribute__((__deprecated__))
+#    endif
+#    ifndef PNG_PRIVATE
+#      if 0 /* Doesn't work so we use deprecated instead*/
+#        define PNG_PRIVATE \
+          __attribute__((warning("This function is not exported by libpng.")))
+#      else
+#        define PNG_PRIVATE \
+          __attribute__((__deprecated__))
+#      endif
+#    endif /* PNG_PRIVATE */
+#  endif /* __GNUC__ */
+#endif /* PNG_PEDANTIC_WARNINGS */
+
+#ifndef PNG_DEPRECATED
+#  define PNG_DEPRECATED  /* Use of this function is deprecated */
+#endif
+#ifndef PNG_USE_RESULT
+#  define PNG_USE_RESULT  /* The result of this function must be checked */
+#endif
+#ifndef PNG_NORETURN
+#  define PNG_NORETURN    /* This function does not return */
+#endif
+#ifndef PNG_ALLOCATED
+#  define PNG_ALLOCATED   /* The result of the function is new memory */
+#endif
+#ifndef PNG_DEPSTRUCT
+#  define PNG_DEPSTRUCT   /* Access to this struct member is deprecated */
+#endif
+#ifndef PNG_PRIVATE
+#  define PNG_PRIVATE     /* This is a private libpng function */
+#endif
+
 /* User may want to use these so they are not in PNG_INTERNAL. Any library
  * functions that are passed far data must be model independent.
  */
@@ -1423,8 +1608,8 @@ typedef z_stream FAR *  png_zstreamp;
    (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED)
 #endif
 
-#if defined(USE_FAR_KEYWORD)  /* memory model independent fns */
-/* use this to make far-to-near assignments */
+#ifdef USE_FAR_KEYWORD  /* memory model independent fns */
+/* Use this to make far-to-near assignments */
 #  define CHECK   1
 #  define NOCHECK 0
 #  define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
@@ -1434,7 +1619,7 @@ typedef z_stream FAR *  png_zstreamp;
 #  define png_memcmp  _fmemcmp    /* SJT: added */
 #  define png_memcpy  _fmemcpy
 #  define png_memset  _fmemset
-#else /* use the usual functions */
+#else /* Use the usual functions */
 #  define CVT_PTR(ptr)         (ptr)
 #  define CVT_PTR_NOCHECK(ptr) (ptr)
 #  ifndef PNG_NO_SNPRINTF
@@ -1452,7 +1637,8 @@ typedef z_stream FAR *  png_zstreamp;
       * sprintf instead of snprintf exposes your application to accidental
       * or malevolent buffer overflows.  If you don't have snprintf()
       * as a general rule you should provide one (you can get one from
-      * Portable OpenSSH). */
+      * Portable OpenSSH).
+      */
 #    define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1)
 #    define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2)
 #    define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngerror.c b/graf2d/asimage/src/libAfterImage/libpng/pngerror.c
index 9f6b90d..025d52e 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngerror.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngerror.c
@@ -1,12 +1,15 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Last changed in libpng 1.2.22 [November 6, 2007]
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * This file provides a location for all error handling.  Users who
  * need special error handling are expected to write replacement functions
  * and use png_set_error_fn() to use those functions.  See the instructions
@@ -14,24 +17,25 @@
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+
 static void /* PRIVATE */
 png_default_error PNGARG((png_structp png_ptr,
-  png_const_charp error_message));
-#ifndef PNG_NO_WARNINGS
+  png_const_charp error_message)) PNG_NORETURN;
+#ifdef PNG_WARNINGS_SUPPORTED
 static void /* PRIVATE */
 png_default_warning PNGARG((png_structp png_ptr,
   png_const_charp warning_message));
-#endif /* PNG_NO_WARNINGS */
+#endif /* PNG_WARNINGS_SUPPORTED */
 
 /* This function is called whenever there is a fatal error.  This function
  * should not be changed.  If there is a need to handle errors differently,
  * you should supply a replacement error function and use png_set_error_fn()
  * to replace the error function at run-time.
  */
-#ifndef PNG_NO_ERROR_TEXT
+#ifdef PNG_ERROR_TEXT_SUPPORTED
 void PNGAPI
 png_error(png_structp png_ptr, png_const_charp error_message)
 {
@@ -42,30 +46,31 @@ png_error(png_structp png_ptr, png_const_charp error_message)
      if (png_ptr->flags&
        (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
      {
-       if (*error_message == '#')
+       if (*error_message == PNG_LITERAL_SHARP)
        {
+           /* Strip "#nnnn " from beginning of error message. */
            int offset;
-           for (offset=1; offset<15; offset++)
-              if (*(error_message+offset) == ' ')
+           for (offset = 1; offset<15; offset++)
+              if (error_message[offset] == ' ')
                   break;
            if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
            {
               int i;
-              for (i=0; i<offset-1; i++)
-                 msg[i]=error_message[i+1];
-              msg[i]='\0';
-              error_message=msg;
+              for (i = 0; i < offset - 1; i++)
+                 msg[i] = error_message[i + 1];
+              msg[i - 1] = '\0';
+              error_message = msg;
            }
            else
-              error_message+=offset;
+              error_message += offset;
        }
        else
        {
            if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
            {
-              msg[0]='0';
-              msg[1]='\0';
-              error_message=msg;
+              msg[0] = '0';
+              msg[1] = '\0';
+              error_message = msg;
            }
        }
      }
@@ -82,16 +87,21 @@ png_error(png_structp png_ptr, png_const_charp error_message)
 void PNGAPI
 png_err(png_structp png_ptr)
 {
+   /* Prior to 1.2.45 the error_fn received a NULL pointer, expressed
+    * erroneously as '\0', instead of the empty string "".  This was
+    * apparently an error, introduced in libpng-1.2.20, and png_default_error
+    * will crash in this case.
+    */
    if (png_ptr != NULL && png_ptr->error_fn != NULL)
-      (*(png_ptr->error_fn))(png_ptr, '\0');
+      (*(png_ptr->error_fn))(png_ptr, "");
 
    /* If the custom handler doesn't exist, or if it returns,
       use the default handler, which will not return. */
-   png_default_error(png_ptr, '\0');
+   png_default_error(png_ptr, "");
 }
-#endif /* PNG_NO_ERROR_TEXT */
+#endif /* PNG_ERROR_TEXT_SUPPORTED */
 
-#ifndef PNG_NO_WARNINGS
+#ifdef PNG_WARNINGS_SUPPORTED
 /* This function is called whenever there is a non-fatal error.  This function
  * should not be changed.  If there is a need to handle warnings differently,
  * you should supply a replacement warning function and use
@@ -108,21 +118,31 @@ png_warning(png_structp png_ptr, png_const_charp warning_message)
      (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
 #endif
      {
-       if (*warning_message == '#')
+       if (*warning_message == PNG_LITERAL_SHARP)
        {
-           for (offset=1; offset<15; offset++)
-              if (*(warning_message+offset) == ' ')
+           for (offset = 1; offset < 15; offset++)
+              if (warning_message[offset] == ' ')
                   break;
        }
      }
-     if (png_ptr != NULL && png_ptr->warning_fn != NULL)
-        (*(png_ptr->warning_fn))(png_ptr, warning_message+offset);
    }
+   if (png_ptr != NULL && png_ptr->warning_fn != NULL)
+      (*(png_ptr->warning_fn))(png_ptr, warning_message + offset);
    else
-      png_default_warning(png_ptr, warning_message+offset);
+      png_default_warning(png_ptr, warning_message + offset);
 }
-#endif /* PNG_NO_WARNINGS */
+#endif /* PNG_WARNINGS_SUPPORTED */
 
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+void PNGAPI
+png_benign_error(png_structp png_ptr, png_const_charp error_message)
+{
+  if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+    png_warning(png_ptr, error_message);
+  else
+    png_error(png_ptr, error_message);
+}
+#endif
 
 /* These utilities are used internally to build an error message that relates
  * to the current chunk.  The chunk name comes from png_ptr->chunk_name,
@@ -137,8 +157,7 @@ static PNG_CONST char png_digit[16] = {
 };
 
 #define PNG_MAX_ERROR_TEXT 64
-
-#if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT)
+#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
 static void /* PRIVATE */
 png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
    error_message)
@@ -150,10 +169,10 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
       int c = png_ptr->chunk_name[iin++];
       if (isnonalpha(c))
       {
-         buffer[iout++] = '[';
+         buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
          buffer[iout++] = png_digit[(c & 0xf0) >> 4];
          buffer[iout++] = png_digit[c & 0x0f];
-         buffer[iout++] = ']';
+         buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
       }
       else
       {
@@ -167,8 +186,13 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
    {
       buffer[iout++] = ':';
       buffer[iout++] = ' ';
-      png_memcpy(buffer+iout, error_message, PNG_MAX_ERROR_TEXT);
-      buffer[iout+PNG_MAX_ERROR_TEXT-1] = '\0';
+
+      iin = 0;
+      while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
+         buffer[iout++] = error_message[iin++];
+
+      /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
+      buffer[iout] = '\0';
    }
 }
 
@@ -186,9 +210,9 @@ png_chunk_error(png_structp png_ptr, png_const_charp error_message)
    }
 }
 #endif /* PNG_READ_SUPPORTED */
-#endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */
+#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */
 
-#ifndef PNG_NO_WARNINGS
+#ifdef PNG_WARNINGS_SUPPORTED
 void PNGAPI
 png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
 {
@@ -201,8 +225,20 @@ png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
      png_warning(png_ptr, msg);
    }
 }
-#endif /* PNG_NO_WARNINGS */
+#endif /* PNG_WARNINGS_SUPPORTED */
 
+#ifdef PNG_READ_SUPPORTED
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+void PNGAPI
+png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message)
+{
+  if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+    png_chunk_warning(png_ptr, error_message);
+  else
+    png_chunk_error(png_ptr, error_message);
+}
+#endif
+#endif /* PNG_READ_SUPPORTED */
 
 /* This is the default error handling function.  Note that replacements for
  * this function MUST NOT RETURN, or the program will likely crash.  This
@@ -212,30 +248,39 @@ png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
 static void /* PRIVATE */
 png_default_error(png_structp png_ptr, png_const_charp error_message)
 {
-#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_CONSOLE_IO_SUPPORTED
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   if (*error_message == '#')
+   if (*error_message == PNG_LITERAL_SHARP)
    {
+     /* Strip "#nnnn " from beginning of error message. */
      int offset;
      char error_number[16];
-     for (offset=0; offset<15; offset++)
+     for (offset = 0; offset<15; offset++)
      {
-         error_number[offset] = *(error_message+offset+1);
-         if (*(error_message+offset) == ' ')
+         error_number[offset] = error_message[offset + 1];
+         if (error_message[offset] == ' ')
              break;
      }
-     if((offset > 1) && (offset < 15))
+     if ((offset > 1) && (offset < 15))
      {
-       error_number[offset-1]='\0';
-       fprintf(stderr, "libpng error no. %s: %s\n", error_number,
-          error_message+offset);
+       error_number[offset - 1] = '\0';
+       fprintf(stderr, "libpng error no. %s: %s",
+          error_number, error_message + offset + 1);
+       fprintf(stderr, PNG_STRING_NEWLINE);
      }
      else
-       fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset);
+     {
+       fprintf(stderr, "libpng error: %s, offset=%d",
+          error_message, offset);
+       fprintf(stderr, PNG_STRING_NEWLINE);
+     }
    }
    else
 #endif
-   fprintf(stderr, "libpng error: %s\n", error_message);
+   {
+      fprintf(stderr, "libpng error: %s", error_message);
+      fprintf(stderr, PNG_STRING_NEWLINE);
+   }
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
@@ -245,21 +290,21 @@ png_default_error(png_structp png_ptr, png_const_charp error_message)
    {
       jmp_buf jmpbuf;
       png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf));
-      longjmp(jmpbuf, 1);
+     longjmp(jmpbuf,1);
    }
 #  else
    longjmp(png_ptr->jmpbuf, 1);
 #  endif
    }
-#else
-   PNG_ABORT();
 #endif
-#ifdef PNG_NO_CONSOLE_IO
-   error_message = error_message; /* make compiler happy */
+   /* Here if not setjmp support or if png_ptr is null. */
+   PNG_ABORT();
+#ifndef PNG_CONSOLE_IO_SUPPORTED
+   error_message = error_message; /* Make compiler happy */
 #endif
 }
 
-#ifndef PNG_NO_WARNINGS
+#ifdef PNG_WARNINGS_SUPPORTED
 /* This function is called when there is a warning, but the library thinks
  * it can continue anyway.  Replacement functions don't have to do anything
  * here if you don't want them to.  In the default configuration, png_ptr is
@@ -268,36 +313,44 @@ png_default_error(png_structp png_ptr, png_const_charp error_message)
 static void /* PRIVATE */
 png_default_warning(png_structp png_ptr, png_const_charp warning_message)
 {
-#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_CONSOLE_IO_SUPPORTED
 #  ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   if (*warning_message == '#')
+   if (*warning_message == PNG_LITERAL_SHARP)
    {
      int offset;
      char warning_number[16];
-     for (offset=0; offset<15; offset++)
+     for (offset = 0; offset < 15; offset++)
      {
-        warning_number[offset]=*(warning_message+offset+1);
-        if (*(warning_message+offset) == ' ')
+        warning_number[offset] = warning_message[offset + 1];
+        if (warning_message[offset] == ' ')
             break;
      }
-     if((offset > 1) && (offset < 15))
+     if ((offset > 1) && (offset < 15))
      {
-       warning_number[offset-1]='\0';
-       fprintf(stderr, "libpng warning no. %s: %s\n", warning_number,
-          warning_message+offset);
+       warning_number[offset + 1] = '\0';
+       fprintf(stderr, "libpng warning no. %s: %s",
+          warning_number, warning_message + offset);
+       fprintf(stderr, PNG_STRING_NEWLINE);
      }
      else
-       fprintf(stderr, "libpng warning: %s\n", warning_message);
+     {
+       fprintf(stderr, "libpng warning: %s",
+          warning_message);
+       fprintf(stderr, PNG_STRING_NEWLINE);
+     }
    }
    else
 #  endif
-     fprintf(stderr, "libpng warning: %s\n", warning_message);
+   {
+     fprintf(stderr, "libpng warning: %s", warning_message);
+     fprintf(stderr, PNG_STRING_NEWLINE);
+   }
 #else
-   warning_message = warning_message; /* make compiler happy */
+   warning_message = warning_message; /* Make compiler happy */
 #endif
-   png_ptr = png_ptr; /* make compiler happy */
+   png_ptr = png_ptr; /* Make compiler happy */
 }
-#endif /* PNG_NO_WARNINGS */
+#endif /* PNG_WARNINGS_SUPPORTED */
 
 /* This function is called when the application wants to use another method
  * of handling errors and warnings.  Note that the error function MUST NOT
@@ -333,7 +386,7 @@ png_get_error_ptr(png_structp png_ptr)
 void PNGAPI
 png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
 {
-   if(png_ptr != NULL)
+   if (png_ptr != NULL)
    {
      png_ptr->flags &=
        ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngget.c b/graf2d/asimage/src/libAfterImage/libpng/pngget.c
index a0e90bb..d397329 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngget.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngget.c
@@ -1,16 +1,20 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * Last changed in libpng 1.2.15 January 5, 2007
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
 
 png_uint_32 PNGAPI
@@ -18,6 +22,7 @@ png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)
 {
    if (png_ptr != NULL && info_ptr != NULL)
       return(info_ptr->valid & flag);
+
    else
       return(0);
 }
@@ -27,30 +32,31 @@ png_get_rowbytes(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
       return(info_ptr->rowbytes);
+
    else
       return(0);
 }
 
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
+#ifdef PNG_INFO_IMAGE_SUPPORTED
 png_bytepp PNGAPI
 png_get_rows(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
       return(info_ptr->row_pointers);
+
    else
       return(0);
 }
 #endif
 
 #ifdef PNG_EASY_ACCESS_SUPPORTED
-/* easy access to info, added in libpng-0.99 */
+/* Easy access to info, added in libpng-0.99 */
 png_uint_32 PNGAPI
 png_get_image_width(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-   {
       return info_ptr->width;
-   }
+
    return (0);
 }
 
@@ -58,9 +64,8 @@ png_uint_32 PNGAPI
 png_get_image_height(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-   {
       return info_ptr->height;
-   }
+
    return (0);
 }
 
@@ -68,9 +73,8 @@ png_byte PNGAPI
 png_get_bit_depth(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-   {
       return info_ptr->bit_depth;
-   }
+
    return (0);
 }
 
@@ -78,9 +82,8 @@ png_byte PNGAPI
 png_get_color_type(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-   {
       return info_ptr->color_type;
-   }
+
    return (0);
 }
 
@@ -88,9 +91,8 @@ png_byte PNGAPI
 png_get_filter_type(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-   {
       return info_ptr->filter_type;
-   }
+
    return (0);
 }
 
@@ -98,9 +100,8 @@ png_byte PNGAPI
 png_get_interlace_type(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-   {
       return info_ptr->interlace_type;
-   }
+
    return (0);
 }
 
@@ -108,9 +109,8 @@ png_byte PNGAPI
 png_get_compression_type(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-   {
       return info_ptr->compression_type;
-   }
+
    return (0);
 }
 
@@ -118,13 +118,16 @@ png_uint_32 PNGAPI
 png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_pHYs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter");
-      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+      png_debug1(1, "in %s retrieval function", "png_get_x_pixels_per_meter");
+
+      if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
           return (0);
-      else return (info_ptr->x_pixels_per_unit);
+
+      else
+          return (info_ptr->x_pixels_per_unit);
    }
 #else
    return (0);
@@ -136,13 +139,16 @@ png_uint_32 PNGAPI
 png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_pHYs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter");
-      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+      png_debug1(1, "in %s retrieval function", "png_get_y_pixels_per_meter");
+
+      if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
           return (0);
-      else return (info_ptr->y_pixels_per_unit);
+
+      else
+          return (info_ptr->y_pixels_per_unit);
    }
 #else
    return (0);
@@ -154,14 +160,17 @@ png_uint_32 PNGAPI
 png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_pHYs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter");
-      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER ||
+      png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
+
+      if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER ||
          info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit)
           return (0);
-      else return (info_ptr->x_pixels_per_unit);
+
+      else
+          return (info_ptr->x_pixels_per_unit);
    }
 #else
    return (0);
@@ -174,18 +183,21 @@ float PNGAPI
 png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr)
    {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
+
    if (info_ptr->valid & PNG_INFO_pHYs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio");
+      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
+
       if (info_ptr->x_pixels_per_unit == 0)
          return ((float)0.0);
+
       else
          return ((float)((float)info_ptr->y_pixels_per_unit
             /(float)info_ptr->x_pixels_per_unit));
    }
 #else
-   return (0.0);
+      return (0.0);
 #endif
    return ((float)0.0);
 }
@@ -195,16 +207,20 @@ png_int_32 PNGAPI
 png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_oFFs_SUPPORTED)
+#ifdef PNG_oFFs_SUPPORTED
+
    if (info_ptr->valid & PNG_INFO_oFFs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
-      if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
+
+      if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
           return (0);
-      else return (info_ptr->x_offset);
+
+      else
+          return (info_ptr->x_offset);
    }
 #else
-   return (0);
+      return (0);
 #endif
    return (0);
 }
@@ -213,13 +229,17 @@ png_int_32 PNGAPI
 png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_oFFs_SUPPORTED)
+
+#ifdef PNG_oFFs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_oFFs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
-      if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
+
+      if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
           return (0);
-      else return (info_ptr->y_offset);
+
+      else
+          return (info_ptr->y_offset);
    }
 #else
    return (0);
@@ -231,13 +251,17 @@ png_int_32 PNGAPI
 png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_oFFs_SUPPORTED)
+
+#ifdef PNG_oFFs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_oFFs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
-      if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
+
+      if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
           return (0);
-      else return (info_ptr->x_offset);
+
+      else
+          return (info_ptr->x_offset);
    }
 #else
    return (0);
@@ -249,13 +273,17 @@ png_int_32 PNGAPI
 png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr)
 {
    if (png_ptr != NULL && info_ptr != NULL)
-#if defined(PNG_oFFs_SUPPORTED)
+
+#ifdef PNG_oFFs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_oFFs)
    {
-      png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
-      if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
+
+      if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
           return (0);
-      else return (info_ptr->y_offset);
+
+      else
+          return (info_ptr->y_offset);
    }
 #else
    return (0);
@@ -299,7 +327,7 @@ png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr)
      *.00003937);
 }
 
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
 png_uint_32 PNGAPI
 png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
@@ -308,7 +336,8 @@ png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
 
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
    {
-      png_debug1(1, "in %s retrieval function\n", "pHYs");
+      png_debug1(1, "in %s retrieval function", "pHYs");
+
       if (res_x != NULL)
       {
          *res_x = info_ptr->x_pixels_per_unit;
@@ -323,7 +352,7 @@ png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
       {
          *unit_type = (int)info_ptr->phys_unit_type;
          retval |= PNG_INFO_pHYs;
-         if(*unit_type == 1)
+         if (*unit_type == 1)
          {
             if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50);
             if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
@@ -357,7 +386,7 @@ png_get_signature(png_structp png_ptr, png_infop info_ptr)
       return (NULL);
 }
 
-#if defined(PNG_bKGD_SUPPORTED)
+#ifdef PNG_bKGD_SUPPORTED
 png_uint_32 PNGAPI
 png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
    png_color_16p *background)
@@ -365,7 +394,8 @@ png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
       && background != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "bKGD");
+      png_debug1(1, "in %s retrieval function", "bKGD");
+
       *background = &(info_ptr->background);
       return (PNG_INFO_bKGD);
    }
@@ -373,7 +403,7 @@ png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_cHRM_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_cHRM(png_structp png_ptr, png_infop info_ptr,
@@ -382,7 +412,8 @@ png_get_cHRM(png_structp png_ptr, png_infop info_ptr,
 {
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
    {
-      png_debug1(1, "in %s retrieval function\n", "cHRM");
+      png_debug1(1, "in %s retrieval function", "cHRM");
+
       if (white_x != NULL)
          *white_x = (double)info_ptr->x_white;
       if (white_y != NULL)
@@ -411,9 +442,10 @@ png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
    png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
    png_fixed_point *blue_x, png_fixed_point *blue_y)
 {
+   png_debug1(1, "in %s retrieval function", "cHRM");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
    {
-      png_debug1(1, "in %s retrieval function\n", "cHRM");
       if (white_x != NULL)
          *white_x = info_ptr->int_x_white;
       if (white_y != NULL)
@@ -437,15 +469,16 @@ png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
 #endif
 #endif
 
-#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_gAMA_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
 {
+   png_debug1(1, "in %s retrieval function", "gAMA");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
       && file_gamma != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "gAMA");
       *file_gamma = (double)info_ptr->gamma;
       return (PNG_INFO_gAMA);
    }
@@ -457,10 +490,11 @@ png_uint_32 PNGAPI
 png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
     png_fixed_point *int_file_gamma)
 {
+   png_debug1(1, "in %s retrieval function", "gAMA");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
       && int_file_gamma != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "gAMA");
       *int_file_gamma = info_ptr->int_gamma;
       return (PNG_INFO_gAMA);
    }
@@ -469,14 +503,15 @@ png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
 #endif
 #endif
 
-#if defined(PNG_sRGB_SUPPORTED)
+#ifdef PNG_sRGB_SUPPORTED
 png_uint_32 PNGAPI
 png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent)
 {
+   png_debug1(1, "in %s retrieval function", "sRGB");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
       && file_srgb_intent != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "sRGB");
       *file_srgb_intent = (int)info_ptr->srgb_intent;
       return (PNG_INFO_sRGB);
    }
@@ -484,20 +519,22 @@ png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent)
 }
 #endif
 
-#if defined(PNG_iCCP_SUPPORTED)
+#ifdef PNG_iCCP_SUPPORTED
 png_uint_32 PNGAPI
 png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
              png_charpp name, int *compression_type,
              png_charpp profile, png_uint_32 *proflen)
 {
+   png_debug1(1, "in %s retrieval function", "iCCP");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
       && name != NULL && profile != NULL && proflen != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "iCCP");
       *name = info_ptr->iccp_name;
       *profile = info_ptr->iccp_profile;
-      /* compression_type is a dummy so the API won't have to change
-         if we introduce multiple compression types later. */
+      /* Compression_type is a dummy so the API won't have to change
+       * if we introduce multiple compression types later.
+       */
       *proflen = (int)info_ptr->iccp_proflen;
       *compression_type = (int)info_ptr->iccp_compression;
       return (PNG_INFO_iCCP);
@@ -506,7 +543,7 @@ png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_sPLT_SUPPORTED)
+#ifdef PNG_sPLT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_sPLT(png_structp png_ptr, png_infop info_ptr,
              png_sPLT_tpp spalettes)
@@ -520,14 +557,15 @@ png_get_sPLT(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_hIST_SUPPORTED)
+#ifdef PNG_hIST_SUPPORTED
 png_uint_32 PNGAPI
 png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist)
 {
+   png_debug1(1, "in %s retrieval function", "hIST");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
       && hist != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "hIST");
       *hist = info_ptr->hist;
       return (PNG_INFO_hIST);
    }
@@ -542,54 +580,48 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
    int *filter_type)
 
 {
-   if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL &&
-      bit_depth != NULL && color_type != NULL)
-   {
-      png_debug1(1, "in %s retrieval function\n", "IHDR");
-      *width = info_ptr->width;
-      *height = info_ptr->height;
-      *bit_depth = info_ptr->bit_depth;
-      if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16)
-        png_error(png_ptr, "Invalid bit depth");
-      *color_type = info_ptr->color_type;
-      if (info_ptr->color_type > 6)
-        png_error(png_ptr, "Invalid color type");
-      if (compression_type != NULL)
-         *compression_type = info_ptr->compression_type;
-      if (filter_type != NULL)
-         *filter_type = info_ptr->filter_type;
-      if (interlace_type != NULL)
-         *interlace_type = info_ptr->interlace_type;
-
-      /* check for potential overflow of rowbytes */
-      if (*width == 0 || *width > PNG_UINT_31_MAX)
-        png_error(png_ptr, "Invalid image width");
-      if (*height == 0 || *height > PNG_UINT_31_MAX)
-        png_error(png_ptr, "Invalid image height");
-      if (info_ptr->width > (PNG_UINT_32_MAX
-                 >> 3)      /* 8-byte RGBA pixels */
-                 - 64       /* bigrowbuf hack */
-                 - 1        /* filter byte */
-                 - 7*8      /* rounding of width to multiple of 8 pixels */
-                 - 8)       /* extra max_pixel_depth pad */
-      {
-         png_warning(png_ptr,
-            "Width too large for libpng to process image data.");
-      }
-      return (1);
-   }
-   return (0);
+   png_debug1(1, "in %s retrieval function", "IHDR");
+
+   if (png_ptr == NULL || info_ptr == NULL || width == NULL ||
+       height == NULL || bit_depth == NULL || color_type == NULL)
+      return (0);
+
+   *width = info_ptr->width;
+   *height = info_ptr->height;
+   *bit_depth = info_ptr->bit_depth;
+   *color_type = info_ptr->color_type;
+
+   if (compression_type != NULL)
+      *compression_type = info_ptr->compression_type;
+
+   if (filter_type != NULL)
+      *filter_type = info_ptr->filter_type;
+
+   if (interlace_type != NULL)
+      *interlace_type = info_ptr->interlace_type;
+
+   /* This is redundant if we can be sure that the info_ptr values were all
+    * assigned in png_set_IHDR().  We do the check anyhow in case an
+    * application has ignored our advice not to mess with the members
+    * of info_ptr directly.
+    */
+   png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
+       info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
+       info_ptr->compression_type, info_ptr->filter_type);
+
+   return (1);
 }
 
-#if defined(PNG_oFFs_SUPPORTED)
+#ifdef PNG_oFFs_SUPPORTED
 png_uint_32 PNGAPI
 png_get_oFFs(png_structp png_ptr, png_infop info_ptr,
    png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
 {
+   png_debug1(1, "in %s retrieval function", "oFFs");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
       && offset_x != NULL && offset_y != NULL && unit_type != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "oFFs");
       *offset_x = info_ptr->x_offset;
       *offset_y = info_ptr->y_offset;
       *unit_type = (int)info_ptr->offset_unit_type;
@@ -599,17 +631,18 @@ png_get_oFFs(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_pCAL_SUPPORTED)
+#ifdef PNG_pCAL_SUPPORTED
 png_uint_32 PNGAPI
 png_get_pCAL(png_structp png_ptr, png_infop info_ptr,
    png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
    png_charp *units, png_charpp *params)
 {
+   png_debug1(1, "in %s retrieval function", "pCAL");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
-      && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
-      nparams != NULL && units != NULL && params != NULL)
+       && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
+       nparams != NULL && units != NULL && params != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "pCAL");
       *purpose = info_ptr->pcal_purpose;
       *X0 = info_ptr->pcal_X0;
       *X1 = info_ptr->pcal_X1;
@@ -623,14 +656,14 @@ png_get_pCAL(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_sCAL_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_sCAL(png_structp png_ptr, png_infop info_ptr,
              int *unit, double *width, double *height)
 {
     if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_sCAL))
+        (info_ptr->valid & PNG_INFO_sCAL))
     {
         *unit = info_ptr->scal_unit;
         *width = info_ptr->scal_pixel_width;
@@ -646,7 +679,7 @@ png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
              int *unit, png_charpp width, png_charpp height)
 {
     if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_sCAL))
+        (info_ptr->valid & PNG_INFO_sCAL))
     {
         *unit = info_ptr->scal_unit;
         *width = info_ptr->scal_s_width;
@@ -659,27 +692,30 @@ png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
 #endif
 #endif
 
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
 png_uint_32 PNGAPI
 png_get_pHYs(png_structp png_ptr, png_infop info_ptr,
    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
 {
    png_uint_32 retval = 0;
 
+   png_debug1(1, "in %s retrieval function", "pHYs");
+
    if (png_ptr != NULL && info_ptr != NULL &&
       (info_ptr->valid & PNG_INFO_pHYs))
    {
-      png_debug1(1, "in %s retrieval function\n", "pHYs");
       if (res_x != NULL)
       {
          *res_x = info_ptr->x_pixels_per_unit;
          retval |= PNG_INFO_pHYs;
       }
+
       if (res_y != NULL)
       {
          *res_y = info_ptr->y_pixels_per_unit;
          retval |= PNG_INFO_pHYs;
       }
+
       if (unit_type != NULL)
       {
          *unit_type = (int)info_ptr->phys_unit_type;
@@ -694,26 +730,28 @@ png_uint_32 PNGAPI
 png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette,
    int *num_palette)
 {
+   png_debug1(1, "in %s retrieval function", "PLTE");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
        && palette != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "PLTE");
       *palette = info_ptr->palette;
       *num_palette = info_ptr->num_palette;
-      png_debug1(3, "num_palette = %d\n", *num_palette);
+      png_debug1(3, "num_palette = %d", *num_palette);
       return (PNG_INFO_PLTE);
    }
    return (0);
 }
 
-#if defined(PNG_sBIT_SUPPORTED)
+#ifdef PNG_sBIT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)
 {
+   png_debug1(1, "in %s retrieval function", "sBIT");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
       && sig_bit != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "sBIT");
       *sig_bit = &(info_ptr->sig_bit);
       return (PNG_INFO_sBIT);
    }
@@ -721,20 +759,23 @@ png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)
 }
 #endif
 
-#if defined(PNG_TEXT_SUPPORTED)
+#ifdef PNG_TEXT_SUPPORTED
 png_uint_32 PNGAPI
 png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr,
    int *num_text)
 {
    if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
    {
-      png_debug1(1, "in %s retrieval function\n",
+      png_debug1(1, "in %s retrieval function",
          (png_ptr->chunk_name[0] == '\0' ? "text"
              : (png_const_charp)png_ptr->chunk_name));
+
       if (text_ptr != NULL)
          *text_ptr = info_ptr->text;
+
       if (num_text != NULL)
          *num_text = info_ptr->num_text;
+
       return ((png_uint_32)info_ptr->num_text);
    }
    if (num_text != NULL)
@@ -743,14 +784,15 @@ png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr,
 }
 #endif
 
-#if defined(PNG_tIME_SUPPORTED)
+#ifdef PNG_tIME_SUPPORTED
 png_uint_32 PNGAPI
 png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
 {
+   png_debug1(1, "in %s retrieval function", "tIME");
+
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
        && mod_time != NULL)
    {
-      png_debug1(1, "in %s retrieval function\n", "tIME");
       *mod_time = &(info_ptr->mod_time);
       return (PNG_INFO_tIME);
    }
@@ -758,7 +800,7 @@ png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
 }
 #endif
 
-#if defined(PNG_tRNS_SUPPORTED)
+#ifdef PNG_tRNS_SUPPORTED
 png_uint_32 PNGAPI
 png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
    png_bytep *trans, int *num_trans, png_color_16p *trans_values)
@@ -766,7 +808,8 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
    png_uint_32 retval = 0;
    if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
    {
-      png_debug1(1, "in %s retrieval function\n", "tRNS");
+      png_debug1(1, "in %s retrieval function", "tRNS");
+
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       {
           if (trans != NULL)
@@ -774,6 +817,7 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
              *trans = info_ptr->trans;
              retval |= PNG_INFO_tRNS;
           }
+
           if (trans_values != NULL)
              *trans_values = &(info_ptr->trans_values);
       }
@@ -784,10 +828,11 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
              *trans_values = &(info_ptr->trans_values);
              retval |= PNG_INFO_tRNS;
           }
-          if(trans != NULL)
+
+          if (trans != NULL)
              *trans = NULL;
       }
-      if(num_trans != NULL)
+      if (num_trans != NULL)
       {
          *num_trans = info_ptr->num_trans;
          retval |= PNG_INFO_tRNS;
@@ -797,7 +842,7 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
 png_uint_32 PNGAPI
 png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
              png_unknown_chunkpp unknowns)
@@ -811,7 +856,7 @@ png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
 png_byte PNGAPI
 png_get_rgb_to_gray_status (png_structp png_ptr)
 {
@@ -819,7 +864,7 @@ png_get_rgb_to_gray_status (png_structp png_ptr)
 }
 #endif
 
-#if defined(PNG_USER_CHUNKS_SUPPORTED)
+#ifdef PNG_USER_CHUNKS_SUPPORTED
 png_voidp PNGAPI
 png_get_user_chunk_ptr(png_structp png_ptr)
 {
@@ -827,64 +872,63 @@ png_get_user_chunk_ptr(png_structp png_ptr)
 }
 #endif
 
-#ifdef PNG_WRITE_SUPPORTED
 png_uint_32 PNGAPI
 png_get_compression_buffer_size(png_structp png_ptr)
 {
    return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L);
 }
-#endif
 
 #ifdef PNG_ASSEMBLER_CODE_SUPPORTED
 #ifndef PNG_1_0_X
-/* this function was added to libpng 1.2.0 and should exist by default */
+/* This function was added to libpng 1.2.0 and should exist by default */
 png_uint_32 PNGAPI
 png_get_asm_flags (png_structp png_ptr)
 {
-    /* obsolete, to be removed from libpng-1.4.0 */
+    /* Obsolete, to be removed from libpng-1.4.0 */
     return (png_ptr? 0L: 0L);
 }
 
-/* this function was added to libpng 1.2.0 and should exist by default */
+/* This function was added to libpng 1.2.0 and should exist by default */
 png_uint_32 PNGAPI
 png_get_asm_flagmask (int flag_select)
 {
-    /* obsolete, to be removed from libpng-1.4.0 */
+    /* Obsolete, to be removed from libpng-1.4.0 */
     flag_select=flag_select;
     return 0L;
 }
 
     /* GRR:  could add this:   && defined(PNG_MMX_CODE_SUPPORTED) */
-/* this function was added to libpng 1.2.0 */
+/* This function was added to libpng 1.2.0 */
 png_uint_32 PNGAPI
 png_get_mmx_flagmask (int flag_select, int *compilerID)
 {
-    /* obsolete, to be removed from libpng-1.4.0 */
+    /* Obsolete, to be removed from libpng-1.4.0 */
     flag_select=flag_select;
     *compilerID = -1;   /* unknown (i.e., no asm/MMX code compiled) */
     return 0L;
 }
 
-/* this function was added to libpng 1.2.0 */
+/* This function was added to libpng 1.2.0 */
 png_byte PNGAPI
 png_get_mmx_bitdepth_threshold (png_structp png_ptr)
 {
-    /* obsolete, to be removed from libpng-1.4.0 */
+    /* Obsolete, to be removed from libpng-1.4.0 */
     return (png_ptr? 0: 0);
 }
 
-/* this function was added to libpng 1.2.0 */
+/* This function was added to libpng 1.2.0 */
 png_uint_32 PNGAPI
 png_get_mmx_rowbytes_threshold (png_structp png_ptr)
 {
-    /* obsolete, to be removed from libpng-1.4.0 */
+    /* Obsolete, to be removed from libpng-1.4.0 */
     return (png_ptr? 0L: 0L);
 }
 #endif /* ?PNG_1_0_X */
 #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
 
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
-/* these functions were added to libpng 1.2.6 */
+/* These functions were added to libpng 1.2.6 but not enabled
+* by default. They will be enabled in libpng-1.4.0 */
 png_uint_32 PNGAPI
 png_get_user_width_max (png_structp png_ptr)
 {
@@ -896,6 +940,5 @@ png_get_user_height_max (png_structp png_ptr)
     return (png_ptr? png_ptr->user_height_max : 0);
 }
 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
- 
 
 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngmem.c b/graf2d/asimage/src/libAfterImage/libpng/pngmem.c
index 248060f..a18719b 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngmem.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngmem.c
@@ -1,12 +1,15 @@
 
 /* pngmem.c - stub functions for memory allocation
  *
- * Last changed in libpng 1.2.13 November 13, 2006
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2006 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.41 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * This file provides a location for all memory allocation.  Users who
  * need special memory handling are expected to supply replacement
  * functions for png_malloc() and png_free(), and to use
@@ -15,13 +18,13 @@
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
 
 /* Borland DOS special memory handler */
 #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
-/* if you change this, be sure to change the one in png.h also */
+/* If you change this, be sure to change the one in png.h also */
 
 /* Allocate memory for a png_struct.  The malloc and memset can be replaced
    by a single call to calloc() if this is thought to improve performance. */
@@ -41,14 +44,14 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
    png_voidp struct_ptr;
 
    if (type == PNG_STRUCT_INFO)
-     size = png_sizeof(png_info);
+      size = png_sizeof(png_info);
    else if (type == PNG_STRUCT_PNG)
-     size = png_sizeof(png_struct);
+      size = png_sizeof(png_struct);
    else
-     return (png_get_copyright(NULL));
+      return (png_get_copyright(NULL));
 
 #ifdef PNG_USER_MEM_SUPPORTED
-   if(malloc_fn != NULL)
+   if (malloc_fn != NULL)
    {
       png_struct dummy_struct;
       png_structp png_ptr = &dummy_struct;
@@ -57,7 +60,7 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
    }
    else
 #endif /* PNG_USER_MEM_SUPPORTED */
-      struct_ptr = (png_voidp)farmalloc(size);
+   struct_ptr = (png_voidp)farmalloc(size);
    if (struct_ptr != NULL)
       png_memset(struct_ptr, 0, size);
    return (struct_ptr);
@@ -80,7 +83,7 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
    if (struct_ptr != NULL)
    {
 #ifdef PNG_USER_MEM_SUPPORTED
-      if(free_fn != NULL)
+      if (free_fn != NULL)
       {
          png_struct dummy_struct;
          png_structp png_ptr = &dummy_struct;
@@ -112,6 +115,16 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
  * result, we would be truncating potentially larger memory requests
  * (which should cause a fatal error) and introducing major problems.
  */
+png_voidp /* PRIVATE */
+png_calloc(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+
+   ret = (png_malloc(png_ptr, size));
+   if (ret != NULL)
+      png_memset(ret,0,(png_size_t)size);
+   return (ret);
+}
 
 png_voidp PNGAPI
 png_malloc(png_structp png_ptr, png_uint_32 size)
@@ -122,10 +135,10 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
       return (NULL);
 
 #ifdef PNG_USER_MEM_SUPPORTED
-   if(png_ptr->malloc_fn != NULL)
-       ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
+   if (png_ptr->malloc_fn != NULL)
+      ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
    else
-       ret = (png_malloc_default(png_ptr, size));
+      ret = (png_malloc_default(png_ptr, size));
    if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
        png_error(png_ptr, "Out of memory!");
    return (ret);
@@ -150,12 +163,12 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
 #endif
 
    if (size != (size_t)size)
-     ret = NULL;
+      ret = NULL;
    else if (size == (png_uint_32)65536L)
    {
       if (png_ptr->offset_table == NULL)
       {
-         /* try to see if we need to do any of this fancy stuff */
+         /* Try to see if we need to do any of this fancy stuff */
          ret = farmalloc(size);
          if (ret == NULL || ((png_size_t)ret & 0xffff))
          {
@@ -171,7 +184,7 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
                ret = NULL;
             }
 
-            if(png_ptr->zlib_window_bits > 14)
+            if (png_ptr->zlib_window_bits > 14)
                num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
             else
                num_blocks = 1;
@@ -188,7 +201,7 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
             {
 #ifndef PNG_USER_MEM_SUPPORTED
                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
-                  png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
+                  png_error(png_ptr, "Out Of Memory."); /* Note "O", "M" */
                else
                   png_warning(png_ptr, "Out Of Memory.");
 #endif
@@ -210,13 +223,13 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
 
             png_ptr->offset_table = table;
             png_ptr->offset_table_ptr = farmalloc(num_blocks *
-               png_sizeof (png_bytep));
+               png_sizeof(png_bytep));
 
             if (png_ptr->offset_table_ptr == NULL)
             {
 #ifndef PNG_USER_MEM_SUPPORTED
                if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
-                  png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */
+                  png_error(png_ptr, "Out Of memory."); /* Note "O", "m" */
                else
                   png_warning(png_ptr, "Out Of memory.");
 #endif
@@ -270,9 +283,10 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
    return (ret);
 }
 
-/* free a pointer allocated by png_malloc().  In the default
-   configuration, png_ptr is not used, but is passed in case it
-   is needed.  If ptr is NULL, return without taking any action. */
+/* Free a pointer allocated by png_malloc().  In the default
+ * configuration, png_ptr is not used, but is passed in case it
+ * is needed.  If ptr is NULL, return without taking any action.
+ */
 void PNGAPI
 png_free(png_structp png_ptr, png_voidp ptr)
 {
@@ -285,7 +299,8 @@ png_free(png_structp png_ptr, png_voidp ptr)
       (*(png_ptr->free_fn))(png_ptr, ptr);
       return;
    }
-   else png_free_default(png_ptr, ptr);
+   else
+      png_free_default(png_ptr, ptr);
 }
 
 void PNGAPI
@@ -293,7 +308,8 @@ png_free_default(png_structp png_ptr, png_voidp ptr)
 {
 #endif /* PNG_USER_MEM_SUPPORTED */
 
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL || ptr == NULL)
+      return;
 
    if (png_ptr->offset_table != NULL)
    {
@@ -353,7 +369,7 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
       return (NULL);
 
 #ifdef PNG_USER_MEM_SUPPORTED
-   if(malloc_fn != NULL)
+   if (malloc_fn != NULL)
    {
       png_struct dummy_struct;
       png_structp png_ptr = &dummy_struct;
@@ -369,7 +385,7 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
    struct_ptr = (png_voidp)farmalloc(size);
 #else
 # if defined(_MSC_VER) && defined(MAXSEG_64K)
-   struct_ptr = (png_voidp)halloc(size,1);
+   struct_ptr = (png_voidp)halloc(size, 1);
 # else
    struct_ptr = (png_voidp)malloc(size);
 # endif
@@ -398,7 +414,7 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
    if (struct_ptr != NULL)
    {
 #ifdef PNG_USER_MEM_SUPPORTED
-      if(free_fn != NULL)
+      if (free_fn != NULL)
       {
          png_struct dummy_struct;
          png_structp png_ptr = &dummy_struct;
@@ -420,10 +436,22 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
 }
 
 /* Allocate memory.  For reasonable files, size should never exceed
-   64K.  However, zlib may allocate more then 64K if you don't tell
-   it not to.  See zconf.h and png.h for more information.  zlib does
-   need to allocate exactly 64K, so whatever you call here must
-   have the ability to do that. */
+ * 64K.  However, zlib may allocate more then 64K if you don't tell
+ * it not to.  See zconf.h and png.h for more information.  zlib does
+ * need to allocate exactly 64K, so whatever you call here must
+ * have the ability to do that.
+ */
+
+png_voidp /* PRIVATE */
+png_calloc(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+
+   ret = (png_malloc(png_ptr, size));
+   if (ret != NULL)
+      png_memset(ret,0,(png_size_t)size);
+   return (ret);
+}
 
 png_voidp PNGAPI
 png_malloc(png_structp png_ptr, png_uint_32 size)
@@ -434,10 +462,10 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
    if (png_ptr == NULL || size == 0)
       return (NULL);
 
-   if(png_ptr->malloc_fn != NULL)
-       ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
+   if (png_ptr->malloc_fn != NULL)
+      ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
    else
-       ret = (png_malloc_default(png_ptr, size));
+      ret = (png_malloc_default(png_ptr, size));
    if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
        png_error(png_ptr, "Out of Memory!");
    return (ret);
@@ -456,7 +484,7 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
    if (size > (png_uint_32)65536L)
    {
 #ifndef PNG_USER_MEM_SUPPORTED
-      if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+      if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
          png_error(png_ptr, "Cannot Allocate > 64K");
       else
 #endif
@@ -464,23 +492,23 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
    }
 #endif
 
- /* Check for overflow */
+   /* Check for overflow */
 #if defined(__TURBOC__) && !defined(__FLAT__)
- if (size != (unsigned long)size)
-   ret = NULL;
- else
-   ret = farmalloc(size);
+   if (size != (unsigned long)size)
+      ret = NULL;
+   else
+      ret = farmalloc(size);
 #else
 # if defined(_MSC_VER) && defined(MAXSEG_64K)
- if (size != (unsigned long)size)
-   ret = NULL;
- else
-   ret = halloc(size, 1);
+   if (size != (unsigned long)size)
+      ret = NULL;
+   else
+      ret = halloc(size, 1);
 # else
- if (size != (size_t)size)
-   ret = NULL;
- else
-   ret = malloc((size_t)size);
+   if (size != (size_t)size)
+      ret = NULL;
+   else
+      ret = malloc((size_t)size);
 # endif
 #endif
 
@@ -493,7 +521,8 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size)
 }
 
 /* Free a pointer allocated by png_malloc().  If ptr is NULL, return
-   without taking any action. */
+ * without taking any action.
+ */
 void PNGAPI
 png_free(png_structp png_ptr, png_voidp ptr)
 {
@@ -506,7 +535,8 @@ png_free(png_structp png_ptr, png_voidp ptr)
       (*(png_ptr->free_fn))(png_ptr, ptr);
       return;
    }
-   else png_free_default(png_ptr, ptr);
+   else
+      png_free_default(png_ptr, ptr);
 }
 void PNGAPI
 png_free_default(png_structp png_ptr, png_voidp ptr)
@@ -529,7 +559,7 @@ png_free_default(png_structp png_ptr, png_voidp ptr)
 
 #endif /* Not Borland DOS special memory handler */
 
-#if defined(PNG_1_0_X)
+#ifdef PNG_1_0_X
 #  define png_malloc_warn png_malloc
 #else
 /* This function was added at libpng version 1.2.3.  The png_malloc_warn()
@@ -542,9 +572,10 @@ png_malloc_warn(png_structp png_ptr, png_uint_32 size)
 {
    png_voidp ptr;
    png_uint_32 save_flags;
-   if(png_ptr == NULL) return (NULL);
+   if (png_ptr == NULL)
+      return (NULL);
 
-   save_flags=png_ptr->flags;
+   save_flags = png_ptr->flags;
    png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
    ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
    png_ptr->flags=save_flags;
@@ -560,7 +591,7 @@ png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
 
    size = (png_size_t)length;
    if ((png_uint_32)size != length)
-      png_error(png_ptr,"Overflow in png_memcpy_check.");
+      png_error(png_ptr, "Overflow in png_memcpy_check.");
 
    return(png_memcpy (s1, s2, size));
 }
@@ -573,7 +604,7 @@ png_memset_check (png_structp png_ptr, png_voidp s1, int value,
 
    size = (png_size_t)length;
    if ((png_uint_32)size != length)
-      png_error(png_ptr,"Overflow in png_memset_check.");
+      png_error(png_ptr, "Overflow in png_memset_check.");
 
    return (png_memset (s1, value, size));
 
@@ -587,10 +618,11 @@ void PNGAPI
 png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
   malloc_fn, png_free_ptr free_fn)
 {
-   if(png_ptr != NULL) {
-   png_ptr->mem_ptr = mem_ptr;
-   png_ptr->malloc_fn = malloc_fn;
-   png_ptr->free_fn = free_fn;
+   if (png_ptr != NULL)
+   {
+      png_ptr->mem_ptr = mem_ptr;
+      png_ptr->malloc_fn = malloc_fn;
+      png_ptr->free_fn = free_fn;
    }
 }
 
@@ -601,7 +633,8 @@ png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
 png_voidp PNGAPI
 png_get_mem_ptr(png_structp png_ptr)
 {
-   if(png_ptr == NULL) return (NULL);
+   if (png_ptr == NULL)
+      return (NULL);
    return ((png_voidp)png_ptr->mem_ptr);
 }
 #endif /* PNG_USER_MEM_SUPPORTED */
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngpread.c b/graf2d/asimage/src/libAfterImage/libpng/pngpread.c
index 87973ae..5af209d 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngpread.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngpread.c
@@ -1,19 +1,22 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * Last changed in libpng 1.2.22 [November 6, 2007]
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.44 [June 26, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 
-/* push model modes */
+/* Push model modes */
 #define PNG_READ_SIG_MODE   0
 #define PNG_READ_CHUNK_MODE 1
 #define PNG_READ_IDAT_MODE  2
@@ -28,7 +31,9 @@ void PNGAPI
 png_process_data(png_structp png_ptr, png_infop info_ptr,
    png_bytep buffer, png_size_t buffer_size)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
    png_push_restore_buffer(png_ptr, buffer, buffer_size);
 
    while (png_ptr->buffer_size)
@@ -43,7 +48,9 @@ png_process_data(png_structp png_ptr, png_infop info_ptr,
 void /* PRIVATE */
 png_process_some_data(png_structp png_ptr, png_infop info_ptr)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
+
    switch (png_ptr->process_mode)
    {
       case PNG_READ_SIG_MODE:
@@ -51,42 +58,25 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
          png_push_read_sig(png_ptr, info_ptr);
          break;
       }
+
       case PNG_READ_CHUNK_MODE:
       {
          png_push_read_chunk(png_ptr, info_ptr);
          break;
       }
+
       case PNG_READ_IDAT_MODE:
       {
          png_push_read_IDAT(png_ptr);
          break;
       }
-#if defined(PNG_READ_tEXt_SUPPORTED)
-      case PNG_READ_tEXt_MODE:
-      {
-         png_push_read_tEXt(png_ptr, info_ptr);
-         break;
-      }
-#endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
-      case PNG_READ_zTXt_MODE:
-      {
-         png_push_read_zTXt(png_ptr, info_ptr);
-         break;
-      }
-#endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
-      case PNG_READ_iTXt_MODE:
-      {
-         png_push_read_iTXt(png_ptr, info_ptr);
-         break;
-      }
-#endif
+
       case PNG_SKIP_MODE:
       {
          png_push_crc_finish(png_ptr);
          break;
       }
+
       default:
       {
          png_ptr->buffer_size = 0;
@@ -114,7 +104,7 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
 
    png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
       num_to_check);
-   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check);
+   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
 
    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
    {
@@ -141,58 +131,59 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
       PNG_CONST PNG_IDAT;
       PNG_CONST PNG_IEND;
       PNG_CONST PNG_PLTE;
-#if defined(PNG_READ_bKGD_SUPPORTED)
+#ifdef PNG_READ_bKGD_SUPPORTED
       PNG_CONST PNG_bKGD;
 #endif
-#if defined(PNG_READ_cHRM_SUPPORTED)
+#ifdef PNG_READ_cHRM_SUPPORTED
       PNG_CONST PNG_cHRM;
 #endif
-#if defined(PNG_READ_gAMA_SUPPORTED)
+#ifdef PNG_READ_gAMA_SUPPORTED
       PNG_CONST PNG_gAMA;
 #endif
-#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_READ_hIST_SUPPORTED
       PNG_CONST PNG_hIST;
 #endif
-#if defined(PNG_READ_iCCP_SUPPORTED)
+#ifdef PNG_READ_iCCP_SUPPORTED
       PNG_CONST PNG_iCCP;
 #endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
+#ifdef PNG_READ_iTXt_SUPPORTED
       PNG_CONST PNG_iTXt;
 #endif
-#if defined(PNG_READ_oFFs_SUPPORTED)
+#ifdef PNG_READ_oFFs_SUPPORTED
       PNG_CONST PNG_oFFs;
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#ifdef PNG_READ_pCAL_SUPPORTED
       PNG_CONST PNG_pCAL;
 #endif
-#if defined(PNG_READ_pHYs_SUPPORTED)
+#ifdef PNG_READ_pHYs_SUPPORTED
       PNG_CONST PNG_pHYs;
 #endif
-#if defined(PNG_READ_sBIT_SUPPORTED)
+#ifdef PNG_READ_sBIT_SUPPORTED
       PNG_CONST PNG_sBIT;
 #endif
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#ifdef PNG_READ_sCAL_SUPPORTED
       PNG_CONST PNG_sCAL;
 #endif
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
       PNG_CONST PNG_sRGB;
 #endif
-#if defined(PNG_READ_sPLT_SUPPORTED)
+#ifdef PNG_READ_sPLT_SUPPORTED
       PNG_CONST PNG_sPLT;
 #endif
-#if defined(PNG_READ_tEXt_SUPPORTED)
+#ifdef PNG_READ_tEXt_SUPPORTED
       PNG_CONST PNG_tEXt;
 #endif
-#if defined(PNG_READ_tIME_SUPPORTED)
+#ifdef PNG_READ_tIME_SUPPORTED
       PNG_CONST PNG_tIME;
 #endif
-#if defined(PNG_READ_tRNS_SUPPORTED)
+#ifdef PNG_READ_tRNS_SUPPORTED
       PNG_CONST PNG_tRNS;
 #endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
+#ifdef PNG_READ_zTXt_SUPPORTED
       PNG_CONST PNG_zTXt;
 #endif
 #endif /* PNG_USE_LOCAL_ARRAYS */
+
    /* First we make sure we have enough data for the 4 byte chunk name
     * and the 4 byte chunk length before proceeding with decoding the
     * chunk data.  To fully decode each of these chunks, we also make
@@ -210,25 +201,31 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
       }
 
       png_push_fill_buffer(png_ptr, chunk_length, 4);
-      png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length);
+      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
       png_reset_crc(png_ptr);
       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
    }
 
    if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
-     if(png_ptr->mode & PNG_AFTER_IDAT)
+     if (png_ptr->mode & PNG_AFTER_IDAT)
         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
 
    if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
    {
+      if (png_ptr->push_length != 13)
+         png_error(png_ptr, "Invalid IHDR length");
+
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
       {
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
    }
+
    else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -236,11 +233,13 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
 
       png_ptr->process_mode = PNG_READ_DONE_MODE;
       png_push_have_end(png_ptr, info_ptr);
    }
+
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
    {
@@ -249,20 +248,26 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
          png_ptr->mode |= PNG_HAVE_IDAT;
+
       png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+
       if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
          png_ptr->mode |= PNG_HAVE_PLTE;
+
       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
       {
          if (!(png_ptr->mode & PNG_HAVE_IHDR))
             png_error(png_ptr, "Missing IHDR before IDAT");
+
          else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
                   !(png_ptr->mode & PNG_HAVE_PLTE))
             png_error(png_ptr, "Missing PLTE before IDAT");
       }
    }
+
 #endif
    else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
    {
@@ -273,23 +278,26 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
       }
       png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
    }
+
    else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
    {
       /* If we reach an IDAT chunk, this means we have read all of the
        * header chunks, and we can start reading the image (or if this
        * is called after the image has been read - we have an error).
        */
-     if (!(png_ptr->mode & PNG_HAVE_IHDR))
-       png_error(png_ptr, "Missing IHDR before IDAT");
-     else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-         !(png_ptr->mode & PNG_HAVE_PLTE))
-       png_error(png_ptr, "Missing PLTE before IDAT");
+
+      if (!(png_ptr->mode & PNG_HAVE_IHDR))
+         png_error(png_ptr, "Missing IHDR before IDAT");
+
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+          !(png_ptr->mode & PNG_HAVE_PLTE))
+         png_error(png_ptr, "Missing PLTE before IDAT");
 
       if (png_ptr->mode & PNG_HAVE_IDAT)
       {
          if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
-           if (png_ptr->push_length == 0)
-              return;
+            if (png_ptr->push_length == 0)
+               return;
 
          if (png_ptr->mode & PNG_AFTER_IDAT)
             png_error(png_ptr, "Too many IDAT's found");
@@ -299,11 +307,14 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
       png_ptr->mode |= PNG_HAVE_IDAT;
       png_ptr->process_mode = PNG_READ_IDAT_MODE;
       png_push_have_info(png_ptr, info_ptr);
-      png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+      png_ptr->zstream.avail_out =
+          (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
+          png_ptr->iwidth) + 1;
       png_ptr->zstream.next_out = png_ptr->row_buf;
       return;
    }
-#if defined(PNG_READ_gAMA_SUPPORTED)
+
+#ifdef PNG_READ_gAMA_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -311,10 +322,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_sBIT_SUPPORTED)
+#ifdef PNG_READ_sBIT_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -322,10 +335,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_cHRM_SUPPORTED)
+#ifdef PNG_READ_cHRM_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -333,10 +348,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -344,10 +361,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_iCCP_SUPPORTED)
+#ifdef PNG_READ_iCCP_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -355,10 +374,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_sPLT_SUPPORTED)
+#ifdef PNG_READ_sPLT_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -366,10 +387,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_tRNS_SUPPORTED)
+#ifdef PNG_READ_tRNS_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -377,10 +400,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_bKGD_SUPPORTED)
+#ifdef PNG_READ_bKGD_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -388,10 +413,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_READ_hIST_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -399,10 +426,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_pHYs_SUPPORTED)
+#ifdef PNG_READ_pHYs_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -410,10 +439,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_oFFs_SUPPORTED)
+#ifdef PNG_READ_oFFs_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -421,10 +452,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
    }
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
+
+#ifdef PNG_READ_pCAL_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -432,10 +465,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#ifdef PNG_READ_sCAL_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -443,10 +478,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_tIME_SUPPORTED)
+#ifdef PNG_READ_tIME_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -454,10 +491,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
+
       png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_tEXt_SUPPORTED)
+#ifdef PNG_READ_tEXt_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -465,10 +504,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
-      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+
+      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
+#ifdef PNG_READ_zTXt_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -476,10 +517,12 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
-      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+
+      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
+#ifdef PNG_READ_iTXt_SUPPORTED
    else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
    {
       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -487,8 +530,10 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
-      png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+
+      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
    }
+
 #endif
    else
    {
@@ -497,7 +542,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
          png_push_save_buffer(png_ptr);
          return;
       }
-      png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
    }
 
    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
@@ -563,7 +608,9 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
 {
    png_bytep ptr;
 
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
+
    ptr = buffer;
    if (png_ptr->save_buffer_size)
    {
@@ -587,6 +634,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
 
       if (length < png_ptr->current_buffer_size)
          save_size = length;
+
       else
          save_size = png_ptr->current_buffer_size;
 
@@ -604,7 +652,7 @@ png_push_save_buffer(png_structp png_ptr)
    {
       if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
       {
-         png_size_t i,istop;
+         png_size_t i, istop;
          png_bytep sp;
          png_bytep dp;
 
@@ -627,10 +675,16 @@ png_push_save_buffer(png_structp png_ptr)
       {
         png_error(png_ptr, "Potential overflow of save_buffer");
       }
+
       new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
       old_buffer = png_ptr->save_buffer;
-      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
+      png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
          (png_uint_32)new_max);
+      if (png_ptr->save_buffer == NULL)
+      {
+        png_free(png_ptr, old_buffer);
+        png_error(png_ptr, "Insufficient memory for save_buffer");
+      }
       png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
       png_free(png_ptr, old_buffer);
       png_ptr->save_buffer_max = new_max;
@@ -673,7 +727,7 @@ png_push_read_IDAT(png_structp png_ptr)
       }
 
       png_push_fill_buffer(png_ptr, chunk_length, 4);
-      png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length);
+      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
       png_reset_crc(png_ptr);
       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
@@ -695,16 +749,18 @@ png_push_read_IDAT(png_structp png_ptr)
       if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
       {
          save_size = (png_size_t)png_ptr->idat_size;
-         /* check for overflow */
-         if((png_uint_32)save_size != png_ptr->idat_size)
+
+         /* Check for overflow */
+         if ((png_uint_32)save_size != png_ptr->idat_size)
             png_error(png_ptr, "save_size overflowed in pngpread");
       }
       else
          save_size = png_ptr->save_buffer_size;
 
       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
-      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
-         png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+      png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
       png_ptr->idat_size -= save_size;
       png_ptr->buffer_size -= save_size;
       png_ptr->save_buffer_size -= save_size;
@@ -717,16 +773,17 @@ png_push_read_IDAT(png_structp png_ptr)
       if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
       {
          save_size = (png_size_t)png_ptr->idat_size;
-         /* check for overflow */
-         if((png_uint_32)save_size != png_ptr->idat_size)
+
+         /* Check for overflow */
+         if ((png_uint_32)save_size != png_ptr->idat_size)
             png_error(png_ptr, "save_size overflowed in pngpread");
       }
       else
          save_size = png_ptr->current_buffer_size;
 
       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
-      if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
-        png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+      png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
 
       png_ptr->idat_size -= save_size;
       png_ptr->buffer_size -= save_size;
@@ -751,57 +808,101 @@ void /* PRIVATE */
 png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
    png_size_t buffer_length)
 {
-   int ret;
-
-   if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
-      png_error(png_ptr, "Extra compression data");
+   /* The caller checks for a non-zero buffer length. */
+   if (!(buffer_length > 0) || buffer == NULL)
+      png_error(png_ptr, "No IDAT data (internal error)");
 
+   /* This routine must process all the data it has been given
+    * before returning, calling the row callback as required to
+    * handle the uncompressed results.
+    */
    png_ptr->zstream.next_in = buffer;
    png_ptr->zstream.avail_in = (uInt)buffer_length;
-   for(;;)
+
+   /* Keep going until the decompressed data is all processed
+    * or the stream marked as finished.
+    */
+   while (png_ptr->zstream.avail_in > 0 &&
+	  !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
    {
-      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-      if (ret != Z_OK)
+      int ret;
+
+      /* We have data for zlib, but we must check that zlib
+       * has somewhere to put the results.  It doesn't matter
+       * if we don't expect any results -- it may be the input
+       * data is just the LZ end code.
+       */
+      if (!(png_ptr->zstream.avail_out > 0))
       {
-         if (ret == Z_STREAM_END)
-         {
-            if (png_ptr->zstream.avail_in)
-               png_error(png_ptr, "Extra compressed data");
-            if (!(png_ptr->zstream.avail_out))
-            {
-               png_push_process_row(png_ptr);
-            }
+         png_ptr->zstream.avail_out =
+             (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
+             png_ptr->iwidth) + 1;
+         png_ptr->zstream.next_out = png_ptr->row_buf;
+      }
 
-            png_ptr->mode |= PNG_AFTER_IDAT;
-            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
-            break;
-         }
-         else if (ret == Z_BUF_ERROR)
-            break;
-         else
-            png_error(png_ptr, "Decompression Error");
+      /* Using Z_SYNC_FLUSH here means that an unterminated
+       * LZ stream can still be handled (a stream with a missing
+       * end code), otherwise (Z_NO_FLUSH) a future zlib
+       * implementation might defer output and, therefore,
+       * change the current behavior.  (See comments in inflate.c
+       * for why this doesn't happen at present with zlib 1.2.5.)
+       */
+      ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
+
+      /* Check for any failure before proceeding. */
+      if (ret != Z_OK && ret != Z_STREAM_END)
+      {
+	 /* Terminate the decompression. */
+	 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+
+         /* This may be a truncated stream (missing or
+	  * damaged end code).  Treat that as a warning.
+	  */
+         if (png_ptr->row_number >= png_ptr->num_rows ||
+	     png_ptr->pass > 6)
+	    png_warning(png_ptr, "Truncated compressed data in IDAT");
+	 else
+	    png_error(png_ptr, "Decompression error in IDAT");
+
+	 /* Skip the check on unprocessed input */
+         return;
       }
-      if (!(png_ptr->zstream.avail_out))
+
+      /* Did inflate output any data? */
+      if (png_ptr->zstream.next_out != png_ptr->row_buf)
       {
-         if ((
-#if defined(PNG_READ_INTERLACING_SUPPORTED)
-             png_ptr->interlaced && png_ptr->pass > 6) ||
-             (!png_ptr->interlaced &&
-#endif
-             png_ptr->row_number == png_ptr->num_rows))
+	 /* Is this unexpected data after the last row?
+	  * If it is, artificially terminate the LZ output
+	  * here.
+	  */
+         if (png_ptr->row_number >= png_ptr->num_rows ||
+	     png_ptr->pass > 6)
          {
-           if (png_ptr->zstream.avail_in)
-             png_warning(png_ptr, "Too much data in IDAT chunks");
-           png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
-           break;
-         }
-         png_push_process_row(png_ptr);
-         png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
-         png_ptr->zstream.next_out = png_ptr->row_buf;
+	    /* Extra data. */
+	    png_warning(png_ptr, "Extra compressed data in IDAT");
+            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+	    /* Do no more processing; skip the unprocessed
+	     * input check below.
+	     */
+            return;
+	 }
+
+	 /* Do we have a complete row? */
+	 if (png_ptr->zstream.avail_out == 0)
+	    png_push_process_row(png_ptr);
       }
-      else
-         break;
+
+      /* And check for the end of the stream. */
+      if (ret == Z_STREAM_END)
+	 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
    }
+
+   /* All the data should have been processed, if anything
+    * is left at this point we have bytes of IDAT data
+    * after the zlib end code.
+    */
+   if (png_ptr->zstream.avail_in > 0)
+      png_warning(png_ptr, "Extra compression data");
 }
 
 void /* PRIVATE */
@@ -817,8 +918,8 @@ png_push_process_row(png_structp png_ptr)
        png_ptr->row_info.width);
 
    png_read_filter_row(png_ptr, &(png_ptr->row_info),
-      png_ptr->row_buf + 1, png_ptr->prev_row + 1,
-      (int)(png_ptr->row_buf[0]));
+       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
+       (int)(png_ptr->row_buf[0]));
 
    png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
       png_ptr->rowbytes + 1);
@@ -826,14 +927,14 @@ png_push_process_row(png_structp png_ptr)
    if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
       png_do_read_transformations(png_ptr);
 
-#if defined(PNG_READ_INTERLACING_SUPPORTED)
-   /* blow up interlaced rows to full size */
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   /* Blow up interlaced rows to full size */
    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
    {
       if (png_ptr->pass < 6)
 /*       old interface (pre-1.0.9):
          png_do_read_interlace(&(png_ptr->row_info),
-            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+             png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
  */
          png_do_read_interlace(png_ptr);
 
@@ -845,9 +946,10 @@ png_push_process_row(png_structp png_ptr)
             for (i = 0; i < 8 && png_ptr->pass == 0; i++)
             {
                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-               png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */
+               png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
             }
-            if (png_ptr->pass == 2) /* pass 1 might be empty */
+
+            if (png_ptr->pass == 2) /* Pass 1 might be empty */
             {
                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
                {
@@ -855,6 +957,7 @@ png_push_process_row(png_structp png_ptr)
                   png_read_push_finish_row(png_ptr);
                }
             }
+
             if (png_ptr->pass == 4 && png_ptr->height <= 4)
             {
                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
@@ -863,13 +966,16 @@ png_push_process_row(png_structp png_ptr)
                   png_read_push_finish_row(png_ptr);
                }
             }
+
             if (png_ptr->pass == 6 && png_ptr->height <= 4)
             {
-                png_push_have_row(png_ptr, png_bytep_NULL);
+                  png_push_have_row(png_ptr, png_bytep_NULL);
                 png_read_push_finish_row(png_ptr);
             }
+
             break;
          }
+
          case 1:
          {
             int i;
@@ -878,7 +984,8 @@ png_push_process_row(png_structp png_ptr)
                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
                png_read_push_finish_row(png_ptr);
             }
-            if (png_ptr->pass == 2) /* skip top 4 generated rows */
+
+            if (png_ptr->pass == 2) /* Skip top 4 generated rows */
             {
                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
                {
@@ -886,22 +993,27 @@ png_push_process_row(png_structp png_ptr)
                   png_read_push_finish_row(png_ptr);
                }
             }
+
             break;
          }
+
          case 2:
          {
             int i;
+
             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
             {
                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
                png_read_push_finish_row(png_ptr);
             }
+
             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
             {
-               png_push_have_row(png_ptr, png_bytep_NULL);
+                  png_push_have_row(png_ptr, png_bytep_NULL);
                png_read_push_finish_row(png_ptr);
             }
-            if (png_ptr->pass == 4) /* pass 3 might be empty */
+
+            if (png_ptr->pass == 4) /* Pass 3 might be empty */
             {
                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
                {
@@ -909,17 +1021,21 @@ png_push_process_row(png_structp png_ptr)
                   png_read_push_finish_row(png_ptr);
                }
             }
+
             break;
          }
+
          case 3:
          {
             int i;
+
             for (i = 0; i < 4 && png_ptr->pass == 3; i++)
             {
                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
                png_read_push_finish_row(png_ptr);
             }
-            if (png_ptr->pass == 4) /* skip top two generated rows */
+
+            if (png_ptr->pass == 4) /* Skip top two generated rows */
             {
                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
                {
@@ -927,50 +1043,62 @@ png_push_process_row(png_structp png_ptr)
                   png_read_push_finish_row(png_ptr);
                }
             }
+
             break;
          }
+
          case 4:
          {
             int i;
+
             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
             {
                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
                png_read_push_finish_row(png_ptr);
             }
+
             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
             {
-               png_push_have_row(png_ptr, png_bytep_NULL);
+                  png_push_have_row(png_ptr, png_bytep_NULL);
                png_read_push_finish_row(png_ptr);
             }
-            if (png_ptr->pass == 6) /* pass 5 might be empty */
+
+            if (png_ptr->pass == 6) /* Pass 5 might be empty */
             {
-               png_push_have_row(png_ptr, png_bytep_NULL);
+                  png_push_have_row(png_ptr, png_bytep_NULL);
                png_read_push_finish_row(png_ptr);
             }
+
             break;
          }
+
          case 5:
          {
             int i;
+
             for (i = 0; i < 2 && png_ptr->pass == 5; i++)
             {
                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
                png_read_push_finish_row(png_ptr);
             }
-            if (png_ptr->pass == 6) /* skip top generated row */
+
+            if (png_ptr->pass == 6) /* Skip top generated row */
             {
-               png_push_have_row(png_ptr, png_bytep_NULL);
+                  png_push_have_row(png_ptr, png_bytep_NULL);
                png_read_push_finish_row(png_ptr);
             }
+
             break;
          }
          case 6:
          {
             png_push_have_row(png_ptr, png_ptr->row_buf + 1);
             png_read_push_finish_row(png_ptr);
+
             if (png_ptr->pass != 6)
                break;
-            png_push_have_row(png_ptr, png_bytep_NULL);
+
+                  png_push_have_row(png_ptr, png_bytep_NULL);
             png_read_push_finish_row(png_ptr);
          }
       }
@@ -987,18 +1115,18 @@ void /* PRIVATE */
 png_read_push_finish_row(png_structp png_ptr)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
-   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
-   /* start of interlace block */
+   /* Start of interlace block */
    PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
 
-   /* offset to next interlace block */
+   /* Offset to next interlace block */
    PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
 
-   /* start of interlace block in the y direction */
+   /* Start of interlace block in the y direction */
    PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
 
-   /* offset to next interlace block in the y direction */
+   /* Offset to next interlace block in the y direction */
    PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
 
    /* Height of interlace block.  This is not currently used - if you need
@@ -1011,6 +1139,7 @@ png_read_push_finish_row(png_structp png_ptr)
    if (png_ptr->row_number < png_ptr->num_rows)
       return;
 
+#ifdef PNG_READ_INTERLACING_SUPPORTED
    if (png_ptr->interlaced)
    {
       png_ptr->row_number = 0;
@@ -1026,6 +1155,7 @@ png_read_push_finish_row(png_structp png_ptr)
 
          if (png_ptr->pass > 7)
             png_ptr->pass--;
+
          if (png_ptr->pass >= 7)
             break;
 
@@ -1034,9 +1164,6 @@ png_read_push_finish_row(png_structp png_ptr)
             png_pass_start[png_ptr->pass]) /
             png_pass_inc[png_ptr->pass];
 
-         png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
-            png_ptr->iwidth) + 1;
-
          if (png_ptr->transformations & PNG_INTERLACE)
             break;
 
@@ -1047,486 +1174,7 @@ png_read_push_finish_row(png_structp png_ptr)
 
       } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
    }
-}
-
-#if defined(PNG_READ_tEXt_SUPPORTED)
-void /* PRIVATE */
-png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
-      {
-         png_error(png_ptr, "Out of place tEXt");
-         info_ptr = info_ptr; /* to quiet some compiler warnings */
-      }
-
-#ifdef PNG_MAX_MALLOC_64K
-   png_ptr->skip_length = 0;  /* This may not be necessary */
-
-   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
-   {
-      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
-      png_ptr->skip_length = length - (png_uint_32)65535L;
-      length = (png_uint_32)65535L;
-   }
-#endif
-
-   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
-         (png_uint_32)(length+1));
-   png_ptr->current_text[length] = '\0';
-   png_ptr->current_text_ptr = png_ptr->current_text;
-   png_ptr->current_text_size = (png_size_t)length;
-   png_ptr->current_text_left = (png_size_t)length;
-   png_ptr->process_mode = PNG_READ_tEXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
-{
-   if (png_ptr->buffer_size && png_ptr->current_text_left)
-   {
-      png_size_t text_size;
-
-      if (png_ptr->buffer_size < png_ptr->current_text_left)
-         text_size = png_ptr->buffer_size;
-      else
-         text_size = png_ptr->current_text_left;
-      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
-      png_ptr->current_text_left -= text_size;
-      png_ptr->current_text_ptr += text_size;
-   }
-   if (!(png_ptr->current_text_left))
-   {
-      png_textp text_ptr;
-      png_charp text;
-      png_charp key;
-      int ret;
-
-      if (png_ptr->buffer_size < 4)
-      {
-         png_push_save_buffer(png_ptr);
-         return;
-      }
-
-      png_push_crc_finish(png_ptr);
-
-#if defined(PNG_MAX_MALLOC_64K)
-      if (png_ptr->skip_length)
-         return;
-#endif
-
-      key = png_ptr->current_text;
-
-      for (text = key; *text; text++)
-         /* empty loop */ ;
-
-      if (text < key + png_ptr->current_text_size)
-         text++;
-
-      text_ptr = (png_textp)png_malloc(png_ptr,
-         (png_uint_32)png_sizeof(png_text));
-      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
-      text_ptr->key = key;
-#ifdef PNG_iTXt_SUPPORTED
-      text_ptr->lang = NULL;
-      text_ptr->lang_key = NULL;
-#endif
-      text_ptr->text = text;
-
-      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
-      png_free(png_ptr, key);
-      png_free(png_ptr, text_ptr);
-      png_ptr->current_text = NULL;
-
-      if (ret)
-        png_warning(png_ptr, "Insufficient memory to store text chunk.");
-   }
-}
-#endif
-
-#if defined(PNG_READ_zTXt_SUPPORTED)
-void /* PRIVATE */
-png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
-      {
-         png_error(png_ptr, "Out of place zTXt");
-         info_ptr = info_ptr; /* to quiet some compiler warnings */
-      }
-
-#ifdef PNG_MAX_MALLOC_64K
-   /* We can't handle zTXt chunks > 64K, since we don't have enough space
-    * to be able to store the uncompressed data.  Actually, the threshold
-    * is probably around 32K, but it isn't as definite as 64K is.
-    */
-   if (length > (png_uint_32)65535L)
-   {
-      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
-      png_push_crc_skip(png_ptr, length);
-      return;
-   }
-#endif
-
-   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
-       (png_uint_32)(length+1));
-   png_ptr->current_text[length] = '\0';
-   png_ptr->current_text_ptr = png_ptr->current_text;
-   png_ptr->current_text_size = (png_size_t)length;
-   png_ptr->current_text_left = (png_size_t)length;
-   png_ptr->process_mode = PNG_READ_zTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
-{
-   if (png_ptr->buffer_size && png_ptr->current_text_left)
-   {
-      png_size_t text_size;
-
-      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
-         text_size = png_ptr->buffer_size;
-      else
-         text_size = png_ptr->current_text_left;
-      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
-      png_ptr->current_text_left -= text_size;
-      png_ptr->current_text_ptr += text_size;
-   }
-   if (!(png_ptr->current_text_left))
-   {
-      png_textp text_ptr;
-      png_charp text;
-      png_charp key;
-      int ret;
-      png_size_t text_size, key_size;
-
-      if (png_ptr->buffer_size < 4)
-      {
-         png_push_save_buffer(png_ptr);
-         return;
-      }
-
-      png_push_crc_finish(png_ptr);
-
-      key = png_ptr->current_text;
-
-      for (text = key; *text; text++)
-         /* empty loop */ ;
-
-      /* zTXt can't have zero text */
-      if (text >= key + png_ptr->current_text_size)
-      {
-         png_ptr->current_text = NULL;
-         png_free(png_ptr, key);
-         return;
-      }
-
-      text++;
-
-      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
-      {
-         png_ptr->current_text = NULL;
-         png_free(png_ptr, key);
-         return;
-      }
-
-      text++;
-
-      png_ptr->zstream.next_in = (png_bytep )text;
-      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
-         (text - key));
-      png_ptr->zstream.next_out = png_ptr->zbuf;
-      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-
-      key_size = text - key;
-      text_size = 0;
-      text = NULL;
-      ret = Z_STREAM_END;
-
-      while (png_ptr->zstream.avail_in)
-      {
-         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-         if (ret != Z_OK && ret != Z_STREAM_END)
-         {
-            inflateReset(&png_ptr->zstream);
-            png_ptr->zstream.avail_in = 0;
-            png_ptr->current_text = NULL;
-            png_free(png_ptr, key);
-            png_free(png_ptr, text);
-            return;
-         }
-         if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
-         {
-            if (text == NULL)
-            {
-               text = (png_charp)png_malloc(png_ptr,
-                  (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
-                     + key_size + 1));
-               png_memcpy(text + key_size, png_ptr->zbuf,
-                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-               png_memcpy(text, key, key_size);
-               text_size = key_size + png_ptr->zbuf_size -
-                  png_ptr->zstream.avail_out;
-               *(text + text_size) = '\0';
-            }
-            else
-            {
-               png_charp tmp;
-
-               tmp = text;
-               text = (png_charp)png_malloc(png_ptr, text_size +
-                  (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
-                   + 1));
-               png_memcpy(text, tmp, text_size);
-               png_free(png_ptr, tmp);
-               png_memcpy(text + text_size, png_ptr->zbuf,
-                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
-               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
-               *(text + text_size) = '\0';
-            }
-            if (ret != Z_STREAM_END)
-            {
-               png_ptr->zstream.next_out = png_ptr->zbuf;
-               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-            }
-         }
-         else
-         {
-            break;
-         }
-
-         if (ret == Z_STREAM_END)
-            break;
-      }
-
-      inflateReset(&png_ptr->zstream);
-      png_ptr->zstream.avail_in = 0;
-
-      if (ret != Z_STREAM_END)
-      {
-         png_ptr->current_text = NULL;
-         png_free(png_ptr, key);
-         png_free(png_ptr, text);
-         return;
-      }
-
-      png_ptr->current_text = NULL;
-      png_free(png_ptr, key);
-      key = text;
-      text += key_size;
-
-      text_ptr = (png_textp)png_malloc(png_ptr,
-          (png_uint_32)png_sizeof(png_text));
-      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
-      text_ptr->key = key;
-#ifdef PNG_iTXt_SUPPORTED
-      text_ptr->lang = NULL;
-      text_ptr->lang_key = NULL;
-#endif
-      text_ptr->text = text;
-
-      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
-      png_free(png_ptr, key);
-      png_free(png_ptr, text_ptr);
-
-      if (ret)
-        png_warning(png_ptr, "Insufficient memory to store text chunk.");
-   }
-}
-#endif
-
-#if defined(PNG_READ_iTXt_SUPPORTED)
-void /* PRIVATE */
-png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
-      {
-         png_error(png_ptr, "Out of place iTXt");
-         info_ptr = info_ptr; /* to quiet some compiler warnings */
-      }
-
-#ifdef PNG_MAX_MALLOC_64K
-   png_ptr->skip_length = 0;  /* This may not be necessary */
-
-   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
-   {
-      png_warning(png_ptr, "iTXt chunk too large to fit in memory");
-      png_ptr->skip_length = length - (png_uint_32)65535L;
-      length = (png_uint_32)65535L;
-   }
-#endif
-
-   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
-         (png_uint_32)(length+1));
-   png_ptr->current_text[length] = '\0';
-   png_ptr->current_text_ptr = png_ptr->current_text;
-   png_ptr->current_text_size = (png_size_t)length;
-   png_ptr->current_text_left = (png_size_t)length;
-   png_ptr->process_mode = PNG_READ_iTXt_MODE;
-}
-
-void /* PRIVATE */
-png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
-{
-
-   if (png_ptr->buffer_size && png_ptr->current_text_left)
-   {
-      png_size_t text_size;
-
-      if (png_ptr->buffer_size < png_ptr->current_text_left)
-         text_size = png_ptr->buffer_size;
-      else
-         text_size = png_ptr->current_text_left;
-      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
-      png_ptr->current_text_left -= text_size;
-      png_ptr->current_text_ptr += text_size;
-   }
-   if (!(png_ptr->current_text_left))
-   {
-      png_textp text_ptr;
-      png_charp key;
-      int comp_flag;
-      png_charp lang;
-      png_charp lang_key;
-      png_charp text;
-      int ret;
-
-      if (png_ptr->buffer_size < 4)
-      {
-         png_push_save_buffer(png_ptr);
-         return;
-      }
-
-      png_push_crc_finish(png_ptr);
-
-#if defined(PNG_MAX_MALLOC_64K)
-      if (png_ptr->skip_length)
-         return;
-#endif
-
-      key = png_ptr->current_text;
-
-      for (lang = key; *lang; lang++)
-         /* empty loop */ ;
-
-      if (lang < key + png_ptr->current_text_size - 3)
-         lang++;
-
-      comp_flag = *lang++;
-      lang++;     /* skip comp_type, always zero */
-
-      for (lang_key = lang; *lang_key; lang_key++)
-         /* empty loop */ ;
-      lang_key++;        /* skip NUL separator */
-
-      text=lang_key;
-      if (lang_key < key + png_ptr->current_text_size - 1)
-      {
-        for (; *text; text++)
-           /* empty loop */ ;
-      }
-
-      if (text < key + png_ptr->current_text_size)
-         text++;
-
-      text_ptr = (png_textp)png_malloc(png_ptr,
-         (png_uint_32)png_sizeof(png_text));
-      text_ptr->compression = comp_flag + 2;
-      text_ptr->key = key;
-      text_ptr->lang = lang;
-      text_ptr->lang_key = lang_key;
-      text_ptr->text = text;
-      text_ptr->text_length = 0;
-      text_ptr->itxt_length = png_strlen(text);
-
-      ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
-      png_ptr->current_text = NULL;
-
-      png_free(png_ptr, text_ptr);
-      if (ret)
-        png_warning(png_ptr, "Insufficient memory to store iTXt chunk.");
-   }
-}
-#endif
-
-/* This function is called when we haven't found a handler for this
- * chunk.  If there isn't a problem with the chunk itself (ie a bad chunk
- * name or a critical chunk), the chunk is (currently) silently ignored.
- */
-void /* PRIVATE */
-png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
-   length)
-{
-   png_uint_32 skip=0;
-   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
-
-   if (!(png_ptr->chunk_name[0] & 0x20))
-   {
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-     if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
-          PNG_HANDLE_CHUNK_ALWAYS
-#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
-          && png_ptr->read_user_chunk_fn == NULL
-#endif
-        )
-#endif
-        png_chunk_error(png_ptr, "unknown critical chunk");
-
-     info_ptr = info_ptr; /* to quiet some compiler warnings */
-   }
-
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-   if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
-   {
-#ifdef PNG_MAX_MALLOC_64K
-      if (length > (png_uint_32)65535L)
-      {
-          png_warning(png_ptr, "unknown chunk too large to fit in memory");
-          skip = length - (png_uint_32)65535L;
-          length = (png_uint_32)65535L;
-      }
-#endif
-      png_memcpy((png_charp)png_ptr->unknown_chunk.name,
-                 (png_charp)png_ptr->chunk_name, 
-                 png_sizeof(png_ptr->unknown_chunk.name));
-      png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]='\0';
-
-      png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
-      png_ptr->unknown_chunk.size = (png_size_t)length;
-      png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
-#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
-      if(png_ptr->read_user_chunk_fn != NULL)
-      {
-         /* callback to user unknown chunk handler */
-         int ret;
-         ret = (*(png_ptr->read_user_chunk_fn))
-           (png_ptr, &png_ptr->unknown_chunk);
-         if (ret < 0)
-            png_chunk_error(png_ptr, "error in user chunk");
-         if (ret == 0)
-         {
-            if (!(png_ptr->chunk_name[0] & 0x20))
-               if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
-                    PNG_HANDLE_CHUNK_ALWAYS)
-                  png_chunk_error(png_ptr, "unknown critical chunk");
-            png_set_unknown_chunks(png_ptr, info_ptr,
-               &png_ptr->unknown_chunk, 1);
-         }
-      }
-#else
-      png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
-#endif
-      png_free(png_ptr, png_ptr->unknown_chunk.data);
-      png_ptr->unknown_chunk.data = NULL;
-   }
-   else
-#endif
-      skip=length;
-   png_push_crc_skip(png_ptr, skip);
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
 }
 
 void /* PRIVATE */
@@ -1559,7 +1207,10 @@ png_progressive_combine_row (png_structp png_ptr,
    PNG_CONST int FARDATA png_pass_dsp_mask[7] =
       {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
 #endif
-   if(png_ptr == NULL) return;
+
+   if (png_ptr == NULL)
+      return;
+
    if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */
       png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
 }
@@ -1569,7 +1220,9 @@ png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
    png_progressive_end_ptr end_fn)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
+
    png_ptr->info_fn = info_fn;
    png_ptr->row_fn = row_fn;
    png_ptr->end_fn = end_fn;
@@ -1580,7 +1233,9 @@ png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
 png_voidp PNGAPI
 png_get_progressive_ptr(png_structp png_ptr)
 {
-   if(png_ptr == NULL) return (NULL);
+   if (png_ptr == NULL)
+      return (NULL);
+
    return png_ptr->io_ptr;
 }
 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngread.c b/graf2d/asimage/src/libAfterImage/libpng/pngread.c
index 02efb0d..69ee464 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngread.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngread.c
@@ -1,20 +1,23 @@
 
 /* pngread.c - read a PNG file
  *
- * Last changed in libpng 1.2.20 September 7, 2007
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.48 [March 8, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * This file contains routines that an application calls directly to
  * read a PNG file or stream.
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
-#if defined(PNG_READ_SUPPORTED)
+#ifdef PNG_READ_SUPPORTED
 
 /* Create a PNG structure for reading, and allocate any memory needed. */
 png_structp PNGAPI
@@ -27,7 +30,9 @@ png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
       warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));
 }
 
-/* Alternate create PNG structure for reading, and allocate any memory needed. */
+/* Alternate create PNG structure for reading, and allocate any memory
+ * needed.
+ */
 png_structp PNGAPI
 png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
@@ -35,6 +40,9 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 {
 #endif /* PNG_USER_MEM_SUPPORTED */
 
+#ifdef PNG_SETJMP_SUPPORTED
+   volatile
+#endif
    png_structp png_ptr;
 
 #ifdef PNG_SETJMP_SUPPORTED
@@ -45,7 +53,8 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 
    int i;
 
-   png_debug(1, "in png_create_read_struct\n");
+   png_debug(1, "in png_create_read_struct");
+
 #ifdef PNG_USER_MEM_SUPPORTED
    png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
@@ -55,10 +64,12 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
    if (png_ptr == NULL)
       return (NULL);
 
-   /* added at libpng-1.2.6 */
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
-   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
+   /* Added at libpng-1.2.6 */
+#ifdef PNG_USER_LIMITS_SUPPORTED
+   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
+   /* Added at libpng-1.2.43 and 1.4.0 */
+   png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
@@ -69,7 +80,7 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 #endif
    {
       png_free(png_ptr, png_ptr->zbuf);
-      png_ptr->zbuf=NULL;
+      png_ptr->zbuf = NULL;
 #ifdef PNG_USER_MEM_SUPPORTED
       png_destroy_struct_2((png_voidp)png_ptr,
          (png_free_ptr)free_fn, (png_voidp)mem_ptr);
@@ -79,9 +90,9 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
       return (NULL);
    }
 #ifdef USE_FAR_KEYWORD
-   png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
-#endif
+   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
 #endif
+#endif /* PNG_SETJMP_SUPPORTED */
 
 #ifdef PNG_USER_MEM_SUPPORTED
    png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
@@ -89,47 +100,53 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 
    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
 
-   i=0;
-   do
-   {
-     if(user_png_ver[i] != png_libpng_ver[i])
-        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-   } while (png_libpng_ver[i++]);
-
-   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+   if (user_png_ver)
    {
-     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
-      * we must recompile any applications that use any older library version.
-      * For versions after libpng 1.0, we will be compatible, so we need
-      * only check the first digit.
-      */
-     if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
-         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
-         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
-     {
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
-        char msg[80];
-        if (user_png_ver)
-        {
-          png_snprintf(msg, 80,
-             "Application was compiled with png.h from libpng-%.20s",
-             user_png_ver);
-          png_warning(png_ptr, msg);
-        }
-        png_snprintf(msg, 80,
+      i = 0;
+      do
+      {
+         if (user_png_ver[i] != png_libpng_ver[i])
+            png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+      } while (png_libpng_ver[i++]);
+    }
+    else
+         png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+
+
+    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+    {
+       /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+       * we must recompile any applications that use any older library version.
+       * For versions after libpng 1.0, we will be compatible, so we need
+       * only check the first digit.
+       */
+      if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+      {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+         char msg[80];
+         if (user_png_ver)
+         {
+           png_snprintf(msg, 80,
+              "Application was compiled with png.h from libpng-%.20s",
+              user_png_ver);
+           png_warning(png_ptr, msg);
+         }
+         png_snprintf(msg, 80,
              "Application  is  running with png.c from libpng-%.20s",
-           png_libpng_ver);
-        png_warning(png_ptr, msg);
+             png_libpng_ver);
+         png_warning(png_ptr, msg);
 #endif
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-        png_ptr->flags=0;
+         png_ptr->flags = 0;
 #endif
-        png_error(png_ptr,
-           "Incompatible libpng version in application and library");
-     }
+         png_error(png_ptr,
+            "Incompatible libpng version in application and library");
+      }
    }
 
-   /* initialize zbuf - compression buffer */
+   /* Initialize zbuf - compression buffer */
    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
      (png_uint_32)png_ptr->zbuf_size);
@@ -137,14 +154,17 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
    png_ptr->zstream.zfree = png_zfree;
    png_ptr->zstream.opaque = (voidpf)png_ptr;
 
-   switch (inflateInit(&png_ptr->zstream))
-   {
-     case Z_OK: /* Do nothing */ break;
-     case Z_MEM_ERROR:
-     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
-     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
-     default: png_error(png_ptr, "Unknown zlib error");
-   }
+      switch (inflateInit(&png_ptr->zstream))
+      {
+         case Z_OK: /* Do nothing */ break;
+         case Z_MEM_ERROR:
+         case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error");
+            break;
+         case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error");
+            break;
+         default: png_error(png_ptr, "Unknown zlib error");
+      }
+
 
    png_ptr->zstream.next_out = png_ptr->zbuf;
    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
@@ -152,25 +172,27 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
    png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);
 
 #ifdef PNG_SETJMP_SUPPORTED
-/* Applications that neglect to set up their own setjmp() and then encounter
-   a png_error() will longjmp here.  Since the jmpbuf is then meaningless we
-   abort instead of returning. */
+/* Applications that neglect to set up their own setjmp() and then
+   encounter a png_error() will longjmp here.  Since the jmpbuf is
+   then meaningless we abort instead of returning. */
 #ifdef USE_FAR_KEYWORD
    if (setjmp(jmpbuf))
-      PNG_ABORT();
-   png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
+       PNG_ABORT();
+   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
 #else
    if (setjmp(png_ptr->jmpbuf))
-      PNG_ABORT();
-#endif
+       PNG_ABORT();
 #endif
+#endif /* PNG_SETJMP_SUPPORTED */
+
    return (png_ptr);
 }
 
 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)
 /* Initialize PNG structure for reading, and allocate any memory needed.
-   This interface is deprecated in favour of the png_create_read_struct(),
-   and it will disappear as of libpng-1.3.0. */
+ * This interface is deprecated in favour of the png_create_read_struct(),
+ * and it will disappear as of libpng-1.3.0.
+ */
 #undef png_read_init
 void PNGAPI
 png_read_init(png_structp png_ptr)
@@ -184,13 +206,14 @@ png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,
    png_size_t png_struct_size, png_size_t png_info_size)
 {
    /* We only come here via pre-1.0.12-compiled applications */
-   if(png_ptr == NULL) return;
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
-   if(png_sizeof(png_struct) > png_struct_size ||
+   if (png_ptr == NULL)
+      return;
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+   if (png_sizeof(png_struct) > png_struct_size ||
       png_sizeof(png_info) > png_info_size)
    {
       char msg[80];
-      png_ptr->warning_fn=NULL;
+      png_ptr->warning_fn = NULL;
       if (user_png_ver)
       {
         png_snprintf(msg, 80,
@@ -204,24 +227,26 @@ png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,
       png_warning(png_ptr, msg);
    }
 #endif
-   if(png_sizeof(png_struct) > png_struct_size)
-     {
-       png_ptr->error_fn=NULL;
+   if (png_sizeof(png_struct) > png_struct_size)
+   {
+      png_ptr->error_fn = NULL;
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-       png_ptr->flags=0;
-#endif
-       png_error(png_ptr,
-       "The png struct allocated by the application for reading is too small.");
-     }
-   if(png_sizeof(png_info) > png_info_size)
-     {
-       png_ptr->error_fn=NULL;
+      png_ptr->flags = 0;
+#endif
+      png_error(png_ptr,
+      "The png struct allocated by the application for reading is"
+      " too small.");
+   }
+   if (png_sizeof(png_info) > png_info_size)
+   {
+      png_ptr->error_fn = NULL;
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-       png_ptr->flags=0;
+      png_ptr->flags = 0;
 #endif
-       png_error(png_ptr,
-         "The info struct allocated by application for reading is too small.");
-     }
+      png_error(png_ptr,
+        "The info struct allocated by application for reading is"
+        " too small.");
+   }
    png_read_init_3(&png_ptr, user_png_ver, png_struct_size);
 }
 #endif /* PNG_1_0_X || PNG_1_2_X */
@@ -234,57 +259,60 @@ png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
    jmp_buf tmp_jmp;  /* to save current jump buffer */
 #endif
 
-   int i=0;
+   int i = 0;
 
    png_structp png_ptr=*ptr_ptr;
 
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
 
    do
    {
-     if(user_png_ver[i] != png_libpng_ver[i])
-     {
+      if (user_png_ver[i] != png_libpng_ver[i])
+      {
 #ifdef PNG_LEGACY_SUPPORTED
-       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
 #else
-       png_ptr->warning_fn=NULL;
-       png_warning(png_ptr,
-        "Application uses deprecated png_read_init() and should be recompiled.");
-       break;
+        png_ptr->warning_fn = NULL;
+        png_warning(png_ptr,
+         "Application uses deprecated png_read_init() and should be"
+         " recompiled.");
+        break;
 #endif
-     }
+      }
    } while (png_libpng_ver[i++]);
 
-   png_debug(1, "in png_read_init_3\n");
+   png_debug(1, "in png_read_init_3");
 
 #ifdef PNG_SETJMP_SUPPORTED
-   /* save jump buffer and error functions */
-   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
+   /* Save jump buffer and error functions */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
 #endif
 
-   if(png_sizeof(png_struct) > png_struct_size)
-     {
-       png_destroy_struct(png_ptr);
-       *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-       png_ptr = *ptr_ptr;
-     }
+   if (png_sizeof(png_struct) > png_struct_size)
+   {
+      png_destroy_struct(png_ptr);
+      *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+      png_ptr = *ptr_ptr;
+   }
 
-   /* reset all variables to 0 */
-   png_memset(png_ptr, 0, png_sizeof (png_struct));
+   /* Reset all variables to 0 */
+   png_memset(png_ptr, 0, png_sizeof(png_struct));
 
 #ifdef PNG_SETJMP_SUPPORTED
-   /* restore jump buffer */
-   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
+   /* Restore jump buffer */
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
 #endif
 
-   /* added at libpng-1.2.6 */
+   /* Added at libpng-1.2.6 */
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
-   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
+   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
 #endif
 
-   /* initialize zbuf - compression buffer */
+   /* Initialize zbuf - compression buffer */
    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zstream.zalloc = png_zalloc;
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
      (png_uint_32)png_ptr->zbuf_size);
    png_ptr->zstream.zalloc = png_zalloc;
@@ -293,11 +321,11 @@ png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
 
    switch (inflateInit(&png_ptr->zstream))
    {
-     case Z_OK: /* Do nothing */ break;
-     case Z_MEM_ERROR:
-     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
-     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
-     default: png_error(png_ptr, "Unknown zlib error");
+      case Z_OK: /* Do nothing */ break;
+      case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
+      case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error");
+          break;
+      default: png_error(png_ptr, "Unknown zlib error");
    }
 
    png_ptr->zstream.next_out = png_ptr->zbuf;
@@ -306,7 +334,7 @@ png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
    png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);
 }
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the information before the actual image data.  This has been
  * changed in v0.90 to allow reading a file that already has the magic
  * bytes read from the stream.  You can tell libpng how many bytes have
@@ -318,8 +346,11 @@ png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
 void PNGAPI
 png_read_info(png_structp png_ptr, png_infop info_ptr)
 {
-   if(png_ptr == NULL) return;
-   png_debug(1, "in png_read_info\n");
+   png_debug(1, "in png_read_info");
+ 
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+ 
    /* If we haven't checked all of the PNG signature bytes, do so now. */
    if (png_ptr->sig_bytes < 8)
    {
@@ -341,97 +372,88 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
          png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
    }
 
-   for(;;)
+   for (;;)
    {
 #ifdef PNG_USE_LOCAL_ARRAYS
       PNG_CONST PNG_IHDR;
       PNG_CONST PNG_IDAT;
       PNG_CONST PNG_IEND;
       PNG_CONST PNG_PLTE;
-#if defined(PNG_READ_bKGD_SUPPORTED)
+#ifdef PNG_READ_bKGD_SUPPORTED
       PNG_CONST PNG_bKGD;
 #endif
-#if defined(PNG_READ_cHRM_SUPPORTED)
+#ifdef PNG_READ_cHRM_SUPPORTED
       PNG_CONST PNG_cHRM;
 #endif
-#if defined(PNG_READ_gAMA_SUPPORTED)
+#ifdef PNG_READ_gAMA_SUPPORTED
       PNG_CONST PNG_gAMA;
 #endif
-#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_READ_hIST_SUPPORTED
       PNG_CONST PNG_hIST;
 #endif
-#if defined(PNG_READ_iCCP_SUPPORTED)
+#ifdef PNG_READ_iCCP_SUPPORTED
       PNG_CONST PNG_iCCP;
 #endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
+#ifdef PNG_READ_iTXt_SUPPORTED
       PNG_CONST PNG_iTXt;
 #endif
-#if defined(PNG_READ_oFFs_SUPPORTED)
+#ifdef PNG_READ_oFFs_SUPPORTED
       PNG_CONST PNG_oFFs;
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#ifdef PNG_READ_pCAL_SUPPORTED
       PNG_CONST PNG_pCAL;
 #endif
-#if defined(PNG_READ_pHYs_SUPPORTED)
+#ifdef PNG_READ_pHYs_SUPPORTED
       PNG_CONST PNG_pHYs;
 #endif
-#if defined(PNG_READ_sBIT_SUPPORTED)
+#ifdef PNG_READ_sBIT_SUPPORTED
       PNG_CONST PNG_sBIT;
 #endif
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#ifdef PNG_READ_sCAL_SUPPORTED
       PNG_CONST PNG_sCAL;
 #endif
-#if defined(PNG_READ_sPLT_SUPPORTED)
+#ifdef PNG_READ_sPLT_SUPPORTED
       PNG_CONST PNG_sPLT;
 #endif
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
       PNG_CONST PNG_sRGB;
 #endif
-#if defined(PNG_READ_tEXt_SUPPORTED)
+#ifdef PNG_READ_tEXt_SUPPORTED
       PNG_CONST PNG_tEXt;
 #endif
-#if defined(PNG_READ_tIME_SUPPORTED)
+#ifdef PNG_READ_tIME_SUPPORTED
       PNG_CONST PNG_tIME;
 #endif
-#if defined(PNG_READ_tRNS_SUPPORTED)
+#ifdef PNG_READ_tRNS_SUPPORTED
       PNG_CONST PNG_tRNS;
 #endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
+#ifdef PNG_READ_zTXt_SUPPORTED
       PNG_CONST PNG_zTXt;
 #endif
 #endif /* PNG_USE_LOCAL_ARRAYS */
-      png_byte chunk_length[4];
-      png_uint_32 length;
-
-      png_read_data(png_ptr, chunk_length, 4);
-      length = png_get_uint_31(png_ptr,chunk_length);
-
-      png_reset_crc(png_ptr);
-      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
-
-      png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name,
-         length);
+      png_uint_32 length = png_read_chunk_header(png_ptr);
+      PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
 
       /* This should be a binary subdivision search or a hash for
        * matching the chunk name rather than a linear search.
        */
-      if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
-        if(png_ptr->mode & PNG_AFTER_IDAT)
+      if (!png_memcmp(chunk_name, png_IDAT, 4))
+        if (png_ptr->mode & PNG_AFTER_IDAT)
           png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
 
-      if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
+      if (!png_memcmp(chunk_name, png_IHDR, 4))
          png_handle_IHDR(png_ptr, info_ptr, length);
-      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+      else if (!png_memcmp(chunk_name, png_IEND, 4))
          png_handle_IEND(png_ptr, info_ptr, length);
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-      else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
+      else if (png_handle_as_unknown(png_ptr, chunk_name))
       {
-         if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+         if (!png_memcmp(chunk_name, png_IDAT, 4))
             png_ptr->mode |= PNG_HAVE_IDAT;
          png_handle_unknown(png_ptr, info_ptr, length);
-         if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+         if (!png_memcmp(chunk_name, png_PLTE, 4))
             png_ptr->mode |= PNG_HAVE_PLTE;
-         else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+         else if (!png_memcmp(chunk_name, png_IDAT, 4))
          {
             if (!(png_ptr->mode & PNG_HAVE_IHDR))
                png_error(png_ptr, "Missing IHDR before IDAT");
@@ -442,9 +464,9 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
          }
       }
 #endif
-      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+      else if (!png_memcmp(chunk_name, png_PLTE, 4))
          png_handle_PLTE(png_ptr, info_ptr, length);
-      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+      else if (!png_memcmp(chunk_name, png_IDAT, 4))
       {
          if (!(png_ptr->mode & PNG_HAVE_IHDR))
             png_error(png_ptr, "Missing IHDR before IDAT");
@@ -456,95 +478,98 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
          png_ptr->mode |= PNG_HAVE_IDAT;
          break;
       }
-#if defined(PNG_READ_bKGD_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
+#ifdef PNG_READ_bKGD_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_bKGD, 4))
          png_handle_bKGD(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_cHRM_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+#ifdef PNG_READ_cHRM_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_cHRM, 4))
          png_handle_cHRM(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_gAMA_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+#ifdef PNG_READ_gAMA_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_gAMA, 4))
          png_handle_gAMA(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_hIST_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+#ifdef PNG_READ_hIST_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_hIST, 4))
          png_handle_hIST(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_oFFs_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+#ifdef PNG_READ_oFFs_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_oFFs, 4))
          png_handle_oFFs(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+#ifdef PNG_READ_pCAL_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_pCAL, 4))
          png_handle_pCAL(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sCAL_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+#ifdef PNG_READ_sCAL_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sCAL, 4))
          png_handle_sCAL(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_pHYs_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+#ifdef PNG_READ_pHYs_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_pHYs, 4))
          png_handle_pHYs(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sBIT_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+#ifdef PNG_READ_sBIT_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sBIT, 4))
          png_handle_sBIT(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sRGB_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+#ifdef PNG_READ_sRGB_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sRGB, 4))
          png_handle_sRGB(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_iCCP_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+#ifdef PNG_READ_iCCP_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_iCCP, 4))
          png_handle_iCCP(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sPLT_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+#ifdef PNG_READ_sPLT_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sPLT, 4))
          png_handle_sPLT(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_tEXt_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+#ifdef PNG_READ_tEXt_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_tEXt, 4))
          png_handle_tEXt(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_tIME_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+#ifdef PNG_READ_tIME_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_tIME, 4))
          png_handle_tIME(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_tRNS_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+#ifdef PNG_READ_tRNS_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_tRNS, 4))
          png_handle_tRNS(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+#ifdef PNG_READ_zTXt_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_zTXt, 4))
          png_handle_zTXt(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+#ifdef PNG_READ_iTXt_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_iTXt, 4))
          png_handle_iTXt(png_ptr, info_ptr, length);
 #endif
       else
          png_handle_unknown(png_ptr, info_ptr, length);
    }
 }
-#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
-/* optional call to update the users info_ptr structure */
+/* Optional call to update the users info_ptr structure */
 void PNGAPI
 png_read_update_info(png_structp png_ptr, png_infop info_ptr)
 {
-   png_debug(1, "in png_read_update_info\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_read_update_info");
+ 
+   if (png_ptr == NULL)
+      return;
    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
       png_read_start_row(png_ptr);
    else
       png_warning(png_ptr,
       "Ignoring extra png_read_update_info() call; row buffer not reallocated");
+
    png_read_transform_info(png_ptr, info_ptr);
 }
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Initialize palette, background, etc, after transformations
  * are set, but before any reading takes place.  This allows
  * the user to obtain a gamma-corrected palette, for example.
@@ -553,32 +578,36 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr)
 void PNGAPI
 png_start_read_image(png_structp png_ptr)
 {
-   png_debug(1, "in png_start_read_image\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_start_read_image");
+ 
+   if (png_ptr == NULL)
+      return;
    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
       png_read_start_row(png_ptr);
 }
-#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 void PNGAPI
 png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
 {
-#ifdef PNG_USE_LOCAL_ARRAYS
    PNG_CONST PNG_IDAT;
    PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,
-     0xff};
+      0xff};
    PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
-#endif
    int ret;
-   if(png_ptr == NULL) return;
-   png_debug2(1, "in png_read_row (row %lu, pass %d)\n",
+ 
+   if (png_ptr == NULL)
+      return;
+ 
+   png_debug2(1, "in png_read_row (row %lu, pass %d)",
       png_ptr->row_number, png_ptr->pass);
+
    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
       png_read_start_row(png_ptr);
    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
    {
-   /* check for transforms that have been set but were defined out */
+   /* Check for transforms that have been set but were defined out */
 #if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
    if (png_ptr->transformations & PNG_INVERT_MONO)
       png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
@@ -587,7 +616,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
    if (png_ptr->transformations & PNG_FILLER)
       png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
 #endif
-#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
+    !defined(PNG_READ_PACKSWAP_SUPPORTED)
    if (png_ptr->transformations & PNG_PACKSWAP)
       png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
 #endif
@@ -609,8 +639,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
 #endif
    }
 
-#if defined(PNG_READ_INTERLACING_SUPPORTED)
-   /* if interlaced and we do not need a new row, combine row and return */
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   /* If interlaced and we do not need a new row, combine row and return */
    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
    {
       switch (png_ptr->pass)
@@ -690,22 +720,18 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
       png_error(png_ptr, "Invalid attempt to read row data");
 
    png_ptr->zstream.next_out = png_ptr->row_buf;
-   png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+   png_ptr->zstream.avail_out =
+       (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
+       png_ptr->iwidth) + 1);
    do
    {
       if (!(png_ptr->zstream.avail_in))
       {
          while (!png_ptr->idat_size)
          {
-            png_byte chunk_length[4];
-
             png_crc_finish(png_ptr, 0);
 
-            png_read_data(png_ptr, chunk_length, 4);
-            png_ptr->idat_size = png_get_uint_31(png_ptr,chunk_length);
-
-            png_reset_crc(png_ptr);
-            png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+            png_ptr->idat_size = png_read_chunk_header(png_ptr);
             if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
                png_error(png_ptr, "Not enough image data");
          }
@@ -741,7 +767,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
    png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
        png_ptr->row_info.width);
 
-   if(png_ptr->row_buf[0])
+   if (png_ptr->row_buf[0])
    png_read_filter_row(png_ptr, &(png_ptr->row_info),
       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
       (int)(png_ptr->row_buf[0]));
@@ -749,8 +775,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
    png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
       png_ptr->rowbytes + 1);
 
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
    {
       /* Intrapixel differencing */
@@ -762,16 +788,16 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
    if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
       png_do_read_transformations(png_ptr);
 
-#if defined(PNG_READ_INTERLACING_SUPPORTED)
-   /* blow up interlaced rows to full size */
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   /* Blow up interlaced rows to full size */
    if (png_ptr->interlaced &&
       (png_ptr->transformations & PNG_INTERLACE))
    {
       if (png_ptr->pass < 6)
-/*       old interface (pre-1.0.9):
-         png_do_read_interlace(&(png_ptr->row_info),
-            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
- */
+         /* Old interface (pre-1.0.9):
+          * png_do_read_interlace(&(png_ptr->row_info),
+          *    png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+          */
          png_do_read_interlace(png_ptr);
 
       if (dsp_row != NULL)
@@ -794,9 +820,9 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
    if (png_ptr->read_row_fn != NULL)
       (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
 }
-#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read one or more rows of image data.  If the image is interlaced,
  * and png_set_interlace_handling() has been called, the rows need to
  * contain the contents of the rows from the previous pass.  If the
@@ -829,8 +855,10 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
    png_bytepp rp;
    png_bytepp dp;
 
-   png_debug(1, "in png_read_rows\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_read_rows");
+ 
+   if (png_ptr == NULL)
+      return;
    rp = row;
    dp = display_row;
    if (rp != NULL && dp != NULL)
@@ -841,14 +869,14 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
 
          png_read_row(png_ptr, rptr, dptr);
       }
-   else if(rp != NULL)
+   else if (rp != NULL)
       for (i = 0; i < num_rows; i++)
       {
          png_bytep rptr = *rp;
          png_read_row(png_ptr, rptr, png_bytep_NULL);
          rp++;
       }
-   else if(dp != NULL)
+   else if (dp != NULL)
       for (i = 0; i < num_rows; i++)
       {
          png_bytep dptr = *dp;
@@ -856,9 +884,9 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
          dp++;
       }
 }
-#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the entire image.  If the image has an alpha channel or a tRNS
  * chunk, and you have called png_handle_alpha()[*], you will need to
  * initialize the image to the current image that PNG will be overlaying.
@@ -874,12 +902,14 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
 void PNGAPI
 png_read_image(png_structp png_ptr, png_bytepp image)
 {
-   png_uint_32 i,image_height;
+   png_uint_32 i, image_height;
    int pass, j;
    png_bytepp rp;
 
-   png_debug(1, "in png_read_image\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_read_image");
+ 
+   if (png_ptr == NULL)
+      return;
 
 #ifdef PNG_READ_INTERLACING_SUPPORTED
    pass = png_set_interlace_handling(png_ptr);
@@ -904,9 +934,9 @@ png_read_image(png_structp png_ptr, png_bytepp image)
       }
    }
 }
-#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the end of the PNG file.  Will not read past the end of the
  * file, will verify the end is accurate, and will read any comments
  * or time information at the end of the file, if info is not NULL.
@@ -914,11 +944,10 @@ png_read_image(png_structp png_ptr, png_bytepp image)
 void PNGAPI
 png_read_end(png_structp png_ptr, png_infop info_ptr)
 {
-   png_byte chunk_length[4];
-   png_uint_32 length;
-
-   png_debug(1, "in png_read_end\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_read_end");
+ 
+   if (png_ptr == NULL)
+      return;
    png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
 
    do
@@ -928,85 +957,79 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
       PNG_CONST PNG_IDAT;
       PNG_CONST PNG_IEND;
       PNG_CONST PNG_PLTE;
-#if defined(PNG_READ_bKGD_SUPPORTED)
+#ifdef PNG_READ_bKGD_SUPPORTED
       PNG_CONST PNG_bKGD;
 #endif
-#if defined(PNG_READ_cHRM_SUPPORTED)
+#ifdef PNG_READ_cHRM_SUPPORTED
       PNG_CONST PNG_cHRM;
 #endif
-#if defined(PNG_READ_gAMA_SUPPORTED)
+#ifdef PNG_READ_gAMA_SUPPORTED
       PNG_CONST PNG_gAMA;
 #endif
-#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_READ_hIST_SUPPORTED
       PNG_CONST PNG_hIST;
 #endif
-#if defined(PNG_READ_iCCP_SUPPORTED)
+#ifdef PNG_READ_iCCP_SUPPORTED
       PNG_CONST PNG_iCCP;
 #endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
+#ifdef PNG_READ_iTXt_SUPPORTED
       PNG_CONST PNG_iTXt;
 #endif
-#if defined(PNG_READ_oFFs_SUPPORTED)
+#ifdef PNG_READ_oFFs_SUPPORTED
       PNG_CONST PNG_oFFs;
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
+#ifdef PNG_READ_pCAL_SUPPORTED
       PNG_CONST PNG_pCAL;
 #endif
-#if defined(PNG_READ_pHYs_SUPPORTED)
+#ifdef PNG_READ_pHYs_SUPPORTED
       PNG_CONST PNG_pHYs;
 #endif
-#if defined(PNG_READ_sBIT_SUPPORTED)
+#ifdef PNG_READ_sBIT_SUPPORTED
       PNG_CONST PNG_sBIT;
 #endif
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#ifdef PNG_READ_sCAL_SUPPORTED
       PNG_CONST PNG_sCAL;
 #endif
-#if defined(PNG_READ_sPLT_SUPPORTED)
+#ifdef PNG_READ_sPLT_SUPPORTED
       PNG_CONST PNG_sPLT;
 #endif
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
       PNG_CONST PNG_sRGB;
 #endif
-#if defined(PNG_READ_tEXt_SUPPORTED)
+#ifdef PNG_READ_tEXt_SUPPORTED
       PNG_CONST PNG_tEXt;
 #endif
-#if defined(PNG_READ_tIME_SUPPORTED)
+#ifdef PNG_READ_tIME_SUPPORTED
       PNG_CONST PNG_tIME;
 #endif
-#if defined(PNG_READ_tRNS_SUPPORTED)
+#ifdef PNG_READ_tRNS_SUPPORTED
       PNG_CONST PNG_tRNS;
 #endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
+#ifdef PNG_READ_zTXt_SUPPORTED
       PNG_CONST PNG_zTXt;
 #endif
 #endif /* PNG_USE_LOCAL_ARRAYS */
+      png_uint_32 length = png_read_chunk_header(png_ptr);
+      PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
 
-      png_read_data(png_ptr, chunk_length, 4);
-      length = png_get_uint_31(png_ptr,chunk_length);
-
-      png_reset_crc(png_ptr);
-      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
-
-      png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
-
-      if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
+      if (!png_memcmp(chunk_name, png_IHDR, 4))
          png_handle_IHDR(png_ptr, info_ptr, length);
-      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+      else if (!png_memcmp(chunk_name, png_IEND, 4))
          png_handle_IEND(png_ptr, info_ptr, length);
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-      else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
+      else if (png_handle_as_unknown(png_ptr, chunk_name))
       {
-         if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+         if (!png_memcmp(chunk_name, png_IDAT, 4))
          {
             if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
                png_error(png_ptr, "Too many IDAT's found");
          }
          png_handle_unknown(png_ptr, info_ptr, length);
-         if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+         if (!png_memcmp(chunk_name, png_PLTE, 4))
             png_ptr->mode |= PNG_HAVE_PLTE;
       }
 #endif
-      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+      else if (!png_memcmp(chunk_name, png_IDAT, 4))
       {
          /* Zero length IDATs are legal after the last IDAT has been
           * read, but not after other chunks have been read.
@@ -1015,83 +1038,83 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
             png_error(png_ptr, "Too many IDAT's found");
          png_crc_finish(png_ptr, length);
       }
-      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+      else if (!png_memcmp(chunk_name, png_PLTE, 4))
          png_handle_PLTE(png_ptr, info_ptr, length);
-#if defined(PNG_READ_bKGD_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
+#ifdef PNG_READ_bKGD_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_bKGD, 4))
          png_handle_bKGD(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_cHRM_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+#ifdef PNG_READ_cHRM_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_cHRM, 4))
          png_handle_cHRM(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_gAMA_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+#ifdef PNG_READ_gAMA_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_gAMA, 4))
          png_handle_gAMA(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_hIST_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+#ifdef PNG_READ_hIST_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_hIST, 4))
          png_handle_hIST(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_oFFs_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+#ifdef PNG_READ_oFFs_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_oFFs, 4))
          png_handle_oFFs(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_pCAL_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+#ifdef PNG_READ_pCAL_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_pCAL, 4))
          png_handle_pCAL(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sCAL_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+#ifdef PNG_READ_sCAL_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sCAL, 4))
          png_handle_sCAL(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_pHYs_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+#ifdef PNG_READ_pHYs_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_pHYs, 4))
          png_handle_pHYs(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sBIT_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+#ifdef PNG_READ_sBIT_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sBIT, 4))
          png_handle_sBIT(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sRGB_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+#ifdef PNG_READ_sRGB_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sRGB, 4))
          png_handle_sRGB(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_iCCP_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+#ifdef PNG_READ_iCCP_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_iCCP, 4))
          png_handle_iCCP(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_sPLT_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+#ifdef PNG_READ_sPLT_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_sPLT, 4))
          png_handle_sPLT(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_tEXt_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+#ifdef PNG_READ_tEXt_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_tEXt, 4))
          png_handle_tEXt(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_tIME_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+#ifdef PNG_READ_tIME_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_tIME, 4))
          png_handle_tIME(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_tRNS_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+#ifdef PNG_READ_tRNS_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_tRNS, 4))
          png_handle_tRNS(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_zTXt_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+#ifdef PNG_READ_zTXt_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_zTXt, 4))
          png_handle_zTXt(png_ptr, info_ptr, length);
 #endif
-#if defined(PNG_READ_iTXt_SUPPORTED)
-      else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+#ifdef PNG_READ_iTXt_SUPPORTED
+      else if (!png_memcmp(chunk_name, png_iTXt, 4))
          png_handle_iTXt(png_ptr, info_ptr, length);
 #endif
       else
          png_handle_unknown(png_ptr, info_ptr, length);
    } while (!(png_ptr->mode & PNG_HAVE_IEND));
 }
-#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
-/* free all memory used by the read */
+/* Free all memory used by the read */
 void PNGAPI
 png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
    png_infopp end_info_ptr_ptr)
@@ -1099,13 +1122,21 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL, end_info_ptr = NULL;
 #ifdef PNG_USER_MEM_SUPPORTED
-   png_free_ptr free_fn;
-   png_voidp mem_ptr;
+   png_free_ptr free_fn = NULL;
+   png_voidp mem_ptr = NULL;
 #endif
 
-   png_debug(1, "in png_destroy_read_struct\n");
+   png_debug(1, "in png_destroy_read_struct");
+ 
    if (png_ptr_ptr != NULL)
       png_ptr = *png_ptr_ptr;
+   if (png_ptr == NULL)
+      return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+   mem_ptr = png_ptr->mem_ptr;
+#endif
 
    if (info_ptr_ptr != NULL)
       info_ptr = *info_ptr_ptr;
@@ -1113,16 +1144,11 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
    if (end_info_ptr_ptr != NULL)
       end_info_ptr = *end_info_ptr_ptr;
 
-#ifdef PNG_USER_MEM_SUPPORTED
-   free_fn = png_ptr->free_fn;
-   mem_ptr = png_ptr->mem_ptr;
-#endif
-
    png_read_destroy(png_ptr, info_ptr, end_info_ptr);
 
    if (info_ptr != NULL)
    {
-#if defined(PNG_TEXT_SUPPORTED)
+#ifdef PNG_TEXT_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
 #endif
 
@@ -1137,7 +1163,7 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
 
    if (end_info_ptr != NULL)
    {
-#if defined(PNG_READ_TEXT_SUPPORTED)
+#ifdef PNG_READ_TEXT_SUPPORTED
       png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
 #endif
 #ifdef PNG_USER_MEM_SUPPORTED
@@ -1161,9 +1187,10 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
    }
 }
 
-/* free all memory used by the read (old method) */
+/* Free all memory used by the read (old method) */
 void /* PRIVATE */
-png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
+png_read_destroy(png_structp png_ptr, png_infop info_ptr,
+    png_infop end_info_ptr)
 {
 #ifdef PNG_SETJMP_SUPPORTED
    jmp_buf tmp_jmp;
@@ -1175,7 +1202,8 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    png_free_ptr free_fn;
 #endif
 
-   png_debug(1, "in png_read_destroy\n");
+   png_debug(1, "in png_read_destroy");
+ 
    if (info_ptr != NULL)
       png_info_destroy(png_ptr, info_ptr);
 
@@ -1185,14 +1213,15 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    png_free(png_ptr, png_ptr->zbuf);
    png_free(png_ptr, png_ptr->big_row_buf);
    png_free(png_ptr, png_ptr->prev_row);
-#if defined(PNG_READ_DITHER_SUPPORTED)
+   png_free(png_ptr, png_ptr->chunkdata);
+#ifdef PNG_READ_DITHER_SUPPORTED
    png_free(png_ptr, png_ptr->palette_lookup);
    png_free(png_ptr, png_ptr->dither_index);
 #endif
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
    png_free(png_ptr, png_ptr->gamma_table);
 #endif
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    png_free(png_ptr, png_ptr->gamma_from_1);
    png_free(png_ptr, png_ptr->gamma_to_1);
 #endif
@@ -1217,7 +1246,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
 #endif
 #endif
-#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_READ_hIST_SUPPORTED
 #ifdef PNG_FREE_ME_SUPPORTED
    if (png_ptr->free_me & PNG_FREE_HIST)
       png_free(png_ptr, png_ptr->hist);
@@ -1228,7 +1257,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
 #endif
 #endif
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
    if (png_ptr->gamma_16_table != NULL)
    {
       int i;
@@ -1239,7 +1268,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
       }
    png_free(png_ptr, png_ptr->gamma_16_table);
    }
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    if (png_ptr->gamma_16_from_1 != NULL)
    {
       int i;
@@ -1262,7 +1291,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    }
 #endif
 #endif
-#if defined(PNG_TIME_RFC1123_SUPPORTED)
+#ifdef PNG_TIME_RFC1123_SUPPORTED
    png_free(png_ptr, png_ptr->time_buffer);
 #endif
 
@@ -1271,17 +1300,11 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    png_free(png_ptr, png_ptr->save_buffer);
 #endif
 
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-#ifdef PNG_TEXT_SUPPORTED
-   png_free(png_ptr, png_ptr->current_text);
-#endif /* PNG_TEXT_SUPPORTED */
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-
    /* Save the important info out of the png_struct, in case it is
     * being used again.
     */
 #ifdef PNG_SETJMP_SUPPORTED
-   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
 #endif
 
    error_fn = png_ptr->error_fn;
@@ -1291,7 +1314,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
    free_fn = png_ptr->free_fn;
 #endif
 
-   png_memset(png_ptr, 0, png_sizeof (png_struct));
+   png_memset(png_ptr, 0, png_sizeof(png_struct));
 
    png_ptr->error_fn = error_fn;
    png_ptr->warning_fn = warning_fn;
@@ -1301,7 +1324,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
-   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
 #endif
 
 }
@@ -1309,13 +1332,14 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
 void PNGAPI
 png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
    png_ptr->read_row_fn = read_row_fn;
 }
 
 
-#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_INFO_IMAGE_SUPPORTED
 void PNGAPI
 png_read_png(png_structp png_ptr, png_infop info_ptr,
                            int transforms,
@@ -1323,9 +1347,10 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
 {
    int row;
 
-   if(png_ptr == NULL) return;
-#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
-   /* invert the alpha channel from opacity to transparency
+   if (png_ptr == NULL)
+      return;
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+   /* Invert the alpha channel from opacity to transparency
     */
    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
        png_set_invert_alpha(png_ptr);
@@ -1336,23 +1361,23 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
     */
    png_read_info(png_ptr, info_ptr);
    if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
-      png_error(png_ptr,"Image is too high to process with png_read_png()");
+      png_error(png_ptr, "Image is too high to process with png_read_png()");
 
    /* -------------- image transformations start here ------------------- */
 
-#if defined(PNG_READ_16_TO_8_SUPPORTED)
-   /* tell libpng to strip 16 bit/color files down to 8 bits per color
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+   /* Tell libpng to strip 16 bit/color files down to 8 bits per color.
     */
    if (transforms & PNG_TRANSFORM_STRIP_16)
-       png_set_strip_16(png_ptr);
+      png_set_strip_16(png_ptr);
 #endif
 
-#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
    /* Strip alpha bytes from the input data without combining with
     * the background (not recommended).
     */
    if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
-       png_set_strip_alpha(png_ptr);
+      png_set_strip_alpha(png_ptr);
 #endif
 
 #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
@@ -1360,41 +1385,41 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
     * byte into separate bytes (useful for paletted and grayscale images).
     */
    if (transforms & PNG_TRANSFORM_PACKING)
-       png_set_packing(png_ptr);
+      png_set_packing(png_ptr);
 #endif
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
    /* Change the order of packed pixels to least significant bit first
     * (not useful if you are using png_set_packing).
     */
    if (transforms & PNG_TRANSFORM_PACKSWAP)
-       png_set_packswap(png_ptr);
+      png_set_packswap(png_ptr);
 #endif
 
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
    /* Expand paletted colors into true RGB triplets
     * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
     * Expand paletted or RGB images with transparency to full alpha
     * channels so the data will be available as RGBA quartets.
     */
    if (transforms & PNG_TRANSFORM_EXPAND)
-       if ((png_ptr->bit_depth < 8) ||
-           (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
-           (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
+      if ((png_ptr->bit_depth < 8) ||
+          (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
+          (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
          png_set_expand(png_ptr);
 #endif
 
    /* We don't handle background color or gamma transformation or dithering.
     */
 
-#if defined(PNG_READ_INVERT_SUPPORTED)
-   /* invert monochrome files to have 0 as white and 1 as black
+#ifdef PNG_READ_INVERT_SUPPORTED
+   /* Invert monochrome files to have 0 as white and 1 as black
     */
    if (transforms & PNG_TRANSFORM_INVERT_MONO)
-       png_set_invert_mono(png_ptr);
+      png_set_invert_mono(png_ptr);
 #endif
 
-#if defined(PNG_READ_SHIFT_SUPPORTED)
+#ifdef PNG_READ_SHIFT_SUPPORTED
    /* If you want to shift the pixel values from the range [0,255] or
     * [0,65535] to the original [0,7] or [0,31], or whatever range the
     * colors were originally in:
@@ -1409,25 +1434,41 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
    }
 #endif
 
-#if defined(PNG_READ_BGR_SUPPORTED)
-   /* flip the RGB pixels to BGR (or RGBA to BGRA)
+#ifdef PNG_READ_BGR_SUPPORTED
+   /* Flip the RGB pixels to BGR (or RGBA to BGRA)
     */
    if (transforms & PNG_TRANSFORM_BGR)
-       png_set_bgr(png_ptr);
+      png_set_bgr(png_ptr);
 #endif
 
-#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
-   /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR)
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR)
     */
    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
        png_set_swap_alpha(png_ptr);
 #endif
 
-#if defined(PNG_READ_SWAP_SUPPORTED)
-   /* swap bytes of 16 bit files to least significant byte first
+#ifdef PNG_READ_SWAP_SUPPORTED
+   /* Swap bytes of 16 bit files to least significant byte first
     */
    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
-       png_set_swap(png_ptr);
+      png_set_swap(png_ptr);
+#endif
+
+/* Added at libpng-1.2.41 */
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+   /* Invert the alpha channel from opacity to transparency
+    */
+   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+       png_set_invert_alpha(png_ptr);
+#endif
+
+/* Added at libpng-1.2.41 */
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+   /* Expand grayscale image to RGB
+    */
+   if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
+       png_set_gray_to_rgb(png_ptr);
 #endif
 
    /* We don't handle adding filler bytes */
@@ -1443,30 +1484,32 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
 #ifdef PNG_FREE_ME_SUPPORTED
    png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
 #endif
-   if(info_ptr->row_pointers == NULL)
+   if (info_ptr->row_pointers == NULL)
    {
       info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
          info_ptr->height * png_sizeof(png_bytep));
+      png_memset(info_ptr->row_pointers, 0, info_ptr->height
+         * png_sizeof(png_bytep));
+
 #ifdef PNG_FREE_ME_SUPPORTED
       info_ptr->free_me |= PNG_FREE_ROWS;
 #endif
+
       for (row = 0; row < (int)info_ptr->height; row++)
-      {
          info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
             png_get_rowbytes(png_ptr, info_ptr));
-      }
    }
 
    png_read_image(png_ptr, info_ptr->row_pointers);
    info_ptr->valid |= PNG_INFO_IDAT;
 
-   /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
+   /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
    png_read_end(png_ptr, info_ptr);
 
-   transforms = transforms; /* quiet compiler warnings */
+   transforms = transforms; /* Quiet compiler warnings */
    params = params;
 
 }
 #endif /* PNG_INFO_IMAGE_SUPPORTED */
-#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 #endif /* PNG_READ_SUPPORTED */
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngrio.c b/graf2d/asimage/src/libAfterImage/libpng/pngrio.c
index 7d2522f..6978682 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngrio.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngrio.c
@@ -1,12 +1,15 @@
 
 /* pngrio.c - functions for data input
  *
- * Last changed in libpng 1.2.13 November 13, 2006
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2006 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * This file provides a location for all input.  Users who need
  * special handling are expected to write a function that has the same
  * arguments as this and performs a similar function, but that possibly
@@ -16,41 +19,45 @@
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
-#if defined(PNG_READ_SUPPORTED)
+#ifdef PNG_READ_SUPPORTED
 
 /* Read the data from whatever input you are using.  The default routine
-   reads from a file pointer.  Note that this routine sometimes gets called
-   with very small lengths, so you should implement some kind of simple
-   buffering if you are using unbuffered reads.  This should never be asked
-   to read more then 64K on a 16 bit machine. */
+ * reads from a file pointer.  Note that this routine sometimes gets called
+ * with very small lengths, so you should implement some kind of simple
+ * buffering if you are using unbuffered reads.  This should never be asked
+ * to read more then 64K on a 16 bit machine.
+ */
 void /* PRIVATE */
 png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 {
-   png_debug1(4,"reading %d bytes\n", (int)length);
+   png_debug1(4, "reading %d bytes", (int)length);
+ 
    if (png_ptr->read_data_fn != NULL)
       (*(png_ptr->read_data_fn))(png_ptr, data, length);
    else
       png_error(png_ptr, "Call to NULL read function");
 }
 
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_STDIO_SUPPORTED
 /* This is the function that does the actual reading of data.  If you are
-   not reading from a standard C stream, you should create a replacement
-   read_data function and use it at run time with png_set_read_fn(), rather
-   than changing the library. */
+ * not reading from a standard C stream, you should create a replacement
+ * read_data function and use it at run time with png_set_read_fn(), rather
+ * than changing the library.
+ */
 #ifndef USE_FAR_KEYWORD
 void PNGAPI
 png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 {
    png_size_t check;
 
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
    /* fread() returns 0 on error, so it is OK to store this in a png_size_t
     * instead of an int, which is what fread() actually returns.
     */
-#if defined(_WIN32_WCE)
+#ifdef _WIN32_WCE
    if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
       check = 0;
 #else
@@ -62,7 +69,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
       png_error(png_ptr, "Read Error");
 }
 #else
-/* this is the model-independent version. Since the standard I/O library
+/* This is the model-independent version. Since the standard I/O library
    can't handle far buffers in the medium and small models, we have to copy
    the data.
 */
@@ -77,14 +84,16 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
    png_byte *n_data;
    png_FILE_p io_ptr;
 
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
    /* Check if data really is near. If so, use usual code. */
    n_data = (png_byte *)CVT_PTR_NOCHECK(data);
    io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
    if ((png_bytep)n_data == data)
    {
-#if defined(_WIN32_WCE)
-      if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+#ifdef _WIN32_WCE
+      if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check,
+          NULL) )
          check = 0;
 #else
       check = fread(n_data, 1, length, io_ptr);
@@ -99,14 +108,14 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
       do
       {
          read = MIN(NEAR_BUF_SIZE, remaining);
-#if defined(_WIN32_WCE)
+#ifdef _WIN32_WCE
          if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) )
             err = 0;
 #else
          err = fread(buf, (png_size_t)1, read, io_ptr);
 #endif
          png_memcpy(data, buf, read); /* copy far buffer to near buffer */
-         if(err != read)
+         if (err != read)
             break;
          else
             check += err;
@@ -122,26 +131,30 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 #endif
 
 /* This function allows the application to supply a new input function
-   for libpng if standard C streams aren't being used.
-
-   This function takes as its arguments:
-   png_ptr      - pointer to a png input data structure
-   io_ptr       - pointer to user supplied structure containing info about
-                  the input functions.  May be NULL.
-   read_data_fn - pointer to a new input function that takes as its
-                  arguments a pointer to a png_struct, a pointer to
-                  a location where input data can be stored, and a 32-bit
-                  unsigned int that is the number of bytes to be read.
-                  To exit and output any fatal error messages the new write
-                  function should call png_error(png_ptr, "Error msg"). */
+ * for libpng if standard C streams aren't being used.
+ *
+ * This function takes as its arguments:
+ * png_ptr      - pointer to a png input data structure
+ * io_ptr       - pointer to user supplied structure containing info about
+ *                the input functions.  May be NULL.
+ * read_data_fn - pointer to a new input function that takes as its
+ *                arguments a pointer to a png_struct, a pointer to
+ *                a location where input data can be stored, and a 32-bit
+ *                unsigned int that is the number of bytes to be read.
+ *                To exit and output any fatal error messages the new write
+ *                function should call png_error(png_ptr, "Error msg").
+ *                May be NULL, in which case libpng's default function will
+ *                be used.
+ */
 void PNGAPI
 png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
    png_rw_ptr read_data_fn)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
    png_ptr->io_ptr = io_ptr;
 
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_STDIO_SUPPORTED
    if (read_data_fn != NULL)
       png_ptr->read_data_fn = read_data_fn;
    else
@@ -160,7 +173,7 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
          "same structure.  Resetting write_data_fn to NULL.");
    }
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
    png_ptr->output_flush_fn = NULL;
 #endif
 }
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngrtran.c b/graf2d/asimage/src/libAfterImage/libpng/pngrtran.c
index 1a428fa..7f0ff92 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngrtran.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngrtran.c
@@ -1,12 +1,15 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.2.22 [November 6, 2007]
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.49 [March 29, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * This file contains functions optionally called by an application
  * in order to tell libpng how to handle data when reading a PNG.
  * Transformations that are used in both reading and writing are
@@ -14,57 +17,71 @@
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
-#if defined(PNG_READ_SUPPORTED)
+#ifdef PNG_READ_SUPPORTED
 
 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
 void PNGAPI
 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
 {
-   png_debug(1, "in png_set_crc_action\n");
+   png_debug(1, "in png_set_crc_action");
+ 
+   if (png_ptr == NULL)
+      return;
+
    /* Tell libpng how we react to CRC errors in critical chunks */
-   if(png_ptr == NULL) return;
    switch (crit_action)
    {
-      case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
+      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
          break;
-      case PNG_CRC_WARN_USE:                               /* warn/use data */
+
+      case PNG_CRC_WARN_USE:                               /* Warn/use data */
          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
          break;
-      case PNG_CRC_QUIET_USE:                             /* quiet/use data */
+
+      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
                            PNG_FLAG_CRC_CRITICAL_IGNORE;
          break;
-      case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
-         png_warning(png_ptr, "Can't discard critical data on CRC error.");
-      case PNG_CRC_ERROR_QUIT:                                /* error/quit */
+
+      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
+         png_warning(png_ptr,
+            "Can't discard critical data on CRC error.");
+      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
+
       case PNG_CRC_DEFAULT:
       default:
          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
          break;
    }
 
+   /* Tell libpng how we react to CRC errors in ancillary chunks */
    switch (ancil_action)
    {
-      case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
+      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
          break;
-      case PNG_CRC_WARN_USE:                              /* warn/use data */
+
+      case PNG_CRC_WARN_USE:                              /* Warn/use data */
          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
          break;
-      case PNG_CRC_QUIET_USE:                            /* quiet/use data */
+
+      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
                            PNG_FLAG_CRC_ANCILLARY_NOWARN;
          break;
-      case PNG_CRC_ERROR_QUIT:                               /* error/quit */
+
+      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
          break;
-      case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
+
+      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
+
       case PNG_CRC_DEFAULT:
       default:
          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
@@ -74,14 +91,16 @@ png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
 
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
     defined(PNG_FLOATING_POINT_SUPPORTED)
-/* handle alpha and tRNS via a background color */
+/* Handle alpha and tRNS via a background color */
 void PNGAPI
 png_set_background(png_structp png_ptr,
    png_color_16p background_color, int background_gamma_code,
    int need_expand, double background_gamma)
 {
-   png_debug(1, "in png_set_background\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_background");
+ 
+   if (png_ptr == NULL)
+      return;
    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
    {
       png_warning(png_ptr, "Application must supply a known background gamma");
@@ -97,28 +116,32 @@ png_set_background(png_structp png_ptr,
 }
 #endif
 
-#if defined(PNG_READ_16_TO_8_SUPPORTED)
-/* strip 16 bit depth files to 8 bit depth */
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+/* Strip 16 bit depth files to 8 bit depth */
 void PNGAPI
 png_set_strip_16(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_strip_16\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_strip_16");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_16_TO_8;
 }
 #endif
 
-#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
 void PNGAPI
 png_set_strip_alpha(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_strip_alpha\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_strip_alpha");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
 }
 #endif
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
+#ifdef PNG_READ_DITHER_SUPPORTED
 /* Dither file to 8 bit.  Supply a palette, the current number
  * of elements in the palette, the maximum number of elements
  * allowed, and a histogram if possible.  If the current number
@@ -142,8 +165,10 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
    int num_palette, int maximum_colors, png_uint_16p histogram,
    int full_dither)
 {
-   png_debug(1, "in png_set_dither\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_dither");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_DITHER;
 
    if (!full_dither)
@@ -151,7 +176,7 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
       int i;
 
       png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
-         (png_uint_32)(num_palette * png_sizeof (png_byte)));
+         (png_uint_32)(num_palette * png_sizeof(png_byte)));
       for (i = 0; i < num_palette; i++)
          png_ptr->dither_index[i] = (png_byte)i;
    }
@@ -161,27 +186,29 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
       if (histogram != NULL)
       {
          /* This is easy enough, just throw out the least used colors.
-            Perhaps not the best solution, but good enough. */
+          * Perhaps not the best solution, but good enough.
+          */
 
          int i;
 
-         /* initialize an array to sort colors */
+         /* Initialize an array to sort colors */
          png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
-            (png_uint_32)(num_palette * png_sizeof (png_byte)));
+            (png_uint_32)(num_palette * png_sizeof(png_byte)));
 
-         /* initialize the dither_sort array */
+         /* Initialize the dither_sort array */
          for (i = 0; i < num_palette; i++)
             png_ptr->dither_sort[i] = (png_byte)i;
 
          /* Find the least used palette entries by starting a
-            bubble sort, and running it until we have sorted
-            out enough colors.  Note that we don't care about
-            sorting all the colors, just finding which are
-            least used. */
+          * bubble sort, and running it until we have sorted
+          * out enough colors.  Note that we don't care about
+          * sorting all the colors, just finding which are
+          * least used.
+          */
 
          for (i = num_palette - 1; i >= maximum_colors; i--)
          {
-            int done; /* to stop early if the list is pre-sorted */
+            int done; /* To stop early if the list is pre-sorted */
             int j;
 
             done = 1;
@@ -202,13 +229,14 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
                break;
          }
 
-         /* swap the palette around, and set up a table, if necessary */
+         /* Swap the palette around, and set up a table, if necessary */
          if (full_dither)
          {
             int j = num_palette;
 
-            /* put all the useful colors within the max, but don't
-               move the others */
+            /* Put all the useful colors within the max, but don't
+             * move the others.
+             */
             for (i = 0; i < maximum_colors; i++)
             {
                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
@@ -224,11 +252,12 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
          {
             int j = num_palette;
 
-            /* move all the used colors inside the max limit, and
-               develop a translation table */
+            /* Move all the used colors inside the max limit, and
+             * develop a translation table.
+             */
             for (i = 0; i < maximum_colors; i++)
             {
-               /* only move the colors we need to */
+               /* Only move the colors we need to */
                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
                {
                   png_color tmp_color;
@@ -240,20 +269,20 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
                   tmp_color = palette[j];
                   palette[j] = palette[i];
                   palette[i] = tmp_color;
-                  /* indicate where the color went */
+                  /* Indicate where the color went */
                   png_ptr->dither_index[j] = (png_byte)i;
                   png_ptr->dither_index[i] = (png_byte)j;
                }
             }
 
-            /* find closest color for those colors we are not using */
+            /* Find closest color for those colors we are not using */
             for (i = 0; i < num_palette; i++)
             {
                if ((int)png_ptr->dither_index[i] >= maximum_colors)
                {
                   int min_d, k, min_k, d_index;
 
-                  /* find the closest color to one we threw out */
+                  /* Find the closest color to one we threw out */
                   d_index = png_ptr->dither_index[i];
                   min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
                   for (k = 1, min_k = 0; k < maximum_colors; k++)
@@ -268,61 +297,58 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
                         min_k = k;
                      }
                   }
-                  /* point to closest color */
+                  /* Point to closest color */
                   png_ptr->dither_index[i] = (png_byte)min_k;
                }
             }
          }
          png_free(png_ptr, png_ptr->dither_sort);
-         png_ptr->dither_sort=NULL;
+         png_ptr->dither_sort = NULL;
       }
       else
       {
          /* This is much harder to do simply (and quickly).  Perhaps
-            we need to go through a median cut routine, but those
-            don't always behave themselves with only a few colors
-            as input.  So we will just find the closest two colors,
-            and throw out one of them (chosen somewhat randomly).
-            [We don't understand this at all, so if someone wants to
-             work on improving it, be our guest - AED, GRP]
-            */
+          * we need to go through a median cut routine, but those
+          * don't always behave themselves with only a few colors
+          * as input.  So we will just find the closest two colors,
+          * and throw out one of them (chosen somewhat randomly).
+          * [We don't understand this at all, so if someone wants to
+          *  work on improving it, be our guest - AED, GRP]
+          */
          int i;
          int max_d;
          int num_new_palette;
          png_dsortp t;
          png_dsortpp hash;
 
-         t=NULL;
+         t = NULL;
 
-         /* initialize palette index arrays */
+         /* Initialize palette index arrays */
          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
-            (png_uint_32)(num_palette * png_sizeof (png_byte)));
+            (png_uint_32)(num_palette * png_sizeof(png_byte)));
          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
-            (png_uint_32)(num_palette * png_sizeof (png_byte)));
+            (png_uint_32)(num_palette * png_sizeof(png_byte)));
 
-         /* initialize the sort array */
+         /* Initialize the sort array */
          for (i = 0; i < num_palette; i++)
          {
             png_ptr->index_to_palette[i] = (png_byte)i;
             png_ptr->palette_to_index[i] = (png_byte)i;
          }
 
-         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
-            png_sizeof (png_dsortp)));
-         for (i = 0; i < 769; i++)
-            hash[i] = NULL;
-/*         png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
+         hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
+            png_sizeof(png_dsortp)));
 
          num_new_palette = num_palette;
 
-         /* initial wild guess at how far apart the farthest pixel
-            pair we will be eliminating will be.  Larger
-            numbers mean more areas will be allocated, Smaller
-            numbers run the risk of not saving enough data, and
-            having to do this all over again.
-
-            I have not done extensive checking on this number.
-            */
+         /* Initial wild guess at how far apart the farthest pixel
+          * pair we will be eliminating will be.  Larger
+          * numbers mean more areas will be allocated, Smaller
+          * numbers run the risk of not saving enough data, and
+          * having to do this all over again.
+          *
+          * I have not done extensive checking on this number.
+          */
          max_d = 96;
 
          while (num_new_palette > maximum_colors)
@@ -406,8 +432,10 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
                         png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
                            = png_ptr->palette_to_index[num_new_palette];
 
-                        png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
-                        png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
+                        png_ptr->index_to_palette[j] =
+                            (png_byte)num_new_palette;
+                        png_ptr->palette_to_index[num_new_palette] =
+                            (png_byte)j;
                      }
                      if (num_new_palette <= maximum_colors)
                         break;
@@ -436,8 +464,8 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
          png_free(png_ptr, hash);
          png_free(png_ptr, png_ptr->palette_to_index);
          png_free(png_ptr, png_ptr->index_to_palette);
-         png_ptr->palette_to_index=NULL;
-         png_ptr->index_to_palette=NULL;
+         png_ptr->palette_to_index = NULL;
+         png_ptr->index_to_palette = NULL;
       }
       num_palette = maximum_colors;
    }
@@ -458,15 +486,11 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
       int num_blue = (1 << PNG_DITHER_BLUE_BITS);
       png_size_t num_entries = ((png_size_t)1 << total_bits);
 
-      png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
-         (png_uint_32)(num_entries * png_sizeof (png_byte)));
-
-      png_memset(png_ptr->palette_lookup, 0, num_entries *
-         png_sizeof (png_byte));
+      png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr,
+         (png_uint_32)(num_entries * png_sizeof(png_byte)));
 
       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
          png_sizeof(png_byte)));
-
       png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
 
       for (i = 0; i < num_palette; i++)
@@ -480,7 +504,8 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
          {
             /* int dr = abs(ir - r); */
             int dr = ((ir > r) ? ir - r : r - ir);
-            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
+            int index_r = (ir << (PNG_DITHER_BLUE_BITS +
+                PNG_DITHER_GREEN_BITS));
 
             for (ig = 0; ig < num_green; ig++)
             {
@@ -526,8 +551,11 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
 void PNGAPI
 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
 {
-   png_debug(1, "in png_set_gamma\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_gamma");
+
+   if (png_ptr == NULL)
+      return;
+
    if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
@@ -537,7 +565,7 @@ png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
 }
 #endif
 
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
 /* Expand paletted images to RGB, expand grayscale images of
  * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
  * to alpha channels.
@@ -545,12 +573,13 @@ png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
 void PNGAPI
 png_set_expand(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_expand\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_expand");
+
+   if (png_ptr == NULL)
+      return;
+
    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-#ifdef PNG_WARN_UNINITIALIZED_ROW
    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-#endif
 }
 
 /* GRR 19990627:  the following three functions currently are identical
@@ -566,33 +595,36 @@ png_set_expand(png_structp png_ptr)
  *  More to the point, these functions make it obvious what libpng will be
  *  doing, whereas "expand" can (and does) mean any number of things.
  *
- *  GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified
- *  to expand only the sample depth but not to expand the tRNS to alpha.
+ *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
+ *  to expand only the sample depth but not to expand the tRNS to alpha
+ *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
  */
 
 /* Expand paletted images to RGB. */
 void PNGAPI
 png_set_palette_to_rgb(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_palette_to_rgb\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_palette_to_rgb");
+
+   if (png_ptr == NULL)
+      return;
+
    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-#ifdef PNG_WARN_UNINITIALIZED_ROW
    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-#endif
 }
 
-#if !defined(PNG_1_0_X)
+#ifndef PNG_1_0_X
 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
 void PNGAPI
 png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
+
+   if (png_ptr == NULL)
+      return;
+
    png_ptr->transformations |= PNG_EXPAND;
-#ifdef PNG_WARN_UNINITIALIZED_ROW
    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-#endif
 }
 #endif
 
@@ -602,8 +634,11 @@ png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
 void PNGAPI
 png_set_gray_1_2_4_to_8(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_gray_1_2_4_to_8\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_gray_1_2_4_to_8");
+
+   if (png_ptr == NULL)
+      return;
+
    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
 }
 #endif
@@ -613,28 +648,26 @@ png_set_gray_1_2_4_to_8(png_structp png_ptr)
 void PNGAPI
 png_set_tRNS_to_alpha(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_tRNS_to_alpha\n");
+   png_debug(1, "in png_set_tRNS_to_alpha");
+
    png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-#ifdef PNG_WARN_UNINITIALIZED_ROW
    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-#endif
 }
 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
 void PNGAPI
 png_set_gray_to_rgb(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_gray_to_rgb\n");
+   png_debug(1, "in png_set_gray_to_rgb");
+
    png_ptr->transformations |= PNG_GRAY_TO_RGB;
-#ifdef PNG_WARN_UNINITIALIZED_ROW
    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-#endif
 }
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-#if defined(PNG_FLOATING_POINT_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
 /* Convert a RGB image to a grayscale of the same width.  This allows us,
  * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
  */
@@ -643,10 +676,22 @@ void PNGAPI
 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
    double green)
 {
-      int red_fixed = (int)((float)red*100000.0 + 0.5);
-      int green_fixed = (int)((float)green*100000.0 + 0.5);
-      if(png_ptr == NULL) return;
-      png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
+   int red_fixed, green_fixed;
+   if (png_ptr == NULL)
+      return;
+   if (red > 21474.83647 || red < -21474.83648 ||
+       green > 21474.83647 || green < -21474.83648)
+   {
+      png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
+      red_fixed = -1;
+      green_fixed = -1;
+   }
+   else
+   {
+      red_fixed = (int)((float)red*100000.0 + 0.5);
+      green_fixed = (int)((float)green*100000.0 + 0.5);
+   }
+   png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
 }
 #endif
 
@@ -654,36 +699,42 @@ void PNGAPI
 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
    png_fixed_point red, png_fixed_point green)
 {
-   png_debug(1, "in png_set_rgb_to_gray\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_rgb_to_gray");
+
+   if (png_ptr == NULL)
+      return;
+
    switch(error_action)
    {
       case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
               break;
+
       case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
               break;
+
       case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
    }
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
       png_ptr->transformations |= PNG_EXPAND;
 #else
    {
-      png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
+      png_warning(png_ptr,
+        "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
       png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
    }
 #endif
    {
       png_uint_16 red_int, green_int;
-      if(red < 0 || green < 0)
+      if (red < 0 || green < 0)
       {
          red_int   =  6968; /* .212671 * 32768 + .5 */
          green_int = 23434; /* .715160 * 32768 + .5 */
       }
-      else if(red + green < 100000L)
+      else if (red + green < 100000L)
       {
-        red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
-        green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
+         red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
+         green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
       }
       else
       {
@@ -693,26 +744,30 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
       }
       png_ptr->rgb_to_gray_red_coeff   = red_int;
       png_ptr->rgb_to_gray_green_coeff = green_int;
-      png_ptr->rgb_to_gray_blue_coeff  = (png_uint_16)(32768-red_int-green_int);
+      png_ptr->rgb_to_gray_blue_coeff  =
+         (png_uint_16)(32768 - red_int - green_int);
    }
 }
 #endif
 
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_LEGACY_SUPPORTED)
+    defined(PNG_LEGACY_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
 void PNGAPI
 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
    read_user_transform_fn)
 {
-   png_debug(1, "in png_set_read_user_transform_fn\n");
-   if(png_ptr == NULL) return;
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   png_debug(1, "in png_set_read_user_transform_fn");
+
+   if (png_ptr == NULL)
+      return;
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
    png_ptr->transformations |= PNG_USER_TRANSFORM;
    png_ptr->read_user_transform_fn = read_user_transform_fn;
 #endif
 #ifdef PNG_LEGACY_SUPPORTED
-   if(read_user_transform_fn)
+   if (read_user_transform_fn)
       png_warning(png_ptr,
         "This version of libpng does not support user transforms");
 #endif
@@ -725,22 +780,25 @@ png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
 void /* PRIVATE */
 png_init_read_transformations(png_structp png_ptr)
 {
-   png_debug(1, "in png_init_read_transformations\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
-   if(png_ptr != NULL)
+   png_debug(1, "in png_init_read_transformations");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+  if (png_ptr != NULL)
 #endif
   {
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
- || defined(PNG_READ_GAMMA_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+    defined(PNG_READ_SHIFT_SUPPORTED) || \
+    defined(PNG_READ_GAMMA_SUPPORTED)
    int color_type = png_ptr->color_type;
 #endif
 
 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
    /* Detect gray background and attempt to enable optimization
-    * for gray --> RGB case */
-   /* Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
+    * for gray --> RGB case
+    *
+    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
     * RGB_ALPHA (in which case need_expand is superfluous anyway), the
     * background color might actually be gray yet not be flagged as such.
     * This is not a problem for the current code, which uses
@@ -767,7 +825,7 @@ png_init_read_transformations(png_structp png_ptr)
    {
       if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
       {
-         /* expand background and tRNS chunks */
+         /* Expand background and tRNS chunks */
          switch (png_ptr->bit_depth)
          {
             case 1:
@@ -781,6 +839,7 @@ png_init_read_transformations(png_structp png_ptr)
                    = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
                }
                break;
+
             case 2:
                png_ptr->background.gray *= (png_uint_16)0x55;
                png_ptr->background.red = png_ptr->background.green
@@ -792,6 +851,7 @@ png_init_read_transformations(png_structp png_ptr)
                    = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
                }
                break;
+
             case 4:
                png_ptr->background.gray *= (png_uint_16)0x11;
                png_ptr->background.red = png_ptr->background.green
@@ -803,7 +863,9 @@ png_init_read_transformations(png_structp png_ptr)
                    = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
                }
                break;
+
             case 8:
+
             case 16:
                png_ptr->background.red = png_ptr->background.green
                  = png_ptr->background.blue = png_ptr->background.gray;
@@ -819,16 +881,17 @@ png_init_read_transformations(png_structp png_ptr)
          png_ptr->background.blue  =
             png_ptr->palette[png_ptr->background.index].blue;
 
-#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
         if (png_ptr->transformations & PNG_INVERT_ALPHA)
         {
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
            if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
 #endif
            {
-           /* invert the alpha channel (in tRNS) unless the pixels are
-              going to be expanded, in which case leave it for later */
-              int i,istop;
+           /* Invert the alpha channel (in tRNS) unless the pixels are
+            * going to be expanded, in which case leave it for later
+            */
+              int i, istop;
               istop=(int)png_ptr->num_trans;
               for (i=0; i<istop; i++)
                  png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
@@ -849,12 +912,12 @@ png_init_read_transformations(png_structp png_ptr)
        && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
          < PNG_GAMMA_THRESHOLD))
    {
-    int i,k;
+    int i, k;
     k=0;
     for (i=0; i<png_ptr->num_trans; i++)
     {
       if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
-        k=1; /* partial transparency is present */
+        k=1; /* Partial transparency is present */
     }
     if (k == 0)
       png_ptr->transformations &= ~PNG_GAMMA;
@@ -864,13 +927,13 @@ png_init_read_transformations(png_structp png_ptr)
         png_ptr->gamma != 0.0)
    {
       png_build_gamma_table(png_ptr);
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
       if (png_ptr->transformations & PNG_BACKGROUND)
       {
          if (color_type == PNG_COLOR_TYPE_PALETTE)
          {
-           /* could skip if no transparency and
-           */
+           /* Could skip if no transparency */
             png_color back, back_1;
             png_colorp palette = png_ptr->palette;
             int num_palette = png_ptr->num_palette;
@@ -895,10 +958,12 @@ png_init_read_transformations(png_structp png_ptr)
                      g = (png_ptr->screen_gamma);
                      gs = 1.0;
                      break;
+
                   case PNG_BACKGROUND_GAMMA_FILE:
                      g = 1.0 / (png_ptr->gamma);
                      gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
                      break;
+
                   case PNG_BACKGROUND_GAMMA_UNIQUE:
                      g = 1.0 / (png_ptr->background_gamma);
                      gs = 1.0 / (png_ptr->background_gamma *
@@ -920,7 +985,8 @@ png_init_read_transformations(png_structp png_ptr)
                   back.red = (png_byte)(pow(
                      (double)png_ptr->background.red/255, gs) * 255.0 + .5);
                   back.green = (png_byte)(pow(
-                     (double)png_ptr->background.green/255, gs) * 255.0 + .5);
+                     (double)png_ptr->background.green/255, gs) * 255.0
+                         + .5);
                   back.blue = (png_byte)(pow(
                      (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
                }
@@ -964,6 +1030,14 @@ png_init_read_transformations(png_structp png_ptr)
                   palette[i].blue = png_ptr->gamma_table[palette[i].blue];
                }
             }
+            /* Prevent the transformations being done again, and make sure
+             * that the now spurious alpha channel is stripped - the code
+             * has just reduced background composition and gamma correction
+             * to a simple alpha channel strip.
+             */
+            png_ptr->transformations &= ~PNG_BACKGROUND;
+            png_ptr->transformations &= ~PNG_GAMMA;
+            png_ptr->transformations |= PNG_STRIP_ALPHA;
          }
          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
          else
@@ -979,10 +1053,12 @@ png_init_read_transformations(png_structp png_ptr)
                   g = (png_ptr->screen_gamma);
                   gs = 1.0;
                   break;
+
                case PNG_BACKGROUND_GAMMA_FILE:
                   g = 1.0 / (png_ptr->gamma);
                   gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
                   break;
+
                case PNG_BACKGROUND_GAMMA_UNIQUE:
                   g = 1.0 / (png_ptr->background_gamma);
                   gs = 1.0 / (png_ptr->background_gamma *
@@ -1024,7 +1100,7 @@ png_init_read_transformations(png_structp png_ptr)
          }
       }
       else
-      /* transformation does not include PNG_BACKGROUND */
+      /* Transformation does not include PNG_BACKGROUND */
 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
       if (color_type == PNG_COLOR_TYPE_PALETTE)
       {
@@ -1038,13 +1114,16 @@ png_init_read_transformations(png_structp png_ptr)
             palette[i].green = png_ptr->gamma_table[palette[i].green];
             palette[i].blue = png_ptr->gamma_table[palette[i].blue];
          }
+
+         /* Done the gamma correction. */
+         png_ptr->transformations &= ~PNG_GAMMA;
       }
    }
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    else
 #endif
 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    /* No GAMMA transformation */
    if ((png_ptr->transformations & PNG_BACKGROUND) &&
        (color_type == PNG_COLOR_TYPE_PALETTE))
@@ -1075,11 +1154,16 @@ png_init_read_transformations(png_structp png_ptr)
                png_ptr->trans[i], back.blue);
          }
       }
+
+      /* Handled alpha, still need to strip the channel. */
+      png_ptr->transformations &= ~PNG_BACKGROUND;
+      png_ptr->transformations |= PNG_STRIP_ALPHA;
    }
 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
 
-#if defined(PNG_READ_SHIFT_SUPPORTED)
+#ifdef PNG_READ_SHIFT_SUPPORTED
    if ((png_ptr->transformations & PNG_SHIFT) &&
+      !(png_ptr->transformations & PNG_EXPAND) &&
       (color_type == PNG_COLOR_TYPE_PALETTE))
    {
       png_uint_16 i;
@@ -1100,12 +1184,14 @@ png_init_read_transformations(png_structp png_ptr)
          png_ptr->palette[i].green >>= sg;
          png_ptr->palette[i].blue >>= sb;
       }
+
+      png_ptr->transformations &= ~PNG_SHIFT;
    }
 #endif  /* PNG_READ_SHIFT_SUPPORTED */
  }
 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
  && !defined(PNG_READ_BACKGROUND_SUPPORTED)
-   if(png_ptr)
+   if (png_ptr)
       return;
 #endif
 }
@@ -1117,13 +1203,14 @@ png_init_read_transformations(png_structp png_ptr)
 void /* PRIVATE */
 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
 {
-   png_debug(1, "in png_read_transform_info\n");
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+   png_debug(1, "in png_read_transform_info");
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
    if (png_ptr->transformations & PNG_EXPAND)
    {
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       {
-         if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS))
+         if (png_ptr->num_trans)
             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
          else
             info_ptr->color_type = PNG_COLOR_TYPE_RGB;
@@ -1136,8 +1223,6 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
          {
             if (png_ptr->transformations & PNG_EXPAND_tRNS)
               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
-            else
-              info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
          }
          if (info_ptr->bit_depth < 8)
             info_ptr->bit_depth = 8;
@@ -1146,7 +1231,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
    }
 #endif
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    if (png_ptr->transformations & PNG_BACKGROUND)
    {
       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
@@ -1155,7 +1240,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
    }
 #endif
 
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
    if (png_ptr->transformations & PNG_GAMMA)
    {
 #ifdef PNG_FLOATING_POINT_SUPPORTED
@@ -1167,34 +1252,34 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
    }
 #endif
 
-#if defined(PNG_READ_16_TO_8_SUPPORTED)
+#ifdef PNG_READ_16_TO_8_SUPPORTED
    if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
       info_ptr->bit_depth = 8;
 #endif
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
       info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
       info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
 #endif
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
+#ifdef PNG_READ_DITHER_SUPPORTED
    if (png_ptr->transformations & PNG_DITHER)
    {
       if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
-         (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
-         png_ptr->palette_lookup && info_ptr->bit_depth == 8)
+          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
+          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
       {
          info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
       }
    }
 #endif
 
-#if defined(PNG_READ_PACK_SUPPORTED)
+#ifdef PNG_READ_PACK_SUPPORTED
    if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
       info_ptr->bit_depth = 8;
 #endif
@@ -1206,7 +1291,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
    else
       info_ptr->channels = 1;
 
-#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
 #endif
@@ -1214,15 +1299,15 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
       info_ptr->channels++;
 
-#if defined(PNG_READ_FILLER_SUPPORTED)
+#ifdef PNG_READ_FILLER_SUPPORTED
    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
    if ((png_ptr->transformations & PNG_FILLER) &&
        ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
        (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
    {
       info_ptr->channels++;
-      /* if adding a true alpha channel not just filler */
-#if !defined(PNG_1_0_X)
+      /* If adding a true alpha channel not just filler */
+#ifndef PNG_1_0_X
       if (png_ptr->transformations & PNG_ADD_ALPHA)
         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
 #endif
@@ -1231,11 +1316,11 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
 
 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
-   if(png_ptr->transformations & PNG_USER_TRANSFORM)
+   if (png_ptr->transformations & PNG_USER_TRANSFORM)
      {
-       if(info_ptr->bit_depth < png_ptr->user_transform_depth)
+       if (info_ptr->bit_depth < png_ptr->user_transform_depth)
          info_ptr->bit_depth = png_ptr->user_transform_depth;
-       if(info_ptr->channels < png_ptr->user_transform_channels)
+       if (info_ptr->channels < png_ptr->user_transform_channels)
          info_ptr->channels = png_ptr->user_transform_channels;
      }
 #endif
@@ -1243,10 +1328,10 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
       info_ptr->bit_depth);
 
-   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
+   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
 
-#if !defined(PNG_READ_EXPAND_SUPPORTED)
-   if(png_ptr)
+#ifndef PNG_READ_EXPAND_SUPPORTED
+   if (png_ptr)
       return;
 #endif
 }
@@ -1258,14 +1343,15 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
 void /* PRIVATE */
 png_do_read_transformations(png_structp png_ptr)
 {
-   png_debug(1, "in png_do_read_transformations\n");
+   png_debug(1, "in png_do_read_transformations");
+
    if (png_ptr->row_buf == NULL)
    {
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
       char msg[50];
 
       png_snprintf2(msg, 50,
-         "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
+         "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
          png_ptr->pass);
       png_error(png_ptr, msg);
 #else
@@ -1276,7 +1362,8 @@ png_do_read_transformations(png_structp png_ptr)
    if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
       /* Application has failed to call either png_read_start_image()
        * or png_read_update_info() after setting transforms that expand
-       * pixels.  This check added to libpng-1.2.19 */
+       * pixels.  This check added to libpng-1.2.19
+       */
 #if (PNG_WARN_UNINITIALIZED_ROW==1)
       png_error(png_ptr, "Uninitialized row");
 #else
@@ -1284,7 +1371,7 @@ png_do_read_transformations(png_structp png_ptr)
 #endif
 #endif
 
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
    if (png_ptr->transformations & PNG_EXPAND)
    {
       if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
@@ -1305,75 +1392,78 @@ png_do_read_transformations(png_structp png_ptr)
    }
 #endif
 
-#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
       png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
          PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
    {
       int rgb_error =
-         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
-      if(rgb_error)
+         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
+             png_ptr->row_buf + 1);
+      if (rgb_error)
       {
          png_ptr->rgb_to_gray_status=1;
-         if((png_ptr->transformations & PNG_RGB_TO_GRAY) == 
+         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
              PNG_RGB_TO_GRAY_WARN)
             png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
-         if((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
+         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
              PNG_RGB_TO_GRAY_ERR)
             png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
       }
    }
 #endif
 
-/*
-From Andreas Dilger e-mail to png-implement, 26 March 1998:
-
-  In most cases, the "simple transparency" should be done prior to doing
-  gray-to-RGB, or you will have to test 3x as many bytes to check if a
-  pixel is transparent.  You would also need to make sure that the
-  transparency information is upgraded to RGB.
-
-  To summarize, the current flow is:
-  - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
-                                  with background "in place" if transparent,
-                                  convert to RGB if necessary
-  - Gray + alpha -> composite with gray background and remove alpha bytes,
-                                  convert to RGB if necessary
-
-  To support RGB backgrounds for gray images we need:
-  - Gray + simple transparency -> convert to RGB + simple transparency, compare
-                                  3 or 6 bytes and composite with background
-                                  "in place" if transparent (3x compare/pixel
-                                  compared to doing composite with gray bkgrnd)
-  - Gray + alpha -> convert to RGB + alpha, composite with background and
-                                  remove alpha bytes (3x float operations/pixel
-                                  compared with composite on gray background)
-
-  Greg's change will do this.  The reason it wasn't done before is for
-  performance, as this increases the per-pixel operations.  If we would check
-  in advance if the background was gray or RGB, and position the gray-to-RGB
-  transform appropriately, then it would save a lot of work/time.
+/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
+ *
+ *   In most cases, the "simple transparency" should be done prior to doing
+ *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
+ *   pixel is transparent.  You would also need to make sure that the
+ *   transparency information is upgraded to RGB.
+ *
+ *   To summarize, the current flow is:
+ *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
+ *                                   with background "in place" if transparent,
+ *                                   convert to RGB if necessary
+ *   - Gray + alpha -> composite with gray background and remove alpha bytes,
+ *                                   convert to RGB if necessary
+ *
+ *   To support RGB backgrounds for gray images we need:
+ *   - Gray + simple transparency -> convert to RGB + simple transparency,
+ *                                   compare 3 or 6 bytes and composite with
+ *                                   background "in place" if transparent
+ *                                   (3x compare/pixel compared to doing
+ *                                   composite with gray bkgrnd)
+ *   - Gray + alpha -> convert to RGB + alpha, composite with background and
+ *                                   remove alpha bytes (3x float
+ *                                   operations/pixel compared with composite
+ *                                   on gray background)
+ *
+ *  Greg's change will do this.  The reason it wasn't done before is for
+ *  performance, as this increases the per-pixel operations.  If we would check
+ *  in advance if the background was gray or RGB, and position the gray-to-RGB
+ *  transform appropriately, then it would save a lot of work/time.
  */
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
-   /* if gray -> RGB, do so now only if background is non-gray; else do later
-    * for performance reasons */
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+   /* If gray -> RGB, do so now only if background is non-gray; else do later
+    * for performance reasons
+    */
    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    if ((png_ptr->transformations & PNG_BACKGROUND) &&
       ((png_ptr->num_trans != 0 ) ||
       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
       png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
          &(png_ptr->trans_values), &(png_ptr->background)
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
          , &(png_ptr->background_1),
          png_ptr->gamma_table, png_ptr->gamma_from_1,
          png_ptr->gamma_to_1, png_ptr->gamma_16_table,
@@ -1383,106 +1473,106 @@ From Andreas Dilger e-mail to png-implement, 26 March 1998:
 );
 #endif
 
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
    if ((png_ptr->transformations & PNG_GAMMA) &&
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
-      !((png_ptr->transformations & PNG_BACKGROUND) &&
-      ((png_ptr->num_trans != 0) ||
-      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+       !((png_ptr->transformations & PNG_BACKGROUND) &&
+       ((png_ptr->num_trans != 0) ||
+       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
 #endif
-      (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
+       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
       png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
-         png_ptr->gamma_table, png_ptr->gamma_16_table,
-         png_ptr->gamma_shift);
+          png_ptr->gamma_table, png_ptr->gamma_16_table,
+          png_ptr->gamma_shift);
 #endif
 
-#if defined(PNG_READ_16_TO_8_SUPPORTED)
+#ifdef PNG_READ_16_TO_8_SUPPORTED
    if (png_ptr->transformations & PNG_16_TO_8)
       png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
+#ifdef PNG_READ_DITHER_SUPPORTED
    if (png_ptr->transformations & PNG_DITHER)
    {
       png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
          png_ptr->palette_lookup, png_ptr->dither_index);
-      if(png_ptr->row_info.rowbytes == (png_uint_32)0)
+      if (png_ptr->row_info.rowbytes == (png_uint_32)0)
          png_error(png_ptr, "png_do_dither returned rowbytes=0");
    }
 #endif
 
-#if defined(PNG_READ_INVERT_SUPPORTED)
+#ifdef PNG_READ_INVERT_SUPPORTED
    if (png_ptr->transformations & PNG_INVERT_MONO)
       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_SHIFT_SUPPORTED)
+#ifdef PNG_READ_SHIFT_SUPPORTED
    if (png_ptr->transformations & PNG_SHIFT)
       png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
          &(png_ptr->shift));
 #endif
 
-#if defined(PNG_READ_PACK_SUPPORTED)
+#ifdef PNG_READ_PACK_SUPPORTED
    if (png_ptr->transformations & PNG_PACK)
       png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_BGR_SUPPORTED)
+#ifdef PNG_READ_BGR_SUPPORTED
    if (png_ptr->transformations & PNG_BGR)
       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
    if (png_ptr->transformations & PNG_PACKSWAP)
       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
-   /* if gray -> RGB, do so now only if we did not do so above */
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+   /* If gray -> RGB, do so now only if we did not do so above */
    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_FILLER_SUPPORTED)
+#ifdef PNG_READ_FILLER_SUPPORTED
    if (png_ptr->transformations & PNG_FILLER)
       png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->filler, png_ptr->flags);
 #endif
 
-#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
    if (png_ptr->transformations & PNG_INVERT_ALPHA)
       png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
    if (png_ptr->transformations & PNG_SWAP_ALPHA)
       png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_SWAP_SUPPORTED)
+#ifdef PNG_READ_SWAP_SUPPORTED
    if (png_ptr->transformations & PNG_SWAP_BYTES)
       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
    if (png_ptr->transformations & PNG_USER_TRANSFORM)
     {
-      if(png_ptr->read_user_transform_fn != NULL)
-        (*(png_ptr->read_user_transform_fn)) /* user read transform function */
-          (png_ptr,                    /* png_ptr */
-           &(png_ptr->row_info),       /* row_info:     */
-             /*  png_uint_32 width;          width of row */
-             /*  png_uint_32 rowbytes;       number of bytes in row */
-             /*  png_byte color_type;        color type of pixels */
-             /*  png_byte bit_depth;         bit depth of samples */
-             /*  png_byte channels;          number of channels (1-4) */
-             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
-           png_ptr->row_buf + 1);      /* start of pixel data for row */
-#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
-      if(png_ptr->user_transform_depth)
+      if (png_ptr->read_user_transform_fn != NULL)
+         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
+            (png_ptr,                    /* png_ptr */
+               &(png_ptr->row_info),     /* row_info: */
+               /*  png_uint_32 width;       width of row */
+               /*  png_uint_32 rowbytes;    number of bytes in row */
+               /*  png_byte color_type;     color type of pixels */
+               /*  png_byte bit_depth;      bit depth of samples */
+               /*  png_byte channels;       number of channels (1-4) */
+               /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
+               png_ptr->row_buf + 1);    /* start of pixel data for row */
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
+      if (png_ptr->user_transform_depth)
          png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
-      if(png_ptr->user_transform_channels)
+      if (png_ptr->user_transform_channels)
          png_ptr->row_info.channels = png_ptr->user_transform_channels;
 #endif
       png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
@@ -1494,7 +1584,7 @@ From Andreas Dilger e-mail to png-implement, 26 March 1998:
 
 }
 
-#if defined(PNG_READ_PACK_SUPPORTED)
+#ifdef PNG_READ_PACK_SUPPORTED
 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
  * without changing the actual values.  Thus, if you had a row with
  * a bit depth of 1, you would end up with bytes that only contained
@@ -1504,8 +1594,9 @@ From Andreas Dilger e-mail to png-implement, 26 March 1998:
 void /* PRIVATE */
 png_do_unpack(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_unpack\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_unpack");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
 #else
    if (row_info->bit_depth < 8)
@@ -1536,6 +1627,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
             }
             break;
          }
+
          case 2:
          {
 
@@ -1557,6 +1649,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
             }
             break;
          }
+
          case 4:
          {
             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
@@ -1585,7 +1678,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
 }
 #endif
 
-#if defined(PNG_READ_SHIFT_SUPPORTED)
+#ifdef PNG_READ_SHIFT_SUPPORTED
 /* Reverse the effects of png_do_shift.  This routine merely shifts the
  * pixels back to their significant bits values.  Thus, if you have
  * a row of bit depth 8, but only 5 are significant, this will shift
@@ -1594,9 +1687,10 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
 void /* PRIVATE */
 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
 {
-   png_debug(1, "in png_do_unshift\n");
+   png_debug(1, "in png_do_unshift");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL && sig_bits != NULL &&
 #endif
        row_info->color_type != PNG_COLOR_TYPE_PALETTE)
@@ -1648,6 +1742,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
             }
             break;
          }
+
          case 4:
          {
             png_bytep bp = row;
@@ -1663,6 +1758,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
             }
             break;
          }
+
          case 8:
          {
             png_bytep bp = row;
@@ -1675,6 +1771,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
             }
             break;
          }
+
          case 16:
          {
             png_bytep bp = row;
@@ -1695,13 +1792,14 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
 }
 #endif
 
-#if defined(PNG_READ_16_TO_8_SUPPORTED)
-/* chop rows of bit depth 16 down to 8 */
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+/* Chop rows of bit depth 16 down to 8 */
 void /* PRIVATE */
 png_do_chop(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_chop\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_chop");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
 #else
    if (row_info->bit_depth == 16)
@@ -1714,20 +1812,23 @@ png_do_chop(png_row_infop row_info, png_bytep row)
 
       for (i = 0; i<istop; i++, sp += 2, dp++)
       {
-#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
+#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
       /* This does a more accurate scaling of the 16-bit color
        * value, rather than a simple low-byte truncation.
        *
        * What the ideal calculation should be:
        *   *dp = (((((png_uint_32)(*sp) << 8) |
-       *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
+       *          (png_uint_32)(*(sp + 1))) * 255 + 127)
+       *          / (png_uint_32)65535L;
        *
        * GRR: no, I think this is what it really should be:
        *   *dp = (((((png_uint_32)(*sp) << 8) |
-       *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
+       *           (png_uint_32)(*(sp + 1))) + 128L)
+       *           / (png_uint_32)257L;
        *
        * GRR: here's the exact calculation with shifts:
-       *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
+       *   temp = (((png_uint_32)(*sp) << 8) |
+       *           (png_uint_32)(*(sp + 1))) + 128L;
        *   *dp = (temp - (temp >> 8)) >> 8;
        *
        * Approximate calculation with shift/add instead of multiply/divide:
@@ -1750,12 +1851,13 @@ png_do_chop(png_row_infop row_info, png_bytep row)
 }
 #endif
 
-#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
 void /* PRIVATE */
 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_read_swap_alpha\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_read_swap_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL)
 #endif
    {
@@ -1842,12 +1944,13 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
 }
 #endif
 
-#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
 void /* PRIVATE */
 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_read_invert_alpha\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_read_invert_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL)
 #endif
    {
@@ -1940,7 +2043,7 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
 }
 #endif
 
-#if defined(PNG_READ_FILLER_SUPPORTED)
+#ifdef PNG_READ_FILLER_SUPPORTED
 /* Add filler channel if we have RGB color */
 void /* PRIVATE */
 png_do_read_filler(png_row_infop row_info, png_bytep row,
@@ -1952,14 +2055,15 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
    png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
    png_byte lo_filler = (png_byte)(filler & 0xff);
 
-   png_debug(1, "in png_do_read_filler\n");
+   png_debug(1, "in png_do_read_filler");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL  && row_info != NULL &&
 #endif
        row_info->color_type == PNG_COLOR_TYPE_GRAY)
    {
-      if(row_info->bit_depth == 8)
+      if (row_info->bit_depth == 8)
       {
          /* This changes the data from G to GX */
          if (flags & PNG_FLAG_FILLER_AFTER)
@@ -1991,7 +2095,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
             row_info->rowbytes = row_width * 2;
          }
       }
-      else if(row_info->bit_depth == 16)
+      else if (row_info->bit_depth == 16)
       {
          /* This changes the data from GG to GGXX */
          if (flags & PNG_FLAG_FILLER_AFTER)
@@ -2031,7 +2135,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
    } /* COLOR_TYPE == GRAY */
    else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
    {
-      if(row_info->bit_depth == 8)
+      if (row_info->bit_depth == 8)
       {
          /* This changes the data from RGB to RGBX */
          if (flags & PNG_FLAG_FILLER_AFTER)
@@ -2067,7 +2171,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
             row_info->rowbytes = row_width * 4;
          }
       }
-      else if(row_info->bit_depth == 16)
+      else if (row_info->bit_depth == 16)
       {
          /* This changes the data from RRGGBB to RRGGBBXX */
          if (flags & PNG_FLAG_FILLER_AFTER)
@@ -2116,17 +2220,18 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
 }
 #endif
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
-/* expand grayscale files to RGB, with or without alpha */
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+/* Expand grayscale files to RGB, with or without alpha */
 void /* PRIVATE */
 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
 {
    png_uint_32 i;
    png_uint_32 row_width = row_info->width;
 
-   png_debug(1, "in png_do_gray_to_rgb\n");
+   png_debug(1, "in png_do_gray_to_rgb");
+
    if (row_info->bit_depth >= 8 &&
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
@@ -2194,16 +2299,18 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
       row_info->color_type |= PNG_COLOR_MASK_COLOR;
       row_info->pixel_depth = (png_byte)(row_info->channels *
          row_info->bit_depth);
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
+      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
    }
 }
 #endif
 
-#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-/* reduce RGB files to grayscale, with or without alpha
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+/* Reduce RGB files to grayscale, with or without alpha
  * using the equation given in Poynton's ColorFAQ at
- * <http://www.inforamp.net/~poynton/>
- * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
+ * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008)
+ * New link:
+ * <http://www.poynton.com/notes/colour_and_gamma/>
+ * Charles Poynton poynton at poynton.com
  *
  *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
  *
@@ -2228,9 +2335,10 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
    png_uint_32 row_width = row_info->width;
    int rgb_error = 0;
 
-   png_debug(1, "in png_do_rgb_to_gray\n");
+   png_debug(1, "in png_do_rgb_to_gray");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
       (row_info->color_type & PNG_COLOR_MASK_COLOR))
@@ -2254,14 +2362,14 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
-                  if(red != green || red != blue)
+                  if (red != green || red != blue)
                   {
                      rgb_error |= 1;
                      *(dp++) = png_ptr->gamma_from_1[
-                       (rc*red+gc*green+bc*blue)>>15];
+                       (rc*red + gc*green + bc*blue)>>15];
                   }
                   else
-                     *(dp++) = *(sp-1);
+                     *(dp++) = *(sp - 1);
                }
             }
             else
@@ -2274,13 +2382,13 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   png_byte red   = *(sp++);
                   png_byte green = *(sp++);
                   png_byte blue  = *(sp++);
-                  if(red != green || red != blue)
+                  if (red != green || red != blue)
                   {
                      rgb_error |= 1;
-                     *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
+                     *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
                   }
                   else
-                     *(dp++) = *(sp-1);
+                     *(dp++) = *(sp - 1);
                }
             }
          }
@@ -2301,13 +2409,14 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
 
-                  if(red == green && red == blue)
+                  if (red == green && red == blue)
                      w = red;
                   else
                   {
                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
                                   png_ptr->gamma_shift][red>>8];
-                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
+                     png_uint_16 green_1 =
+                         png_ptr->gamma_16_to_1[(green&0xff) >>
                                   png_ptr->gamma_shift][green>>8];
                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
                                   png_ptr->gamma_shift][blue>>8];
@@ -2335,7 +2444,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
 
-                  if(red != green || red != blue)
+                  if (red != green || red != blue)
                      rgb_error |= 1;
                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
@@ -2358,7 +2467,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
-                  if(red != green || red != blue)
+                  if (red != green || red != blue)
                      rgb_error |= 1;
                   *(dp++) =  png_ptr->gamma_from_1
                              [(rc*red + gc*green + bc*blue)>>15];
@@ -2375,7 +2484,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   png_byte red   = *(sp++);
                   png_byte green = *(sp++);
                   png_byte blue  = *(sp++);
-                  if(red != green || red != blue)
+                  if (red != green || red != blue)
                      rgb_error |= 1;
                   *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
                   *(dp++) = *(sp++);  /* alpha */
@@ -2398,18 +2507,19 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
 
-                  if(red == green && red == blue)
+                  if (red == green && red == blue)
                      w = red;
                   else
                   {
                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
-                                  png_ptr->gamma_shift][red>>8];
-                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
-                                  png_ptr->gamma_shift][green>>8];
+                         png_ptr->gamma_shift][red>>8];
+                     png_uint_16 green_1 =
+                         png_ptr->gamma_16_to_1[(green&0xff) >>
+                         png_ptr->gamma_shift][green>>8];
                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
-                                  png_ptr->gamma_shift][blue>>8];
+                         png_ptr->gamma_shift][blue>>8];
                      png_uint_16 gray16  = (png_uint_16)((rc * red_1
-                                  + gc * green_1 + bc * blue_1)>>15);
+                         + gc * green_1 + bc * blue_1)>>15);
                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
                          png_ptr->gamma_shift][gray16 >> 8];
                      rgb_error |= 1;
@@ -2432,7 +2542,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
                   red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
                   green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
                   blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
-                  if(red != green || red != blue)
+                  if (red != green || red != blue)
                      rgb_error |= 1;
                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
@@ -2447,7 +2557,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
       row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
       row_info->pixel_depth = (png_byte)(row_info->channels *
          row_info->bit_depth);
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
+      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
    }
    return rgb_error;
 }
@@ -2466,7 +2576,8 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
    int i;
    int v;
 
-   png_debug(1, "in png_do_build_grayscale_palette\n");
+   png_debug(1, "in png_do_build_grayscale_palette");
+
    if (palette == NULL)
       return;
 
@@ -2476,18 +2587,22 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
          num_palette = 2;
          color_inc = 0xff;
          break;
+
       case 2:
          num_palette = 4;
          color_inc = 0x55;
          break;
+
       case 4:
          num_palette = 16;
          color_inc = 0x11;
          break;
+
       case 8:
          num_palette = 256;
          color_inc = 1;
          break;
+
       default:
          num_palette = 0;
          color_inc = 0;
@@ -2503,14 +2618,17 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
 }
 
 /* This function is currently unused.  Do we really need it? */
-#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
+#if defined(PNG_READ_DITHER_SUPPORTED) && \
+  defined(PNG_CORRECT_PALETTE_SUPPORTED)
 void /* PRIVATE */
 png_correct_palette(png_structp png_ptr, png_colorp palette,
    int num_palette)
 {
-   png_debug(1, "in png_correct_palette\n");
+   png_debug(1, "in png_correct_palette");
+
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
-    defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+    defined(PNG_READ_GAMMA_SUPPORTED) && \
+  defined(PNG_FLOATING_POINT_SUPPORTED)
    if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
    {
       png_color back, back_1;
@@ -2531,8 +2649,8 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
 
          g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
 
-         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
-             fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
+         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN
+             || fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
          {
             back.red = png_ptr->background.red;
             back.green = png_ptr->background.green;
@@ -2619,7 +2737,7 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
    }
    else
 #endif
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
    if (png_ptr->transformations & PNG_GAMMA)
    {
       int i;
@@ -2631,11 +2749,11 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
          palette[i].blue = png_ptr->gamma_table[palette[i].blue];
       }
    }
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    else
 #endif
 #endif
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
    if (png_ptr->transformations & PNG_BACKGROUND)
    {
       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
@@ -2665,7 +2783,7 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
             }
          }
       }
-      else /* assume grayscale palette (what else could it be?) */
+      else /* Assume grayscale palette (what else could it be?) */
       {
          int i;
 
@@ -2684,7 +2802,7 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
 }
 #endif
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
 /* Replace any alpha or transparency with the supplied background color.
  * "background" is already in the screen gamma, while "background_1" is
  * at a gamma of 1.0.  Paletted files have already been taken care of.
@@ -2692,7 +2810,7 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
 void /* PRIVATE */
 png_do_background(png_row_infop row_info, png_bytep row,
    png_color_16p trans_values, png_color_16p background
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
    , png_color_16p background_1,
    png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
    png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
@@ -2705,9 +2823,10 @@ png_do_background(png_row_infop row_info, png_bytep row,
    png_uint_32 row_width=row_info->width;
    int shift;
 
-   png_debug(1, "in png_do_background\n");
+   png_debug(1, "in png_do_background");
+
    if (background != NULL &&
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
       (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
@@ -2741,9 +2860,10 @@ png_do_background(png_row_infop row_info, png_bytep row,
                   }
                   break;
                }
+
                case 2:
                {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                   if (gamma_table != NULL)
                   {
                      sp = row;
@@ -2797,9 +2917,10 @@ png_do_background(png_row_infop row_info, png_bytep row,
                   }
                   break;
                }
+
                case 4:
                {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                   if (gamma_table != NULL)
                   {
                      sp = row;
@@ -2853,9 +2974,10 @@ png_do_background(png_row_infop row_info, png_bytep row,
                   }
                   break;
                }
+
                case 8:
                {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                   if (gamma_table != NULL)
                   {
                      sp = row;
@@ -2885,9 +3007,10 @@ png_do_background(png_row_infop row_info, png_bytep row,
                   }
                   break;
                }
+
                case 16:
                {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                   if (gamma_16 != NULL)
                   {
                      sp = row;
@@ -2898,7 +3021,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
                         if (v == trans_values->gray)
                         {
-                           /* background is already in screen gamma */
+                           /* Background is already in screen gamma */
                            *sp = (png_byte)((background->gray >> 8) & 0xff);
                            *(sp + 1) = (png_byte)(background->gray & 0xff);
                         }
@@ -2931,11 +3054,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
             }
             break;
          }
+
          case PNG_COLOR_TYPE_RGB:
          {
             if (row_info->bit_depth == 8)
             {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                if (gamma_table != NULL)
                {
                   sp = row;
@@ -2976,7 +3100,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
             }
             else /* if (row_info->bit_depth == 16) */
             {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                if (gamma_16 != NULL)
                {
                   sp = row;
@@ -2988,7 +3112,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      if (r == trans_values->red && g == trans_values->green &&
                         b == trans_values->blue)
                      {
-                        /* background is already in screen gamma */
+                        /* Background is already in screen gamma */
                         *sp = (png_byte)((background->red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(background->red & 0xff);
                         *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
@@ -3035,11 +3159,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
             }
             break;
          }
+
          case PNG_COLOR_TYPE_GRAY_ALPHA:
          {
             if (row_info->bit_depth == 8)
             {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                    gamma_table != NULL)
                {
@@ -3055,7 +3180,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      }
                      else if (a == 0)
                      {
-                        /* background is already in screen gamma */
+                        /* Background is already in screen gamma */
                         *dp = (png_byte)background->gray;
                      }
                      else
@@ -3081,7 +3206,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      {
                         *dp = *sp;
                      }
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                      else if (a == 0)
                      {
                         *dp = (png_byte)background->gray;
@@ -3098,7 +3223,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
             }
             else /* if (png_ptr->bit_depth == 16) */
             {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                    gamma_16_to_1 != NULL)
                {
@@ -3116,17 +3241,17 @@ png_do_background(png_row_infop row_info, png_bytep row,
                         *dp = (png_byte)((v >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(v & 0xff);
                      }
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                      else if (a == 0)
 #else
                      else
 #endif
                      {
-                        /* background is already in screen gamma */
+                        /* Background is already in screen gamma */
                         *dp = (png_byte)((background->gray >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(background->gray & 0xff);
                      }
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                      else
                      {
                         png_uint_16 g, v, w;
@@ -3152,7 +3277,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      {
                         png_memcpy(dp, sp, 2);
                      }
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                      else if (a == 0)
 #else
                      else
@@ -3161,7 +3286,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                         *dp = (png_byte)((background->gray >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(background->gray & 0xff);
                      }
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                      else
                      {
                         png_uint_16 g, v;
@@ -3177,11 +3302,12 @@ png_do_background(png_row_infop row_info, png_bytep row,
             }
             break;
          }
+
          case PNG_COLOR_TYPE_RGB_ALPHA:
          {
             if (row_info->bit_depth == 8)
             {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
                    gamma_table != NULL)
                {
@@ -3199,7 +3325,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      }
                      else if (a == 0)
                      {
-                        /* background is already in screen gamma */
+                        /* Background is already in screen gamma */
                         *dp = (png_byte)background->red;
                         *(dp + 1) = (png_byte)background->green;
                         *(dp + 2) = (png_byte)background->blue;
@@ -3254,7 +3380,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
             }
             else /* if (row_info->bit_depth == 16) */
             {
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
                    gamma_16_to_1 != NULL)
                {
@@ -3280,7 +3406,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
                      }
                      else if (a == 0)
                      {
-                        /* background is already in screen gamma */
+                        /* Background is already in screen gamma */
                         *dp = (png_byte)((background->red >> 8) & 0xff);
                         *(dp + 1) = (png_byte)(background->red & 0xff);
                         *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
@@ -3365,13 +3491,13 @@ png_do_background(png_row_infop row_info, png_bytep row,
          row_info->channels--;
          row_info->pixel_depth = (png_byte)(row_info->channels *
             row_info->bit_depth);
-         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
+         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       }
    }
 }
 #endif
 
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
 /* Gamma correct the image, avoiding the alpha channel.  Make sure
  * you do this after you deal with the transparency issue on grayscale
  * or RGB images. If your bit depth is 8, use gamma_table, if it
@@ -3387,9 +3513,10 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
    png_uint_32 i;
    png_uint_32 row_width=row_info->width;
 
-   png_debug(1, "in png_do_gamma\n");
+   png_debug(1, "in png_do_gamma");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
        ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
@@ -3435,6 +3562,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             break;
          }
+
          case PNG_COLOR_TYPE_RGB_ALPHA:
          {
             if (row_info->bit_depth == 8)
@@ -3472,6 +3600,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             break;
          }
+
          case PNG_COLOR_TYPE_GRAY_ALPHA:
          {
             if (row_info->bit_depth == 8)
@@ -3496,6 +3625,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
             }
             break;
          }
+
          case PNG_COLOR_TYPE_GRAY:
          {
             if (row_info->bit_depth == 2)
@@ -3509,13 +3639,14 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
                   int d = *sp & 0x03;
 
                   *sp = (png_byte)(
-                        ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
-                        ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
-                        ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
-                        ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
+                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
+                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
+                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
+                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
                   sp++;
                }
             }
+
             if (row_info->bit_depth == 4)
             {
                sp = row;
@@ -3525,10 +3656,11 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
                   int lsb = *sp & 0x0f;
 
                   *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
-                          | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
+                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
                   sp++;
                }
             }
+
             else if (row_info->bit_depth == 8)
             {
                sp = row;
@@ -3538,6 +3670,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
                   sp++;
                }
             }
+
             else if (row_info->bit_depth == 16)
             {
                sp = row;
@@ -3556,7 +3689,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row,
 }
 #endif
 
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
 /* Expands a palette row to an RGB or RGBA row depending
  * upon whether you supply trans and num_trans.
  */
@@ -3569,9 +3702,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
    png_uint_32 i;
    png_uint_32 row_width=row_info->width;
 
-   png_debug(1, "in png_do_expand_palette\n");
+   png_debug(1, "in png_do_expand_palette");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
        row_info->color_type == PNG_COLOR_TYPE_PALETTE)
@@ -3603,6 +3737,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
                }
                break;
             }
+
             case 2:
             {
                sp = row + (png_size_t)((row_width - 1) >> 2);
@@ -3624,6 +3759,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
                }
                break;
             }
+
             case 4:
             {
                sp = row + (png_size_t)((row_width - 1) >> 1);
@@ -3688,6 +3824,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
                   *dp-- = palette[*sp].red;
                   sp--;
                }
+
                row_info->bit_depth = 8;
                row_info->pixel_depth = 24;
                row_info->rowbytes = row_width * 3;
@@ -3712,8 +3849,9 @@ png_do_expand(png_row_infop row_info, png_bytep row,
    png_uint_32 i;
    png_uint_32 row_width=row_info->width;
 
-   png_debug(1, "in png_do_expand\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_expand");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL)
 #endif
    {
@@ -3749,6 +3887,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                   }
                   break;
                }
+
                case 2:
                {
                   gray = (png_uint_16)((gray&0x03)*0x55);
@@ -3772,6 +3911,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                   }
                   break;
                }
+
                case 4:
                {
                   gray = (png_uint_16)((gray&0x0f)*0x11);
@@ -3795,6 +3935,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                   break;
                }
             }
+
             row_info->bit_depth = 8;
             row_info->pixel_depth = 8;
             row_info->rowbytes = row_width;
@@ -3816,6 +3957,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                   *dp-- = *sp--;
                }
             }
+
             else if (row_info->bit_depth == 16)
             {
                png_byte gray_high = (gray >> 8) & 0xff;
@@ -3824,7 +3966,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                dp = row + (row_info->rowbytes << 1) - 1;
                for (i = 0; i < row_width; i++)
                {
-                  if (*(sp-1) == gray_high && *(sp) == gray_low) 
+                  if (*(sp - 1) == gray_high && *(sp) == gray_low)
                   {
                      *dp-- = 0;
                      *dp-- = 0;
@@ -3838,6 +3980,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
                   *dp-- = *sp--;
                }
             }
+
             row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
             row_info->channels = 2;
             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
@@ -3903,13 +4046,13 @@ png_do_expand(png_row_infop row_info, png_bytep row,
          row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
          row_info->channels = 4;
          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
-         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
+         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       }
    }
 }
 #endif
 
-#if defined(PNG_READ_DITHER_SUPPORTED)
+#ifdef PNG_READ_DITHER_SUPPORTED
 void /* PRIVATE */
 png_do_dither(png_row_infop row_info, png_bytep row,
     png_bytep palette_lookup, png_bytep dither_lookup)
@@ -3918,8 +4061,9 @@ png_do_dither(png_row_infop row_info, png_bytep row,
    png_uint_32 i;
    png_uint_32 row_width=row_info->width;
 
-   png_debug(1, "in png_do_dither\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_dither");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL)
 #endif
    {
@@ -3935,13 +4079,13 @@ png_do_dither(png_row_infop row_info, png_bytep row,
             g = *sp++;
             b = *sp++;
 
-            /* this looks real messy, but the compiler will reduce
-               it down to a reasonable formula.  For example, with
-               5 bits per color, we get:
-               p = (((r >> 3) & 0x1f) << 10) |
-                  (((g >> 3) & 0x1f) << 5) |
-                  ((b >> 3) & 0x1f);
-               */
+            /* This looks real messy, but the compiler will reduce
+             * it down to a reasonable formula.  For example, with
+             * 5 bits per color, we get:
+             * p = (((r >> 3) & 0x1f) << 10) |
+             *    (((g >> 3) & 0x1f) << 5) |
+             *    ((b >> 3) & 0x1f);
+             */
             p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
                ((1 << PNG_DITHER_RED_BITS) - 1)) <<
                (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
@@ -3956,7 +4100,7 @@ png_do_dither(png_row_infop row_info, png_bytep row,
          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
          row_info->channels = 1;
          row_info->pixel_depth = row_info->bit_depth;
-         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
+         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       }
       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
          palette_lookup != NULL && row_info->bit_depth == 8)
@@ -3985,7 +4129,7 @@ png_do_dither(png_row_infop row_info, png_bytep row,
          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
          row_info->channels = 1;
          row_info->pixel_depth = row_info->bit_depth;
-         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
+         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
       }
       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
          dither_lookup && row_info->bit_depth == 8)
@@ -4001,7 +4145,7 @@ png_do_dither(png_row_infop row_info, png_bytep row,
 #endif
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-#if defined(PNG_READ_GAMMA_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
 static PNG_CONST int png_gamma_shift[] =
    {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
 
@@ -4009,11 +4153,39 @@ static PNG_CONST int png_gamma_shift[] =
  * tables, we don't make a full table if we are reducing to 8-bit in
  * the future.  Note also how the gamma_16 tables are segmented so that
  * we don't need to allocate > 64K chunks for a full 16-bit table.
+ *
+ * See the PNG extensions document for an integer algorithm for creating
+ * the gamma tables.  Maybe we will implement that here someday.
+ *
+ * We should only reach this point if
+ *
+ *      the file_gamma is known (i.e., the gAMA or sRGB chunk is present,
+ *      or the application has provided a file_gamma)
+ *
+ *   AND
+ *      {
+ *         the screen_gamma is known
+ *      OR
+ *
+ *         RGB_to_gray transformation is being performed
+ *      }
+ *
+ *   AND
+ *      {
+ *         the screen_gamma is different from the reciprocal of the
+ *         file_gamma by more than the specified threshold
+ *
+ *      OR
+ *
+ *         a background color has been specified and the file_gamma
+ *         and screen_gamma are not 1.0, within the specified threshold.
+ *      }
  */
+
 void /* PRIVATE */
 png_build_gamma_table(png_structp png_ptr)
 {
-  png_debug(1, "in png_build_gamma_table\n");
+  png_debug(1, "in png_build_gamma_table");
 
   if (png_ptr->bit_depth <= 8)
   {
@@ -4022,6 +4194,7 @@ png_build_gamma_table(png_structp png_ptr)
 
      if (png_ptr->screen_gamma > .000001)
         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+
      else
         g = 1.0;
 
@@ -4054,10 +4227,11 @@ png_build_gamma_table(png_structp png_ptr)
         png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
            (png_uint_32)256);
 
-        if(png_ptr->screen_gamma > 0.000001)
+        if (png_ptr->screen_gamma > 0.000001)
            g = 1.0 / png_ptr->screen_gamma;
+
         else
-           g = png_ptr->gamma;   /* probably doing rgb_to_gray */
+           g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
 
         for (i = 0; i < 256; i++)
         {
@@ -4078,8 +4252,10 @@ png_build_gamma_table(png_structp png_ptr)
      if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
      {
         sig_bit = (int)png_ptr->sig_bit.red;
+
         if ((int)png_ptr->sig_bit.green > sig_bit)
            sig_bit = png_ptr->sig_bit.green;
+
         if ((int)png_ptr->sig_bit.blue > sig_bit)
            sig_bit = png_ptr->sig_bit.blue;
      }
@@ -4090,6 +4266,7 @@ png_build_gamma_table(png_structp png_ptr)
 
      if (sig_bit > 0)
         shift = 16 - sig_bit;
+
      else
         shift = 0;
 
@@ -4101,6 +4278,7 @@ png_build_gamma_table(png_structp png_ptr)
 
      if (shift > 8)
         shift = 8;
+
      if (shift < 0)
         shift = 0;
 
@@ -4113,8 +4291,8 @@ png_build_gamma_table(png_structp png_ptr)
      else
         g = 1.0;
 
-     png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
-        (png_uint_32)(num * png_sizeof (png_uint_16p)));
+     png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr,
+        (png_uint_32)(num * png_sizeof(png_uint_16p)));
 
      if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
      {
@@ -4124,7 +4302,7 @@ png_build_gamma_table(png_structp png_ptr)
         for (i = 0; i < num; i++)
         {
            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
-              (png_uint_32)(256 * png_sizeof (png_uint_16)));
+              (png_uint_32)(256 * png_sizeof(png_uint_16)));
         }
 
         g = 1.0 / g;
@@ -4154,9 +4332,10 @@ png_build_gamma_table(png_structp png_ptr)
         for (i = 0; i < num; i++)
         {
            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
-              (png_uint_32)(256 * png_sizeof (png_uint_16)));
+              (png_uint_32)(256 * png_sizeof(png_uint_16)));
 
            ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
+
            for (j = 0; j < 256; j++)
            {
               png_ptr->gamma_16_table[i][j] =
@@ -4173,13 +4352,13 @@ png_build_gamma_table(png_structp png_ptr)
 
         g = 1.0 / (png_ptr->gamma);
 
-        png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
-           (png_uint_32)(num * png_sizeof (png_uint_16p )));
+        png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr,
+           (png_uint_32)(num * png_sizeof(png_uint_16p )));
 
         for (i = 0; i < num; i++)
         {
            png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
-              (png_uint_32)(256 * png_sizeof (png_uint_16)));
+              (png_uint_32)(256 * png_sizeof(png_uint_16)));
 
            ig = (((png_uint_32)i *
               (png_uint_32)png_gamma_shift[shift]) >> 4);
@@ -4191,21 +4370,23 @@ png_build_gamma_table(png_structp png_ptr)
            }
         }
 
-        if(png_ptr->screen_gamma > 0.000001)
+        if (png_ptr->screen_gamma > 0.000001)
            g = 1.0 / png_ptr->screen_gamma;
+
         else
-           g = png_ptr->gamma;   /* probably doing rgb_to_gray */
+           g = png_ptr->gamma;   /* Probably doing rgb_to_gray */
 
-        png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
-           (png_uint_32)(num * png_sizeof (png_uint_16p)));
+        png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr,
+           (png_uint_32)(num * png_sizeof(png_uint_16p)));
 
         for (i = 0; i < num; i++)
         {
            png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
-              (png_uint_32)(256 * png_sizeof (png_uint_16)));
+              (png_uint_32)(256 * png_sizeof(png_uint_16)));
 
            ig = (((png_uint_32)i *
               (png_uint_32)png_gamma_shift[shift]) >> 4);
+
            for (j = 0; j < 256; j++)
            {
               png_ptr->gamma_16_from_1[i][j] =
@@ -4221,14 +4402,15 @@ png_build_gamma_table(png_structp png_ptr)
 /* To do: install integer version of png_build_gamma_table here */
 #endif
 
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-/* undoes intrapixel differencing  */
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Undoes intrapixel differencing  */
 void /* PRIVATE */
 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_read_intrapixel\n");
+   png_debug(1, "in png_do_read_intrapixel");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
        (row_info->color_type & PNG_COLOR_MASK_COLOR))
@@ -4242,8 +4424,10 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
 
          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
             bytes_per_pixel = 3;
+
          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
             bytes_per_pixel = 4;
+
          else
             return;
 
@@ -4260,18 +4444,20 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
 
          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
             bytes_per_pixel = 6;
+
          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
             bytes_per_pixel = 8;
+
          else
             return;
 
          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
          {
-            png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
-            png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
-            png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
-            png_uint_32 red  = (png_uint_32)((s0+s1+65536L) & 0xffffL);
-            png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
+            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
+            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
+            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
+            png_uint_32 red  = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
+            png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
             *(rp  ) = (png_byte)((red >> 8) & 0xff);
             *(rp+1) = (png_byte)(red & 0xff);
             *(rp+4) = (png_byte)((blue >> 8) & 0xff);
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngrutil.c b/graf2d/asimage/src/libAfterImage/libpng/pngrutil.c
index 08d03ff..1de7427 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngrutil.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngrutil.c
@@ -1,36 +1,40 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.2.22 [November 6, 2007]
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.48 [March 8, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * This file contains routines that are only called from within
  * libpng itself during the course of reading an image.
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
-#if defined(PNG_READ_SUPPORTED)
+#ifdef PNG_READ_SUPPORTED
 
 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
 #  define WIN32_WCE_OLD
 #endif
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-#  if defined(WIN32_WCE_OLD)
-/* strtod() function is not supported on WindowsCE */
-__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
+#  ifdef WIN32_WCE_OLD
+/* The strtod() function is not supported on WindowsCE */
+__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr,
+    char **endptr)
 {
    double result = 0;
    int len;
    wchar_t *str, *end;
 
    len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
-   str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t));
+   str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
    if ( NULL != str )
    {
       MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
@@ -49,7 +53,15 @@ __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **end
 png_uint_32 PNGAPI
 png_get_uint_31(png_structp png_ptr, png_bytep buf)
 {
+#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
    png_uint_32 i = png_get_uint_32(buf);
+#else
+   /* Avoid an extra function call by inlining the result. */
+   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
+      ((png_uint_32)(*(buf + 1)) << 16) +
+      ((png_uint_32)(*(buf + 2)) << 8) +
+      (png_uint_32)(*(buf + 3));
+#endif
    if (i > PNG_UINT_31_MAX)
      png_error(png_ptr, "PNG unsigned integer out of range.");
    return (i);
@@ -69,7 +81,8 @@ png_get_uint_32(png_bytep buf)
 
 /* Grab a signed 32-bit integer from a buffer in big-endian format.  The
  * data is stored in the PNG file in two's complement format, and it is
- * assumed that the machine format for signed integers is the same. */
+ * assumed that the machine format for signed integers is the same.
+ */
 png_int_32 PNGAPI
 png_get_int_32(png_bytep buf)
 {
@@ -92,19 +105,50 @@ png_get_uint_16(png_bytep buf)
 }
 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
 
+/* Read the chunk header (length + type name).
+ * Put the type name into png_ptr->chunk_name, and return the length.
+ */
+png_uint_32 /* PRIVATE */
+png_read_chunk_header(png_structp png_ptr)
+{
+   png_byte buf[8];
+   png_uint_32 length;
+
+   /* Read the length and the chunk name */
+   png_read_data(png_ptr, buf, 8);
+   length = png_get_uint_31(png_ptr, buf);
+
+   /* Put the chunk name into png_ptr->chunk_name */
+   png_memcpy(png_ptr->chunk_name, buf + 4, 4);
+
+   png_debug2(0, "Reading %s chunk, length = %lu",
+      png_ptr->chunk_name, length);
+
+   /* Reset the crc and run it over the chunk name */
+   png_reset_crc(png_ptr);
+   png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
+
+   /* Check to see if chunk name is valid */
+   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+
+   return length;
+}
+
 /* Read data, and (optionally) run it through the CRC. */
 void /* PRIVATE */
 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
    png_read_data(png_ptr, buf, length);
    png_calculate_crc(png_ptr, buf, length);
 }
 
 /* Optionally skip data and then check the CRC.  Depending on whether we
-   are reading a ancillary or critical chunk, and how the program has set
-   things up, we may calculate the CRC on the data and print a message.
-   Returns '1' if there was a CRC error, '0' otherwise. */
+ * are reading a ancillary or critical chunk, and how the program has set
+ * things up, we may calculate the CRC on the data and print a message.
+ * Returns '1' if there was a CRC error, '0' otherwise.
+ */
 int /* PRIVATE */
 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
 {
@@ -123,7 +167,7 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
    if (png_crc_error(png_ptr))
    {
       if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
-           !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
+          !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
           (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
           (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
       {
@@ -140,7 +184,8 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
 }
 
 /* Compare the CRC stored in the PNG file with that calculated by libpng from
-   the data it has read thus far. */
+ * the data it has read thus far.
+ */
 int /* PRIVATE */
 png_crc_error(png_structp png_ptr)
 {
@@ -173,177 +218,213 @@ png_crc_error(png_structp png_ptr)
 
 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
     defined(PNG_READ_iCCP_SUPPORTED)
-/*
- * Decompress trailing data in a chunk.  The assumption is that chunkdata
- * points at an allocated area holding the contents of a chunk with a
- * trailing compressed part.  What we get back is an allocated area
- * holding the original prefix part and an uncompressed version of the
- * trailing part (the malloc area passed in is freed).
- */
-png_charp /* PRIVATE */
-png_decompress_chunk(png_structp png_ptr, int comp_type,
-                              png_charp chunkdata, png_size_t chunklength,
-                              png_size_t prefix_size, png_size_t *newlength)
+static png_size_t
+png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
+        png_bytep output, png_size_t output_size)
 {
-   static PNG_CONST char msg[] = "Error decoding compressed text";
-   png_charp text;
-   png_size_t text_size;
+   png_size_t count = 0;
+
+   png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
+   png_ptr->zstream.avail_in = size;
 
-   if (comp_type == PNG_COMPRESSION_TYPE_BASE)
+   while (1)
    {
-      int ret = Z_OK;
-      png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
-      png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
+      int ret, avail;
+
+      /* Reset the output buffer each time round - we empty it
+       * after every inflate call.
+       */
       png_ptr->zstream.next_out = png_ptr->zbuf;
-      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
 
-      text_size = 0;
-      text = NULL;
+      ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
+      avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
 
-      while (png_ptr->zstream.avail_in)
+      /* First copy/count any new output - but only if we didn't
+       * get an error code.
+       */
+      if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
       {
-         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-         if (ret != Z_OK && ret != Z_STREAM_END)
+         if (output != 0 && output_size > count)
          {
-            if (png_ptr->zstream.msg != NULL)
-               png_warning(png_ptr, png_ptr->zstream.msg);
-            else
-               png_warning(png_ptr, msg);
-            inflateReset(&png_ptr->zstream);
-            png_ptr->zstream.avail_in = 0;
+            png_size_t copy = output_size - count;
+            if ((png_size_t) avail < copy) copy = (png_size_t) avail;
+            png_memcpy(output + count, png_ptr->zbuf, copy);
+         }
+         count += avail;
+      }
 
-            if (text ==  NULL)
-            {
-               text_size = prefix_size + png_sizeof(msg) + 1;
-               text = (png_charp)png_malloc_warn(png_ptr, text_size);
-               if (text ==  NULL)
-                 {
-                    png_free(png_ptr,chunkdata);
-                    png_error(png_ptr,"Not enough memory to decompress chunk");
-                 }
-               png_memcpy(text, chunkdata, prefix_size);
-            }
+      if (ret == Z_OK)
+         continue;
 
-            text[text_size - 1] = 0x00;
+      /* Termination conditions - always reset the zstream, it
+       * must be left in inflateInit state.
+       */
+      png_ptr->zstream.avail_in = 0;
+      inflateReset(&png_ptr->zstream);
 
-            /* Copy what we can of the error message into the text chunk */
-            text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
-            text_size = png_sizeof(msg) > text_size ? text_size :
-               png_sizeof(msg);
-            png_memcpy(text + prefix_size, msg, text_size + 1);
-            break;
-         }
-         if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
+      if (ret == Z_STREAM_END)
+         return count; /* NOTE: may be zero. */
+
+      /* Now handle the error codes - the API always returns 0
+       * and the error message is dumped into the uncompressed
+       * buffer if available.
+       */
+      {
+         PNG_CONST char *msg;
+         if (png_ptr->zstream.msg != 0)
+            msg = png_ptr->zstream.msg;
+         else
          {
-            if (text == NULL)
-            {
-               text_size = prefix_size +
-                   png_ptr->zbuf_size - png_ptr->zstream.avail_out;
-               text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
-               if (text ==  NULL)
-                 {
-                    png_free(png_ptr,chunkdata);
-                    png_error(png_ptr,"Not enough memory to decompress chunk.");
-                 }
-               png_memcpy(text + prefix_size, png_ptr->zbuf,
-                    text_size - prefix_size);
-               png_memcpy(text, chunkdata, prefix_size);
-               *(text + text_size) = 0x00;
-            }
-            else
-            {
-               png_charp tmp;
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+            char umsg[52];
 
-               tmp = text;
-               text = (png_charp)png_malloc_warn(png_ptr,
-                  (png_uint_32)(text_size +
-                  png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
-               if (text == NULL)
-               {
-                  png_free(png_ptr, tmp);
-                  png_free(png_ptr, chunkdata);
-                  png_error(png_ptr,"Not enough memory to decompress chunk..");
-               }
-               png_memcpy(text, tmp, text_size);
-               png_free(png_ptr, tmp);
-               png_memcpy(text + text_size, png_ptr->zbuf,
-                  (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
-               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
-               *(text + text_size) = 0x00;
-            }
-            if (ret == Z_STREAM_END)
-               break;
-            else
+            switch (ret)
             {
-               png_ptr->zstream.next_out = png_ptr->zbuf;
-               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+               case Z_BUF_ERROR:
+                  msg = "Buffer error in compressed datastream in %s chunk";
+                  break;
+               case Z_DATA_ERROR:
+                  msg = "Data error in compressed datastream in %s chunk";
+                  break;
+               default:
+                  msg = "Incomplete compressed datastream in %s chunk";
+                  break;
             }
-         }
-      }
-      if (ret != Z_STREAM_END)
-      {
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
-         char umsg[52];
-
-         if (ret == Z_BUF_ERROR)
-            png_snprintf(umsg, 52,
-                "Buffer error in compressed datastream in %s chunk",
-                png_ptr->chunk_name);
-         else if (ret == Z_DATA_ERROR)
-            png_snprintf(umsg, 52,
-                "Data error in compressed datastream in %s chunk",
-                png_ptr->chunk_name);
-         else
-            png_snprintf(umsg, 52,
-                "Incomplete compressed datastream in %s chunk",
-                png_ptr->chunk_name);
-         png_warning(png_ptr, umsg);
+
+            png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
+            msg = umsg;
 #else
-         png_warning(png_ptr,
-            "Incomplete compressed datastream in chunk other than IDAT");
+            msg = "Damaged compressed datastream in chunk other than IDAT";
 #endif
-         text_size=prefix_size;
-         if (text ==  NULL)
-         {
-            text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
-            if (text == NULL)
-              {
-                png_free(png_ptr, chunkdata);
-                png_error(png_ptr,"Not enough memory for text.");
-              }
-            png_memcpy(text, chunkdata, prefix_size);
          }
-         *(text + text_size) = 0x00;
+
+         png_warning(png_ptr, msg);
       }
 
-      inflateReset(&png_ptr->zstream);
-      png_ptr->zstream.avail_in = 0;
+      /* 0 means an error - notice that this code simple ignores
+       * zero length compressed chunks as a result.
+       */
+      return 0;
+   }
+}
+
+/*
+ * Decompress trailing data in a chunk.  The assumption is that chunkdata
+ * points at an allocated area holding the contents of a chunk with a
+ * trailing compressed part.  What we get back is an allocated area
+ * holding the original prefix part and an uncompressed version of the
+ * trailing part (the malloc area passed in is freed).
+ */
+void /* PRIVATE */
+png_decompress_chunk(png_structp png_ptr, int comp_type,
+    png_size_t chunklength,
+    png_size_t prefix_size, png_size_t *newlength)
+{
+   /* The caller should guarantee this */
+   if (prefix_size > chunklength)
+   {
+      /* The recovery is to delete the chunk. */
+      png_warning(png_ptr, "invalid chunklength");
+      prefix_size = 0; /* To delete everything */
+   }
+
+   else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
+   {
+      png_size_t expanded_size = png_inflate(png_ptr,
+                (png_bytep)(png_ptr->chunkdata + prefix_size),
+                chunklength - prefix_size,
+                0/*output*/, 0/*output size*/);
+
+      /* Now check the limits on this chunk - if the limit fails the
+       * compressed data will be removed, the prefix will remain.
+       */
+      if (prefix_size >= (~(png_size_t)0) - 1 ||
+         expanded_size >= (~(png_size_t)0) - 1 - prefix_size
+#ifdef PNG_USER_CHUNK_MALLOC_MAX
+         || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
+          prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
+#endif
+          )
+         png_warning(png_ptr, "Exceeded size limit while expanding chunk");
+
+      /* If the size is zero either there was an error and a message
+       * has already been output (warning) or the size really is zero
+       * and we have nothing to do - the code will exit through the
+       * error case below.
+       */
+      else if (expanded_size > 0)
+      {
+         /* Success (maybe) - really uncompress the chunk. */
+         png_size_t new_size = 0;
 
-      png_free(png_ptr, chunkdata);
-      chunkdata = text;
-      *newlength=text_size;
+         png_charp text = png_malloc_warn(png_ptr,
+             prefix_size + expanded_size + 1);
+
+         if (text != NULL)
+         {
+            png_memcpy(text, png_ptr->chunkdata, prefix_size);
+            new_size = png_inflate(png_ptr,
+                (png_bytep)(png_ptr->chunkdata + prefix_size),
+                chunklength - prefix_size,
+                (png_bytep)(text + prefix_size), expanded_size);
+            text[prefix_size + expanded_size] = 0; /* just in case */
+
+            if (new_size == expanded_size)
+            {
+               png_free(png_ptr, png_ptr->chunkdata);
+               png_ptr->chunkdata = text;
+               *newlength = prefix_size + expanded_size;
+               return; /* The success return! */
+            }
+
+            png_warning(png_ptr, "png_inflate logic error");
+            png_free(png_ptr, text);
+         }
+         else
+          png_warning(png_ptr, "Not enough memory to decompress chunk.");
+      }
    }
+
    else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
    {
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
       char umsg[50];
 
-      png_snprintf(umsg, 50,
-         "Unknown zTXt compression type %d", comp_type);
+      png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
+          comp_type);
       png_warning(png_ptr, umsg);
 #else
       png_warning(png_ptr, "Unknown zTXt compression type");
 #endif
 
-      *(chunkdata + prefix_size) = 0x00;
-      *newlength=prefix_size;
+      /* The recovery is to simply drop the data. */
    }
 
-   return chunkdata;
+   /* Generic error return - leave the prefix, delete the compressed
+    * data, reallocate the chunkdata to remove the potentially large
+    * amount of compressed data.
+    */
+   {
+      png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
+      if (text != NULL)
+      {
+         if (prefix_size > 0)
+            png_memcpy(text, png_ptr->chunkdata, prefix_size);
+         png_free(png_ptr, png_ptr->chunkdata);
+         png_ptr->chunkdata = text;
+
+         /* This is an extra zero in the 'uncompressed' part. */
+         *(png_ptr->chunkdata + prefix_size) = 0x00;
+      }
+      /* Ignore a malloc error here - it is safe. */
+   }
+
+   *newlength = prefix_size;
 }
 #endif
 
-/* read and check the IDHR chunk */
+/* Read and check the IDHR chunk */
 void /* PRIVATE */
 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
@@ -352,12 +433,12 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    int bit_depth, color_type, compression_type, filter_type;
    int interlace_type;
 
-   png_debug(1, "in png_handle_IHDR\n");
+   png_debug(1, "in png_handle_IHDR");
 
    if (png_ptr->mode & PNG_HAVE_IHDR)
       png_error(png_ptr, "Out of place IHDR");
 
-   /* check the length */
+   /* Check the length */
    if (length != 13)
       png_error(png_ptr, "Invalid IHDR chunk");
 
@@ -374,66 +455,71 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    filter_type = buf[11];
    interlace_type = buf[12];
 
-   /* set internal variables */
+   /* Set internal variables */
    png_ptr->width = width;
    png_ptr->height = height;
    png_ptr->bit_depth = (png_byte)bit_depth;
    png_ptr->interlaced = (png_byte)interlace_type;
    png_ptr->color_type = (png_byte)color_type;
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
    png_ptr->filter_type = (png_byte)filter_type;
 #endif
    png_ptr->compression_type = (png_byte)compression_type;
 
-   /* find number of channels */
+   /* Find number of channels */
    switch (png_ptr->color_type)
    {
       case PNG_COLOR_TYPE_GRAY:
       case PNG_COLOR_TYPE_PALETTE:
          png_ptr->channels = 1;
          break;
+
       case PNG_COLOR_TYPE_RGB:
          png_ptr->channels = 3;
          break;
+
       case PNG_COLOR_TYPE_GRAY_ALPHA:
          png_ptr->channels = 2;
          break;
+
       case PNG_COLOR_TYPE_RGB_ALPHA:
          png_ptr->channels = 4;
          break;
    }
 
-   /* set up other useful info */
+   /* Set up other useful info */
    png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
    png_ptr->channels);
-   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
-   png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
-   png_debug1(3,"channels = %d\n", png_ptr->channels);
-   png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
+   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
+   png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
+   png_debug1(3, "channels = %d", png_ptr->channels);
+   png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
       color_type, interlace_type, compression_type, filter_type);
 }
 
-/* read and check the palette */
+/* Read and check the palette */
 void /* PRIVATE */
 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_color palette[PNG_MAX_PALETTE_LENGTH];
    int num, i;
-#ifndef PNG_NO_POINTER_INDEXING
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
    png_colorp pal_ptr;
 #endif
 
-   png_debug(1, "in png_handle_PLTE\n");
+   png_debug(1, "in png_handle_PLTE");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before PLTE");
+
    else if (png_ptr->mode & PNG_HAVE_IDAT)
    {
       png_warning(png_ptr, "Invalid PLTE after IDAT");
       png_crc_finish(png_ptr, length);
       return;
    }
+
    else if (png_ptr->mode & PNG_HAVE_PLTE)
       png_error(png_ptr, "Duplicate PLTE chunk");
 
@@ -446,7 +532,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       png_crc_finish(png_ptr, length);
       return;
    }
-#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+#ifndef PNG_READ_OPT_PLTE_SUPPORTED
    if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
    {
       png_crc_finish(png_ptr, length);
@@ -462,6 +548,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
          png_crc_finish(png_ptr, length);
          return;
       }
+
       else
       {
          png_error(png_ptr, "Invalid palette chunk");
@@ -470,7 +557,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    num = (int)length / 3;
 
-#ifndef PNG_NO_POINTER_INDEXING
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
    for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
    {
       png_byte buf[3];
@@ -486,7 +573,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       png_byte buf[3];
 
       png_crc_read(png_ptr, buf, 3);
-      /* don't depend upon png_color being any order */
+      /* Don't depend upon png_color being any order */
       palette[i].red = buf[0];
       palette[i].green = buf[1];
       palette[i].blue = buf[2];
@@ -494,16 +581,17 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 #endif
 
    /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
-      whatever the normal CRC configuration tells us.  However, if we
-      have an RGB image, the PLTE can be considered ancillary, so
-      we will act as though it is. */
-#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+    * whatever the normal CRC configuration tells us.  However, if we
+    * have an RGB image, the PLTE can be considered ancillary, so
+    * we will act as though it is.
+    */
+#ifndef PNG_READ_OPT_PLTE_SUPPORTED
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
 #endif
    {
       png_crc_finish(png_ptr, 0);
    }
-#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+#ifndef PNG_READ_OPT_PLTE_SUPPORTED
    else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
    {
       /* If we don't want to use the data from an ancillary chunk,
@@ -532,7 +620,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    png_set_PLTE(png_ptr, info_ptr, palette, num);
 
-#if defined(PNG_READ_tRNS_SUPPORTED)
+#ifdef PNG_READ_tRNS_SUPPORTED
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
       if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
@@ -556,7 +644,7 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 void /* PRIVATE */
 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_debug(1, "in png_handle_IEND\n");
+   png_debug(1, "in png_handle_IEND");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
    {
@@ -571,10 +659,10 @@ png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
    png_crc_finish(png_ptr, length);
 
-   info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */
+   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
 }
 
-#if defined(PNG_READ_gAMA_SUPPORTED)
+#ifdef PNG_READ_gAMA_SUPPORTED
 void /* PRIVATE */
 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
@@ -584,7 +672,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 #endif
    png_byte buf[4];
 
-   png_debug(1, "in png_handle_gAMA\n");
+   png_debug(1, "in png_handle_gAMA");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before gAMA");
@@ -599,7 +687,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       png_warning(png_ptr, "Out of place gAMA chunk");
 
    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
       && !(info_ptr->valid & PNG_INFO_sRGB)
 #endif
       )
@@ -621,7 +709,7 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
 
    igamma = (png_fixed_point)png_get_uint_32(buf);
-   /* check for zero gamma */
+   /* Check for zero gamma */
    if (igamma == 0)
       {
          png_warning(png_ptr,
@@ -629,14 +717,14 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
          return;
       }
 
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
       if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
       {
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
-#ifndef PNG_NO_CONSOLE_IO
-         fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
+#ifdef PNG_CONSOLE_IO_SUPPORTED
+         fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
 #endif
          return;
       }
@@ -655,14 +743,14 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_sBIT_SUPPORTED)
+#ifdef PNG_READ_sBIT_SUPPORTED
 void /* PRIVATE */
 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_size_t truelen;
    png_byte buf[4];
 
-   png_debug(1, "in png_handle_sBIT\n");
+   png_debug(1, "in png_handle_sBIT");
 
    buf[0] = buf[1] = buf[2] = buf[3] = 0;
 
@@ -721,11 +809,11 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_cHRM_SUPPORTED)
+#ifdef PNG_READ_cHRM_SUPPORTED
 void /* PRIVATE */
 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_byte buf[4];
+   png_byte buf[32];
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
 #endif
@@ -734,7 +822,7 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    png_uint_32 uint_x, uint_y;
 
-   png_debug(1, "in png_handle_cHRM\n");
+   png_debug(1, "in png_handle_cHRM");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before cHRM");
@@ -749,7 +837,7 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       png_warning(png_ptr, "Missing PLTE before cHRM");
 
    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
       && !(info_ptr->valid & PNG_INFO_sRGB)
 #endif
       )
@@ -766,64 +854,27 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_x = png_get_uint_32(buf);
-
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x > 80000L || uint_y > 80000L ||
-      uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM white point");
-      png_crc_finish(png_ptr, 24);
+   png_crc_read(png_ptr, buf, 32);
+   if (png_crc_finish(png_ptr, 0))
       return;
-   }
-   int_x_white = (png_fixed_point)uint_x;
-   int_y_white = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
    uint_x = png_get_uint_32(buf);
+   uint_y = png_get_uint_32(buf + 4);
+   int_x_white = (png_fixed_point)uint_x;
+   int_y_white = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM red point");
-      png_crc_finish(png_ptr, 16);
-      return;
-   }
+   uint_x = png_get_uint_32(buf + 8);
+   uint_y = png_get_uint_32(buf + 12);
    int_x_red = (png_fixed_point)uint_x;
    int_y_red = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_x = png_get_uint_32(buf);
-
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM green point");
-      png_crc_finish(png_ptr, 8);
-      return;
-   }
+   uint_x = png_get_uint_32(buf + 16);
+   uint_y = png_get_uint_32(buf + 20);
    int_x_green = (png_fixed_point)uint_x;
    int_y_green = (png_fixed_point)uint_y;
 
-   png_crc_read(png_ptr, buf, 4);
-   uint_x = png_get_uint_32(buf);
-
-   png_crc_read(png_ptr, buf, 4);
-   uint_y = png_get_uint_32(buf);
-
-   if (uint_x + uint_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid cHRM blue point");
-      png_crc_finish(png_ptr, 0);
-      return;
-   }
+   uint_x = png_get_uint_32(buf + 24);
+   uint_y = png_get_uint_32(buf + 28);
    int_x_blue = (png_fixed_point)uint_x;
    int_y_blue = (png_fixed_point)uint_y;
 
@@ -838,7 +889,7 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    blue_y  = (float)int_y_blue  / (float)100000.0;
 #endif
 
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
    if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
       {
       if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
@@ -852,21 +903,22 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
          {
             png_warning(png_ptr,
               "Ignoring incorrect cHRM value when sRGB is also present");
-#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_CONSOLE_IO_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-            fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
+            fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
                white_x, white_y, red_x, red_y);
-            fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
+            fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
                green_x, green_y, blue_x, blue_y);
 #else
-            fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
-               int_x_white, int_y_white, int_x_red, int_y_red);
-            fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
-               int_x_green, int_y_green, int_x_blue, int_y_blue);
-#endif
-#endif /* PNG_NO_CONSOLE_IO */
+            fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
+               (long)int_x_white, (long)int_y_white,
+               (long)int_x_red, (long)int_y_red);
+            fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
+               (long)int_x_green, (long)int_y_green,
+               (long)int_x_blue, (long)int_y_blue);
+#endif
+#endif /* PNG_CONSOLE_IO_SUPPORTED */
          }
-         png_crc_finish(png_ptr, 0);
          return;
       }
 #endif /* PNG_READ_sRGB_SUPPORTED */
@@ -880,19 +932,17 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
       int_y_green, int_x_blue, int_y_blue);
 #endif
-   if (png_crc_finish(png_ptr, 0))
-      return;
 }
 #endif
 
-#if defined(PNG_READ_sRGB_SUPPORTED)
+#ifdef PNG_READ_sRGB_SUPPORTED
 void /* PRIVATE */
 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    int intent;
    png_byte buf[1];
 
-   png_debug(1, "in png_handle_sRGB\n");
+   png_debug(1, "in png_handle_sRGB");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before sRGB");
@@ -925,7 +975,7 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
 
    intent = buf[0];
-   /* check for bad intent */
+   /* Check for bad intent */
    if (intent >= PNG_sRGB_INTENT_LAST)
    {
       png_warning(png_ptr, "Unknown sRGB intent");
@@ -947,12 +997,13 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       {
          png_warning(png_ptr,
            "Ignoring incorrect gAMA value when sRGB is also present");
-#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_CONSOLE_IO_SUPPORTED
 #  ifdef PNG_FIXED_POINT_SUPPORTED
-         fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
+         fprintf(stderr, "incorrect gamma=(%d/100000)\n",
+            (int)png_ptr->int_gamma);
 #  else
 #    ifdef PNG_FLOATING_POINT_SUPPORTED
-         fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
+         fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
 #    endif
 #  endif
 #endif
@@ -982,12 +1033,11 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif /* PNG_READ_sRGB_SUPPORTED */
 
-#if defined(PNG_READ_iCCP_SUPPORTED)
+#ifdef PNG_READ_iCCP_SUPPORTED
 void /* PRIVATE */
 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 /* Note: this does not properly handle chunks that are > 64K under DOS */
 {
-   png_charp chunkdata;
    png_byte compression_type;
    png_bytep pC;
    png_charp profile;
@@ -995,7 +1045,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_uint_32 profile_size, profile_length;
    png_size_t slength, prefix_length, data_length;
 
-   png_debug(1, "in png_handle_iCCP\n");
+   png_debug(1, "in png_handle_iCCP");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before iCCP");
@@ -1025,93 +1075,117 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, skip))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (profile = chunkdata; *profile; profile++)
-      /* empty loop to find end of name */ ;
+   for (profile = png_ptr->chunkdata; *profile; profile++)
+      /* Empty loop to find end of name */ ;
 
    ++profile;
 
-   /* there should be at least one zero (the compression type byte)
-      following the separator, and we should be on it  */
-   if ( profile >= chunkdata + slength - 1)
+   /* There should be at least one zero (the compression type byte)
+    * following the separator, and we should be on it
+    */
+   if ( profile >= png_ptr->chunkdata + slength - 1)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "Malformed iCCP chunk");
       return;
    }
 
-   /* compression_type should always be zero */
+   /* Compression_type should always be zero */
    compression_type = *profile++;
    if (compression_type)
    {
       png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
-      compression_type=0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
+      compression_type = 0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
                                  wrote nonzero) */
    }
 
-   prefix_length = profile - chunkdata;
-   chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
-                                    slength, prefix_length, &data_length);
+   prefix_length = profile - png_ptr->chunkdata;
+   png_decompress_chunk(png_ptr, compression_type,
+     slength, prefix_length, &data_length);
 
    profile_length = data_length - prefix_length;
 
    if ( prefix_length > data_length || profile_length < 4)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "Profile size field missing from iCCP chunk");
       return;
    }
 
    /* Check the profile_size recorded in the first 32 bits of the ICC profile */
-   pC = (png_bytep)(chunkdata+prefix_length);
-   profile_size = ((*(pC  ))<<24) |
-                  ((*(pC+1))<<16) |
-                  ((*(pC+2))<< 8) |
-                  ((*(pC+3))    );
+   pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
+   profile_size = ((*(pC    ))<<24) |
+                  ((*(pC + 1))<<16) |
+                  ((*(pC + 2))<< 8) |
+                  ((*(pC + 3))    );
 
-   if(profile_size < profile_length)
+   if (profile_size < profile_length)
       profile_length = profile_size;
 
-   if(profile_size > profile_length)
+   if (profile_size > profile_length)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "Ignoring truncated iCCP profile.");
       return;
    }
 
-   png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
-                chunkdata + prefix_length, profile_length);
-   png_free(png_ptr, chunkdata);
+   png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
+     compression_type, png_ptr->chunkdata + prefix_length, profile_length);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
 }
 #endif /* PNG_READ_iCCP_SUPPORTED */
 
-#if defined(PNG_READ_sPLT_SUPPORTED)
+#ifdef PNG_READ_sPLT_SUPPORTED
 void /* PRIVATE */
 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 /* Note: this does not properly handle chunks that are > 64K under DOS */
 {
-   png_bytep chunkdata;
    png_bytep entry_start;
    png_sPLT_t new_palette;
-#ifdef PNG_NO_POINTER_INDEXING
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
    png_sPLT_entryp pp;
 #endif
    int data_length, entry_size, i;
    png_uint_32 skip = 0;
    png_size_t slength;
 
-   png_debug(1, "in png_handle_sPLT\n");
+   png_debug(1, "in png_handle_sPLT");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+
+   if (png_ptr->user_chunk_cache_max != 0)
+   {
+      if (png_ptr->user_chunk_cache_max == 1)
+      {
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      if (--png_ptr->user_chunk_cache_max == 1)
+      {
+         png_warning(png_ptr, "No space in chunk cache for sPLT");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+   }
+#endif
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before sPLT");
@@ -1131,45 +1205,50 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, skip))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (entry_start = chunkdata; *entry_start; entry_start++)
-      /* empty loop to find end of name */ ;
+   for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
+       entry_start++)
+      /* Empty loop to find end of name */ ;
    ++entry_start;
 
-   /* a sample depth should follow the separator, and we should be on it  */
-   if (entry_start > chunkdata + slength - 2)
+   /* A sample depth should follow the separator, and we should be on it  */
+   if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "malformed sPLT chunk");
       return;
    }
 
    new_palette.depth = *entry_start++;
    entry_size = (new_palette.depth == 8 ? 6 : 10);
-   data_length = (slength - (entry_start - chunkdata));
+   data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
 
-   /* integrity-check the data length */
+   /* Integrity-check the data length */
    if (data_length % entry_size)
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       png_warning(png_ptr, "sPLT chunk has bad length");
       return;
    }
 
    new_palette.nentries = (png_int_32) ( data_length / entry_size);
-   if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
-       png_sizeof(png_sPLT_entry)))
+   if ((png_uint_32) new_palette.nentries >
+       (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
    {
        png_warning(png_ptr, "sPLT chunk too long");
        return;
@@ -1182,10 +1261,10 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
        return;
    }
 
-#ifndef PNG_NO_POINTER_INDEXING
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
    for (i = 0; i < new_palette.nentries; i++)
    {
-      png_sPLT_entryp pp = new_palette.entries + i;
+      pp = new_palette.entries + i;
 
       if (new_palette.depth == 8)
       {
@@ -1226,29 +1305,24 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   /* discard all chunk data except the name and stash that */
-   new_palette.name = (png_charp)chunkdata;
+   /* Discard all chunk data except the name and stash that */
+   new_palette.name = png_ptr->chunkdata;
 
    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
 
-   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    png_free(png_ptr, new_palette.entries);
 }
 #endif /* PNG_READ_sPLT_SUPPORTED */
 
-#if defined(PNG_READ_tRNS_SUPPORTED)
+#ifdef PNG_READ_tRNS_SUPPORTED
 void /* PRIVATE */
 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
-   int bit_mask;
-
-   png_debug(1, "in png_handle_tRNS\n");
 
-   /* For non-indexed color, mask off any bits in the tRNS value that
-    * exceed the bit depth.  Some creators were writing extra bits there.
-    * This is not needed for indexed color. */
-   bit_mask = (1 << png_ptr->bit_depth) - 1;
+   png_debug(1, "in png_handle_tRNS");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before tRNS");
@@ -1278,7 +1352,7 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
       png_crc_read(png_ptr, buf, 2);
       png_ptr->num_trans = 1;
-      png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask;
+      png_ptr->trans_values.gray = png_get_uint_16(buf);
    }
    else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
    {
@@ -1292,9 +1366,9 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       }
       png_crc_read(png_ptr, buf, (png_size_t)length);
       png_ptr->num_trans = 1;
-      png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask;
-      png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask;
-      png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask;
+      png_ptr->trans_values.red = png_get_uint_16(buf);
+      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
+      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
    }
    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
@@ -1337,14 +1411,14 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_bKGD_SUPPORTED)
+#ifdef PNG_READ_bKGD_SUPPORTED
 void /* PRIVATE */
 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_size_t truelen;
    png_byte buf[6];
 
-   png_debug(1, "in png_handle_bKGD\n");
+   png_debug(1, "in png_handle_bKGD");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before bKGD");
@@ -1393,9 +1467,9 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
       png_ptr->background.index = buf[0];
-      if(info_ptr->num_palette)
+      if (info_ptr && info_ptr->num_palette)
       {
-          if(buf[0] > info_ptr->num_palette)
+          if (buf[0] >= info_ptr->num_palette)
           {
              png_warning(png_ptr, "Incorrect bKGD chunk index value");
              return;
@@ -1426,14 +1500,14 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_READ_hIST_SUPPORTED
 void /* PRIVATE */
 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    unsigned int num, i;
    png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
 
-   png_debug(1, "in png_handle_hIST\n");
+   png_debug(1, "in png_handle_hIST");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before hIST");
@@ -1456,15 +1530,16 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   num = length / 2 ;
-   if (num != (unsigned int) png_ptr->num_palette || num >
-      (unsigned int) PNG_MAX_PALETTE_LENGTH)
+   if (length > 2*PNG_MAX_PALETTE_LENGTH ||
+       length != (unsigned int) (2*png_ptr->num_palette))
    {
       png_warning(png_ptr, "Incorrect hIST chunk length");
       png_crc_finish(png_ptr, length);
       return;
    }
 
+   num = length / 2 ;
+
    for (i = 0; i < num; i++)
    {
       png_byte buf[2];
@@ -1480,7 +1555,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_pHYs_SUPPORTED)
+#ifdef PNG_READ_pHYs_SUPPORTED
 void /* PRIVATE */
 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
@@ -1488,7 +1563,7 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_uint_32 res_x, res_y;
    int unit_type;
 
-   png_debug(1, "in png_handle_pHYs\n");
+   png_debug(1, "in png_handle_pHYs");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before pHYs");
@@ -1523,7 +1598,7 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_oFFs_SUPPORTED)
+#ifdef PNG_READ_oFFs_SUPPORTED
 void /* PRIVATE */
 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
@@ -1531,7 +1606,7 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_int_32 offset_x, offset_y;
    int unit_type;
 
-   png_debug(1, "in png_handle_oFFs\n");
+   png_debug(1, "in png_handle_oFFs");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before oFFs");
@@ -1566,12 +1641,11 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_pCAL_SUPPORTED)
-/* read the pCAL chunk (described in the PNG Extensions document) */
+#ifdef PNG_READ_pCAL_SUPPORTED
+/* Read the pCAL chunk (described in the PNG Extensions document) */
 void /* PRIVATE */
 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_charp purpose;
    png_int_32 X0, X1;
    png_byte type, nparams;
    png_charp buf, units, endptr;
@@ -1579,7 +1653,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_size_t slength;
    int i;
 
-   png_debug(1, "in png_handle_pCAL\n");
+   png_debug(1, "in png_handle_pCAL");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before pCAL");
@@ -1596,48 +1670,51 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
+   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
       length + 1);
-   purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (purpose == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
      {
        png_warning(png_ptr, "No memory for pCAL purpose.");
        return;
      }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)purpose, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, purpose);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   purpose[slength] = 0x00; /* null terminate the last string */
+   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
 
-   png_debug(3, "Finding end of pCAL purpose string\n");
-   for (buf = purpose; *buf; buf++)
-      /* empty loop */ ;
+   png_debug(3, "Finding end of pCAL purpose string");
+   for (buf = png_ptr->chunkdata; *buf; buf++)
+      /* Empty loop */ ;
 
-   endptr = purpose + slength;
+   endptr = png_ptr->chunkdata + slength;
 
    /* We need to have at least 12 bytes after the purpose string
       in order to get the parameter information. */
    if (endptr <= buf + 12)
    {
       png_warning(png_ptr, "Invalid pCAL data");
-      png_free(png_ptr, purpose);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
+   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
    X0 = png_get_int_32((png_bytep)buf+1);
    X1 = png_get_int_32((png_bytep)buf+5);
    type = buf[9];
    nparams = buf[10];
    units = buf + 11;
 
-   png_debug(3, "Checking pCAL equation type and number of parameters\n");
+   png_debug(3, "Checking pCAL equation type and number of parameters");
    /* Check that we have the right number of parameters for known
       equation types. */
    if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
@@ -1646,7 +1723,8 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
    {
       png_warning(png_ptr, "Invalid pCAL parameters for equation type");
-      png_free(png_ptr, purpose);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
    else if (type >= PNG_EQUATION_LAST)
@@ -1657,12 +1735,13 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    for (buf = units; *buf; buf++)
       /* Empty loop to move past the units string. */ ;
 
-   png_debug(3, "Allocating pCAL parameters array\n");
-   params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
-      *png_sizeof(png_charp))) ;
+   png_debug(3, "Allocating pCAL parameters array");
+   params = (png_charpp)png_malloc_warn(png_ptr,
+      (png_uint_32)(nparams * png_sizeof(png_charp))) ;
    if (params == NULL)
      {
-       png_free(png_ptr, purpose);
+       png_free(png_ptr, png_ptr->chunkdata);
+       png_ptr->chunkdata = NULL;
        png_warning(png_ptr, "No memory for pCAL params.");
        return;
      }
@@ -1672,7 +1751,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    {
       buf++; /* Skip the null string terminator from previous parameter. */
 
-      png_debug1(3, "Reading pCAL parameter %d\n", i);
+      png_debug1(3, "Reading pCAL parameter %d", i);
       for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
          /* Empty loop to move past each parameter string */ ;
 
@@ -1680,26 +1759,28 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       if (buf > endptr)
       {
          png_warning(png_ptr, "Invalid pCAL data");
-         png_free(png_ptr, purpose);
+         png_free(png_ptr, png_ptr->chunkdata);
+         png_ptr->chunkdata = NULL;
          png_free(png_ptr, params);
          return;
       }
    }
 
-   png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
+   png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
       units, params);
 
-   png_free(png_ptr, purpose);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    png_free(png_ptr, params);
 }
 #endif
 
-#if defined(PNG_READ_sCAL_SUPPORTED)
-/* read the sCAL chunk */
+#ifdef PNG_READ_sCAL_SUPPORTED
+/* Read the sCAL chunk */
 void /* PRIVATE */
 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
-   png_charp buffer, ep;
+   png_charp ep;
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    double width, height;
    png_charp vp;
@@ -1710,7 +1791,7 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 #endif
    png_size_t slength;
 
-   png_debug(1, "in png_handle_sCAL\n");
+   png_debug(1, "in png_handle_sCAL");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before sCAL");
@@ -1727,88 +1808,113 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       return;
    }
 
-   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
+   /* Need unit type, width, \0, height: minimum 4 bytes */
+   else if (length < 4)
+   {
+      png_warning(png_ptr, "sCAL chunk too short");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
       length + 1);
-   buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (buffer == NULL)
-     {
-       png_warning(png_ptr, "Out of memory while processing sCAL chunk");
-       return;
-     }
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
+   {
+      png_warning(png_ptr, "Out of memory while processing sCAL chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)buffer, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, buffer);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   buffer[slength] = 0x00; /* null terminate the last string */
+   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
 
-   ep = buffer + 1;        /* skip unit byte */
+   ep = png_ptr->chunkdata + 1;        /* Skip unit byte */
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    width = png_strtod(png_ptr, ep, &vp);
    if (*vp)
    {
-       png_warning(png_ptr, "malformed width string in sCAL chunk");
-       return;
+      png_warning(png_ptr, "malformed width string in sCAL chunk");
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
+      return;
    }
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
    swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
    if (swidth == NULL)
-     {
-       png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
-       return;
-     }
-   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
+   {
+      png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
+      return;
+   }
+   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep) + 1);
 #endif
 #endif
 
-   for (ep = buffer; *ep; ep++)
-      /* empty loop */ ;
+   for (ep = png_ptr->chunkdata + 1; *ep; ep++)
+      /* Empty loop */ ;
    ep++;
 
-   if (buffer + slength < ep)
+   if (png_ptr->chunkdata + slength < ep)
    {
-       png_warning(png_ptr, "Truncated sCAL chunk");
-#if defined(PNG_FIXED_POINT_SUPPORTED) && \
-    !defined(PNG_FLOATING_POINT_SUPPORTED)
-       png_free(png_ptr, swidth);
+      png_warning(png_ptr, "Truncated sCAL chunk");
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+      png_free(png_ptr, swidth);
 #endif
-      png_free(png_ptr, buffer);
-       return;
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
+      return;
    }
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    height = png_strtod(png_ptr, ep, &vp);
    if (*vp)
    {
-       png_warning(png_ptr, "malformed height string in sCAL chunk");
-       return;
+      png_warning(png_ptr, "malformed height string in sCAL chunk");
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+      png_free(png_ptr, swidth);
+#endif
+      return;
    }
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
    sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
-   if (swidth == NULL)
-     {
-       png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
-       return;
-     }
-   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
+   if (sheight == NULL)
+   {
+      png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+      png_free(png_ptr, swidth);
+#endif
+      return;
+   }
+   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep) + 1);
 #endif
 #endif
 
-   if (buffer + slength < ep
+   if (png_ptr->chunkdata + slength < ep
 #ifdef PNG_FLOATING_POINT_SUPPORTED
       || width <= 0. || height <= 0.
 #endif
       )
    {
       png_warning(png_ptr, "Invalid sCAL data");
-      png_free(png_ptr, buffer);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
       png_free(png_ptr, swidth);
       png_free(png_ptr, sheight);
@@ -1818,14 +1924,15 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
 
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-   png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
+   png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
+   png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
 #endif
 #endif
 
-   png_free(png_ptr, buffer);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
    png_free(png_ptr, swidth);
    png_free(png_ptr, sheight);
@@ -1833,14 +1940,14 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_tIME_SUPPORTED)
+#ifdef PNG_READ_tIME_SUPPORTED
 void /* PRIVATE */
 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_byte buf[7];
    png_time mod_time;
 
-   png_debug(1, "in png_handle_tIME\n");
+   png_debug(1, "in png_handle_tIME");
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Out of place tIME chunk");
@@ -1876,7 +1983,7 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 }
 #endif
 
-#if defined(PNG_READ_tEXt_SUPPORTED)
+#ifdef PNG_READ_tEXt_SUPPORTED
 /* Note: this does not properly handle chunks that are > 64K under DOS */
 void /* PRIVATE */
 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
@@ -1888,7 +1995,24 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    png_size_t slength;
    int ret;
 
-   png_debug(1, "in png_handle_tEXt\n");
+   png_debug(1, "in png_handle_tEXt");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+   if (png_ptr->user_chunk_cache_max != 0)
+   {
+      if (png_ptr->user_chunk_cache_max == 1)
+      {
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      if (--png_ptr->user_chunk_cache_max == 1)
+      {
+         png_warning(png_ptr, "No space in chunk cache for tEXt");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+   }
+#endif
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before tEXt");
@@ -1905,25 +2029,30 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 #endif
 
-   key = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (key == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
    {
      png_warning(png_ptr, "No memory to process text chunk.");
      return;
    }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)key, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
 
    if (png_crc_finish(png_ptr, skip))
    {
-      png_free(png_ptr, key);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
+   key = png_ptr->chunkdata;
+
    key[slength] = 0x00;
 
    for (text = key; *text; text++)
-      /* empty loop to find end of key */ ;
+      /* Empty loop to find end of key */ ;
 
    if (text != key + slength)
       text++;
@@ -1933,7 +2062,8 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    if (text_ptr == NULL)
    {
      png_warning(png_ptr, "Not enough memory to process text chunk.");
-     png_free(png_ptr, key);
+     png_free(png_ptr, png_ptr->chunkdata);
+     png_ptr->chunkdata = NULL;
      return;
    }
    text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
@@ -1946,28 +2076,46 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    text_ptr->text = text;
    text_ptr->text_length = png_strlen(text);
 
-   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
 
-   png_free(png_ptr, key);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    png_free(png_ptr, text_ptr);
    if (ret)
      png_warning(png_ptr, "Insufficient memory to process text chunk.");
 }
 #endif
 
-#if defined(PNG_READ_zTXt_SUPPORTED)
-/* note: this does not correctly handle chunks that are > 64K under DOS */
+#ifdef PNG_READ_zTXt_SUPPORTED
+/* Note: this does not correctly handle chunks that are > 64K under DOS */
 void /* PRIVATE */
 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_textp text_ptr;
-   png_charp chunkdata;
    png_charp text;
    int comp_type;
    int ret;
    png_size_t slength, prefix_len, data_len;
 
-   png_debug(1, "in png_handle_zTXt\n");
+   png_debug(1, "in png_handle_zTXt");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+   if (png_ptr->user_chunk_cache_max != 0)
+   {
+      if (png_ptr->user_chunk_cache_max == 1)
+      {
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      if (--png_ptr->user_chunk_cache_max == 1)
+      {
+         png_warning(png_ptr, "No space in chunk cache for zTXt");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+   }
+#endif
+
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before zTXt");
 
@@ -1979,36 +2127,39 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       there is no hard and fast rule to tell us where to stop. */
    if (length > (png_uint_32)65535L)
    {
-     png_warning(png_ptr,"zTXt chunk too large to fit in memory");
+     png_warning(png_ptr, "zTXt chunk too large to fit in memory");
      png_crc_finish(png_ptr, length);
      return;
    }
 #endif
 
-   chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (chunkdata == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
    {
-     png_warning(png_ptr,"Out of memory processing zTXt chunk.");
+     png_warning(png_ptr, "Out of memory processing zTXt chunk.");
      return;
    }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (text = chunkdata; *text; text++)
-      /* empty loop */ ;
+   for (text = png_ptr->chunkdata; *text; text++)
+      /* Empty loop */ ;
 
    /* zTXt must have some text after the chunkdataword */
-   if (text >= chunkdata + slength - 2)
+   if (text >= png_ptr->chunkdata + slength - 2)
    {
       png_warning(png_ptr, "Truncated zTXt chunk");
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
    else
@@ -2019,54 +2170,72 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
           png_warning(png_ptr, "Unknown compression type in zTXt chunk");
           comp_type = PNG_TEXT_COMPRESSION_zTXt;
        }
-       text++;        /* skip the compression_method byte */
+       text++;        /* Skip the compression_method byte */
    }
-   prefix_len = text - chunkdata;
+   prefix_len = text - png_ptr->chunkdata;
 
-   chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
-                                    (png_size_t)length, prefix_len, &data_len);
+   png_decompress_chunk(png_ptr, comp_type,
+     (png_size_t)length, prefix_len, &data_len);
 
    text_ptr = (png_textp)png_malloc_warn(png_ptr,
-     (png_uint_32)png_sizeof(png_text));
+      (png_uint_32)png_sizeof(png_text));
    if (text_ptr == NULL)
    {
-     png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
-     png_free(png_ptr, chunkdata);
+     png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
+     png_free(png_ptr, png_ptr->chunkdata);
+     png_ptr->chunkdata = NULL;
      return;
    }
    text_ptr->compression = comp_type;
-   text_ptr->key = chunkdata;
+   text_ptr->key = png_ptr->chunkdata;
 #ifdef PNG_iTXt_SUPPORTED
    text_ptr->lang = NULL;
    text_ptr->lang_key = NULL;
    text_ptr->itxt_length = 0;
 #endif
-   text_ptr->text = chunkdata + prefix_len;
+   text_ptr->text = png_ptr->chunkdata + prefix_len;
    text_ptr->text_length = data_len;
 
-   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
 
    png_free(png_ptr, text_ptr);
-   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    if (ret)
      png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
 }
 #endif
 
-#if defined(PNG_READ_iTXt_SUPPORTED)
-/* note: this does not correctly handle chunks that are > 64K under DOS */
+#ifdef PNG_READ_iTXt_SUPPORTED
+/* Note: this does not correctly handle chunks that are > 64K under DOS */
 void /* PRIVATE */
 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_textp text_ptr;
-   png_charp chunkdata;
    png_charp key, lang, text, lang_key;
    int comp_flag;
    int comp_type = 0;
    int ret;
    png_size_t slength, prefix_len, data_len;
 
-   png_debug(1, "in png_handle_iTXt\n");
+   png_debug(1, "in png_handle_iTXt");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+   if (png_ptr->user_chunk_cache_max != 0)
+   {
+      if (png_ptr->user_chunk_cache_max == 1)
+      {
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      if (--png_ptr->user_chunk_cache_max == 1)
+      {
+         png_warning(png_ptr, "No space in chunk cache for iTXt");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+   }
+#endif
 
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_error(png_ptr, "Missing IHDR before iTXt");
@@ -2079,40 +2248,44 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
       there is no hard and fast rule to tell us where to stop. */
    if (length > (png_uint_32)65535L)
    {
-     png_warning(png_ptr,"iTXt chunk too large to fit in memory");
+     png_warning(png_ptr, "iTXt chunk too large to fit in memory");
      png_crc_finish(png_ptr, length);
      return;
    }
 #endif
 
-   chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
-   if (chunkdata == NULL)
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+   if (png_ptr->chunkdata == NULL)
    {
      png_warning(png_ptr, "No memory to process iTXt chunk.");
      return;
    }
    slength = (png_size_t)length;
-   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
    if (png_crc_finish(png_ptr, 0))
    {
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   chunkdata[slength] = 0x00;
+   png_ptr->chunkdata[slength] = 0x00;
 
-   for (lang = chunkdata; *lang; lang++)
-      /* empty loop */ ;
-   lang++;        /* skip NUL separator */
+   for (lang = png_ptr->chunkdata; *lang; lang++)
+      /* Empty loop */ ;
+   lang++;        /* Skip NUL separator */
 
    /* iTXt must have a language tag (possibly empty), two compression bytes,
-      translated keyword (possibly empty), and possibly some text after the
-      keyword */
+    * translated keyword (possibly empty), and possibly some text after the
+    * keyword
+    */
 
-   if (lang >= chunkdata + slength - 3)
+   if (lang >= png_ptr->chunkdata + slength - 3)
    {
       png_warning(png_ptr, "Truncated iTXt chunk");
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
    else
@@ -2122,54 +2295,58 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    }
 
    for (lang_key = lang; *lang_key; lang_key++)
-      /* empty loop */ ;
-   lang_key++;        /* skip NUL separator */
+      /* Empty loop */ ;
+   lang_key++;        /* Skip NUL separator */
 
-   if (lang_key >= chunkdata + slength)
+   if (lang_key >= png_ptr->chunkdata + slength)
    {
       png_warning(png_ptr, "Truncated iTXt chunk");
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
    for (text = lang_key; *text; text++)
-      /* empty loop */ ;
-   text++;        /* skip NUL separator */
-   if (text >= chunkdata + slength)
+      /* Empty loop */ ;
+   text++;        /* Skip NUL separator */
+   if (text >= png_ptr->chunkdata + slength)
    {
       png_warning(png_ptr, "Malformed iTXt chunk");
-      png_free(png_ptr, chunkdata);
+      png_free(png_ptr, png_ptr->chunkdata);
+      png_ptr->chunkdata = NULL;
       return;
    }
 
-   prefix_len = text - chunkdata;
+   prefix_len = text - png_ptr->chunkdata;
 
-   key=chunkdata;
+   key=png_ptr->chunkdata;
    if (comp_flag)
-       chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
-          (size_t)length, prefix_len, &data_len);
+       png_decompress_chunk(png_ptr, comp_type,
+         (size_t)length, prefix_len, &data_len);
    else
-       data_len=png_strlen(chunkdata + prefix_len);
+       data_len = png_strlen(png_ptr->chunkdata + prefix_len);
    text_ptr = (png_textp)png_malloc_warn(png_ptr,
       (png_uint_32)png_sizeof(png_text));
    if (text_ptr == NULL)
    {
-     png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
-     png_free(png_ptr, chunkdata);
+     png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
+     png_free(png_ptr, png_ptr->chunkdata);
+     png_ptr->chunkdata = NULL;
      return;
    }
    text_ptr->compression = (int)comp_flag + 1;
-   text_ptr->lang_key = chunkdata+(lang_key-key);
-   text_ptr->lang = chunkdata+(lang-key);
+   text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
+   text_ptr->lang = png_ptr->chunkdata + (lang - key);
    text_ptr->itxt_length = data_len;
    text_ptr->text_length = 0;
-   text_ptr->key = chunkdata;
-   text_ptr->text = chunkdata + prefix_len;
+   text_ptr->key = png_ptr->chunkdata;
+   text_ptr->text = png_ptr->chunkdata + prefix_len;
 
-   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
 
    png_free(png_ptr, text_ptr);
-   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, png_ptr->chunkdata);
+   png_ptr->chunkdata = NULL;
    if (ret)
      png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
 }
@@ -2185,25 +2362,40 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 {
    png_uint_32 skip = 0;
 
-   png_debug(1, "in png_handle_unknown\n");
+   png_debug(1, "in png_handle_unknown");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+   if (png_ptr->user_chunk_cache_max != 0)
+   {
+      if (png_ptr->user_chunk_cache_max == 1)
+      {
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      if (--png_ptr->user_chunk_cache_max == 1)
+      {
+         png_warning(png_ptr, "No space in chunk cache for unknown chunk");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+   }
+#endif
 
    if (png_ptr->mode & PNG_HAVE_IDAT)
    {
 #ifdef PNG_USE_LOCAL_ARRAYS
       PNG_CONST PNG_IDAT;
 #endif
-      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* not an IDAT */
+      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* Not an IDAT */
          png_ptr->mode |= PNG_AFTER_IDAT;
    }
 
-   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
-
    if (!(png_ptr->chunk_name[0] & 0x20))
    {
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-      if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
            PNG_HANDLE_CHUNK_ALWAYS
-#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
            && png_ptr->read_user_chunk_fn == NULL
 #endif
         )
@@ -2211,9 +2403,12 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
           png_chunk_error(png_ptr, "unknown critical chunk");
    }
 
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-   if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
-       (png_ptr->read_user_chunk_fn != NULL))
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+   if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+       || (png_ptr->read_user_chunk_fn != NULL)
+#endif
+        )
    {
 #ifdef PNG_MAX_MALLOC_64K
        if (length > (png_uint_32)65535L)
@@ -2224,16 +2419,22 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
        }
 #endif
        png_memcpy((png_charp)png_ptr->unknown_chunk.name,
-                  (png_charp)png_ptr->chunk_name, 
+                  (png_charp)png_ptr->chunk_name,
                   png_sizeof(png_ptr->unknown_chunk.name));
-       png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
-       png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
+       png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
+           = '\0';
        png_ptr->unknown_chunk.size = (png_size_t)length;
-       png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
-#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
-       if(png_ptr->read_user_chunk_fn != NULL)
+       if (length == 0)
+         png_ptr->unknown_chunk.data = NULL;
+       else
+       {
+         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
+         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
+       }
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+       if (png_ptr->read_user_chunk_fn != NULL)
        {
-          /* callback to user unknown chunk handler */
+          /* Callback to user unknown chunk handler */
           int ret;
           ret = (*(png_ptr->read_user_chunk_fn))
             (png_ptr, &png_ptr->unknown_chunk);
@@ -2242,16 +2443,18 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
           if (ret == 0)
           {
              if (!(png_ptr->chunk_name[0] & 0x20))
-                if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+                if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
                      PNG_HANDLE_CHUNK_ALWAYS)
+#endif
                    png_chunk_error(png_ptr, "unknown critical chunk");
              png_set_unknown_chunks(png_ptr, info_ptr,
                &png_ptr->unknown_chunk, 1);
           }
        }
-#else
-       png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
+       else
 #endif
+       png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
        png_free(png_ptr, png_ptr->unknown_chunk.data);
        png_ptr->unknown_chunk.data = NULL;
    }
@@ -2261,8 +2464,8 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 
    png_crc_finish(png_ptr, skip);
 
-#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
-   info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
+#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
+   info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
 #endif
 }
 
@@ -2277,7 +2480,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
 void /* PRIVATE */
 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
 {
-   png_debug(1, "in png_check_chunk_name\n");
+   png_debug(1, "in png_check_chunk_name");
    if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
        isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
    {
@@ -2299,7 +2502,7 @@ png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
 void /* PRIVATE */
 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
 {
-   png_debug(1,"in png_combine_row\n");
+   png_debug(1, "in png_combine_row");
    if (mask == 0xff)
    {
       png_memcpy(row, png_ptr->row_buf + 1,
@@ -2319,7 +2522,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask)
             png_uint_32 i;
             png_uint_32 row_width = png_ptr->width;
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
             if (png_ptr->transformations & PNG_PACKSWAP)
             {
                 s_start = 0;
@@ -2374,7 +2577,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask)
             png_uint_32 row_width = png_ptr->width;
             int value;
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
             if (png_ptr->transformations & PNG_PACKSWAP)
             {
                s_start = 0;
@@ -2426,7 +2629,7 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask)
             png_uint_32 row_width = png_ptr->width;
             int value;
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
             if (png_ptr->transformations & PNG_PACKSWAP)
             {
                s_start = 0;
@@ -2509,13 +2712,11 @@ png_do_read_interlace(png_structp png_ptr)
    png_bytep row = png_ptr->row_buf + 1;
    int pass = png_ptr->pass;
    png_uint_32 transformations = png_ptr->transformations;
-#ifdef PNG_USE_LOCAL_ARRAYS
-   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-   /* offset to next interlace block */
+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+   /* Offset to next interlace block */
    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-#endif
 
-   png_debug(1,"in png_do_read_interlace\n");
+   png_debug(1, "in png_do_read_interlace");
    if (row != NULL && row_info != NULL)
    {
       png_uint_32 final_width;
@@ -2535,7 +2736,7 @@ png_do_read_interlace(png_structp png_ptr)
             png_uint_32 i;
             int j;
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
             if (transformations & PNG_PACKSWAP)
             {
                 sshift = (int)((row_info->width + 7) & 0x07);
@@ -2588,7 +2789,7 @@ png_do_read_interlace(png_structp png_ptr)
             int jstop = png_pass_inc[pass];
             png_uint_32 i;
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
             if (transformations & PNG_PACKSWAP)
             {
                sshift = (int)(((row_info->width + 3) & 0x03) << 1);
@@ -2644,7 +2845,7 @@ png_do_read_interlace(png_structp png_ptr)
             png_uint_32 i;
             int jstop = png_pass_inc[pass];
 
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
             if (transformations & PNG_PACKSWAP)
             {
                sshift = (int)(((row_info->width + 1) & 0x01) << 2);
@@ -2693,7 +2894,8 @@ png_do_read_interlace(png_structp png_ptr)
          default:
          {
             png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
-            png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
+            png_bytep sp = row + (png_size_t)(row_info->width - 1)
+                * pixel_bytes;
             png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
 
             int jstop = png_pass_inc[pass];
@@ -2716,10 +2918,10 @@ png_do_read_interlace(png_structp png_ptr)
          }
       }
       row_info->width = final_width;
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
+      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
    }
-#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
-   transformations = transformations; /* silence compiler warning */
+#ifndef PNG_READ_PACKSWAP_SUPPORTED
+   transformations = transformations; /* Silence compiler warning */
 #endif
 }
 #endif /* PNG_READ_INTERLACING_SUPPORTED */
@@ -2728,8 +2930,8 @@ void /* PRIVATE */
 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
    png_bytep prev_row, int filter)
 {
-   png_debug(1, "in png_read_filter_row\n");
-   png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
+   png_debug(1, "in png_read_filter_row");
+   png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
    switch (filter)
    {
       case PNG_FILTER_VALUE_NONE:
@@ -2803,7 +3005,7 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
             rp++;
          }
 
-         for (i = 0; i < istop; i++)   /* use leftover rp,pp */
+         for (i = 0; i < istop; i++)   /* Use leftover rp,pp */
          {
             int a, b, c, pa, pb, pc, p;
 
@@ -2833,7 +3035,7 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
                   p = c;
              */
 
-            p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+            p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
 
             *rp = (png_byte)(((int)(*rp) + p) & 0xff);
             rp++;
@@ -2842,35 +3044,37 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
       }
       default:
          png_warning(png_ptr, "Ignoring bad adaptive filter type");
-         *row=0;
+         *row = 0;
          break;
    }
 }
 
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 void /* PRIVATE */
 png_read_finish_row(png_structp png_ptr)
 {
-#ifdef PNG_USE_LOCAL_ARRAYS
-   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
-   /* start of interlace block */
+   /* Start of interlace block */
    PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
 
-   /* offset to next interlace block */
+   /* Offset to next interlace block */
    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
 
-   /* start of interlace block in the y direction */
+   /* Start of interlace block in the y direction */
    PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
 
-   /* offset to next interlace block in the y direction */
+   /* Offset to next interlace block in the y direction */
    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-#endif
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
 
-   png_debug(1, "in png_read_finish_row\n");
+   png_debug(1, "in png_read_finish_row");
    png_ptr->row_number++;
    if (png_ptr->row_number < png_ptr->num_rows)
       return;
 
+#ifdef PNG_READ_INTERLACING_SUPPORTED
    if (png_ptr->interlaced)
    {
       png_ptr->row_number = 0;
@@ -2886,9 +3090,6 @@ png_read_finish_row(png_structp png_ptr)
             png_pass_start[png_ptr->pass]) /
             png_pass_inc[png_ptr->pass];
 
-         png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
-            png_ptr->iwidth) + 1;
-
          if (!(png_ptr->transformations & PNG_INTERLACE))
          {
             png_ptr->num_rows = (png_ptr->height +
@@ -2905,6 +3106,7 @@ png_read_finish_row(png_structp png_ptr)
       if (png_ptr->pass < 7)
          return;
    }
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
 
    if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
    {
@@ -2916,7 +3118,7 @@ png_read_finish_row(png_structp png_ptr)
 
       png_ptr->zstream.next_out = (Byte *)&extra;
       png_ptr->zstream.avail_out = (uInt)1;
-      for(;;)
+      for (;;)
       {
          if (!(png_ptr->zstream.avail_in))
          {
@@ -2946,7 +3148,7 @@ png_read_finish_row(png_structp png_ptr)
          {
             if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
                png_ptr->idat_size)
-               png_warning(png_ptr, "Extra compressed data");
+               png_warning(png_ptr, "Extra compressed data.");
             png_ptr->mode |= PNG_AFTER_IDAT;
             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
             break;
@@ -2968,38 +3170,40 @@ png_read_finish_row(png_structp png_ptr)
    }
 
    if (png_ptr->idat_size || png_ptr->zstream.avail_in)
-      png_warning(png_ptr, "Extra compression data");
+      png_warning(png_ptr, "Extra compression data.");
 
    inflateReset(&png_ptr->zstream);
 
    png_ptr->mode |= PNG_AFTER_IDAT;
 }
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
 
 void /* PRIVATE */
 png_read_start_row(png_structp png_ptr)
 {
-#ifdef PNG_USE_LOCAL_ARRAYS
-   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
-   /* start of interlace block */
+   /* Start of interlace block */
    PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
 
-   /* offset to next interlace block */
+   /* Offset to next interlace block */
    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
 
-   /* start of interlace block in the y direction */
+   /* Start of interlace block in the y direction */
    PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
 
-   /* offset to next interlace block in the y direction */
+   /* Offset to next interlace block in the y direction */
    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
 #endif
 
    int max_pixel_depth;
-   png_uint_32 row_bytes;
+   png_size_t row_bytes;
 
-   png_debug(1, "in png_read_start_row\n");
+   png_debug(1, "in png_read_start_row");
    png_ptr->zstream.avail_in = 0;
    png_init_read_transformations(png_ptr);
+#ifdef PNG_READ_INTERLACING_SUPPORTED
    if (png_ptr->interlaced)
    {
       if (!(png_ptr->transformations & PNG_INTERLACE))
@@ -3012,27 +3216,21 @@ png_read_start_row(png_structp png_ptr)
          png_pass_inc[png_ptr->pass] - 1 -
          png_pass_start[png_ptr->pass]) /
          png_pass_inc[png_ptr->pass];
-
-         row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
-
-         png_ptr->irowbytes = (png_size_t)row_bytes;
-         if((png_uint_32)png_ptr->irowbytes != row_bytes)
-            png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
    }
    else
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
    {
       png_ptr->num_rows = png_ptr->height;
       png_ptr->iwidth = png_ptr->width;
-      png_ptr->irowbytes = png_ptr->rowbytes + 1;
    }
    max_pixel_depth = png_ptr->pixel_depth;
 
-#if defined(PNG_READ_PACK_SUPPORTED)
+#ifdef PNG_READ_PACK_SUPPORTED
    if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
       max_pixel_depth = 8;
 #endif
 
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
    if (png_ptr->transformations & PNG_EXPAND)
    {
       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
@@ -3060,7 +3258,7 @@ png_read_start_row(png_structp png_ptr)
    }
 #endif
 
-#if defined(PNG_READ_FILLER_SUPPORTED)
+#ifdef PNG_READ_FILLER_SUPPORTED
    if (png_ptr->transformations & (PNG_FILLER))
    {
       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
@@ -3082,14 +3280,14 @@ png_read_start_row(png_structp png_ptr)
    }
 #endif
 
-#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
    {
       if (
-#if defined(PNG_READ_EXPAND_SUPPORTED)
+#ifdef PNG_READ_EXPAND_SUPPORTED
         (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
 #endif
-#if defined(PNG_READ_FILLER_SUPPORTED)
+#ifdef PNG_READ_FILLER_SUPPORTED
         (png_ptr->transformations & (PNG_FILLER)) ||
 #endif
         png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -3118,46 +3316,70 @@ png_read_start_row(png_structp png_ptr)
 
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
-   if(png_ptr->transformations & PNG_USER_TRANSFORM)
+   if (png_ptr->transformations & PNG_USER_TRANSFORM)
      {
-       int user_pixel_depth=png_ptr->user_transform_depth*
+       int user_pixel_depth = png_ptr->user_transform_depth*
          png_ptr->user_transform_channels;
-       if(user_pixel_depth > max_pixel_depth)
+       if (user_pixel_depth > max_pixel_depth)
          max_pixel_depth=user_pixel_depth;
      }
 #endif
 
-   /* align the width on the next larger 8 pixels.  Mainly used
-      for interlacing */
+   /* Align the width on the next larger 8 pixels.  Mainly used
+    * for interlacing
+    */
    row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
-   /* calculate the maximum bytes needed, adding a byte and a pixel
-      for safety's sake */
-   row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
+   /* Calculate the maximum bytes needed, adding a byte and a pixel
+    * for safety's sake
+    */
+   row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
       1 + ((max_pixel_depth + 7) >> 3);
 #ifdef PNG_MAX_MALLOC_64K
    if (row_bytes > (png_uint_32)65536L)
       png_error(png_ptr, "This image requires a row greater than 64KB");
 #endif
-   png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
-   png_ptr->row_buf = png_ptr->big_row_buf+32;
+
+   if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
+   {
+     png_free(png_ptr, png_ptr->big_row_buf);
+     if (png_ptr->interlaced)
+        png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
+            row_bytes + 64);
+     else
+        png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
+            row_bytes + 64);
+     png_ptr->old_big_row_buf_size = row_bytes + 64;
+
+     /* Use 32 bytes of padding before and after row_buf. */
+     png_ptr->row_buf = png_ptr->big_row_buf + 32;
+     png_ptr->old_big_row_buf_size = row_bytes + 64;
+   }
 
 #ifdef PNG_MAX_MALLOC_64K
-   if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
+   if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
       png_error(png_ptr, "This image requires a row greater than 64KB");
 #endif
-   if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
+   if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
       png_error(png_ptr, "Row has too many bytes to allocate in memory.");
-   png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
-      png_ptr->rowbytes + 1));
 
-   png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+   if (row_bytes + 1 > png_ptr->old_prev_row_size)
+   {
+      png_free(png_ptr, png_ptr->prev_row);
+      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
+        row_bytes + 1));
+      png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
+      png_ptr->old_prev_row_size = row_bytes + 1;
+   }
+
+   png_ptr->rowbytes = row_bytes;
 
-   png_debug1(3, "width = %lu,\n", png_ptr->width);
-   png_debug1(3, "height = %lu,\n", png_ptr->height);
-   png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
-   png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
-   png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
-   png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
+   png_debug1(3, "width = %lu,", png_ptr->width);
+   png_debug1(3, "height = %lu,", png_ptr->height);
+   png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
+   png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
+   png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
+   png_debug1(3, "irowbytes = %lu",
+       PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
 
    png_ptr->flags |= PNG_FLAG_ROW_INIT;
 }
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngset.c b/graf2d/asimage/src/libAfterImage/libpng/pngset.c
index 447c3f8..72d89fc 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngset.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngset.c
@@ -1,12 +1,15 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Last changed in libpng 1.2.22 [November 6, 2007]
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.49 [March 29, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * The functions here are used during reads to store data from the file
  * into the info struct, and during writes to store application data
  * into the info struct for writing into the file.  This abstracts the
@@ -14,15 +17,16 @@
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
 
-#if defined(PNG_bKGD_SUPPORTED)
+#ifdef PNG_bKGD_SUPPORTED
 void PNGAPI
 png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
 {
-   png_debug1(1, "in %s storage function\n", "bKGD");
+   png_debug1(1, "in %s storage function", "bKGD");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
@@ -31,41 +35,17 @@ png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
 }
 #endif
 
-#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_cHRM_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 void PNGAPI
 png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
    double white_x, double white_y, double red_x, double red_y,
    double green_x, double green_y, double blue_x, double blue_y)
 {
-   png_debug1(1, "in %s storage function\n", "cHRM");
+   png_debug1(1, "in %s storage function", "cHRM");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
-   if (!(white_x || white_y || red_x || red_y || green_x || green_y ||
-       blue_x || blue_y))
-   {
-      png_warning(png_ptr,
-        "Ignoring attempt to set all-zero chromaticity values");
-      return;
-   }
-   if (white_x < 0.0 || white_y < 0.0 ||
-         red_x < 0.0 ||   red_y < 0.0 ||
-       green_x < 0.0 || green_y < 0.0 ||
-        blue_x < 0.0 ||  blue_y < 0.0)
-   {
-      png_warning(png_ptr,
-        "Ignoring attempt to set negative chromaticity value");
-      return;
-   }
-   if (white_x > 21474.83 || white_y > 21474.83 ||
-         red_x > 21474.83 ||   red_y > 21474.83 ||
-       green_x > 21474.83 || green_y > 21474.83 ||
-        blue_x > 21474.83 ||  blue_y > 21474.83)
-   {
-      png_warning(png_ptr,
-        "Ignoring attempt to set chromaticity value exceeding 21474.83");
-      return;
-   }
 
    info_ptr->x_white = (float)white_x;
    info_ptr->y_white = (float)white_y;
@@ -87,7 +67,8 @@ png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
 #endif
    info_ptr->valid |= PNG_INFO_cHRM;
 }
-#endif
+#endif /* PNG_FLOATING_POINT_SUPPORTED */
+
 #ifdef PNG_FIXED_POINT_SUPPORTED
 void PNGAPI
 png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
@@ -95,80 +76,49 @@ png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
    png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
    png_fixed_point blue_x, png_fixed_point blue_y)
 {
-   png_debug1(1, "in %s storage function\n", "cHRM");
+   png_debug1(1, "in %s storage function", "cHRM fixed");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   if (!(white_x || white_y || red_x || red_y || green_x || green_y ||
-       blue_x || blue_y))
-   {
-      png_warning(png_ptr,
-        "Ignoring attempt to set all-zero chromaticity values");
-      return;
-   }
-   if (white_x < 0 || white_y < 0 ||
-         red_x < 0 ||   red_y < 0 ||
-       green_x < 0 || green_y < 0 ||
-        blue_x < 0 ||  blue_y < 0)
-   {
-      png_warning(png_ptr,
-        "Ignoring attempt to set negative chromaticity value");
-      return;
-   }
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   if (white_x > (double) PNG_UINT_31_MAX ||
-       white_y > (double) PNG_UINT_31_MAX ||
-         red_x > (double) PNG_UINT_31_MAX ||
-         red_y > (double) PNG_UINT_31_MAX ||
-       green_x > (double) PNG_UINT_31_MAX ||
-       green_y > (double) PNG_UINT_31_MAX ||
-        blue_x > (double) PNG_UINT_31_MAX ||
-        blue_y > (double) PNG_UINT_31_MAX)
-#else
-   if (white_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
-       white_y > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
-         red_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
-         red_y > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
-       green_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
-       green_y > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
-        blue_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
-        blue_y > (png_fixed_point) PNG_UINT_31_MAX/100000L)
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+   if (png_check_cHRM_fixed(png_ptr,
+      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
 #endif
    {
-      png_warning(png_ptr,
-        "Ignoring attempt to set chromaticity value exceeding 21474.83");
-      return;
+      info_ptr->int_x_white = white_x;
+      info_ptr->int_y_white = white_y;
+      info_ptr->int_x_red   = red_x;
+      info_ptr->int_y_red   = red_y;
+      info_ptr->int_x_green = green_x;
+      info_ptr->int_y_green = green_y;
+      info_ptr->int_x_blue  = blue_x;
+      info_ptr->int_y_blue  = blue_y;
+#ifdef  PNG_FLOATING_POINT_SUPPORTED
+      info_ptr->x_white = (float)(white_x/100000.);
+      info_ptr->y_white = (float)(white_y/100000.);
+      info_ptr->x_red   = (float)(  red_x/100000.);
+      info_ptr->y_red   = (float)(  red_y/100000.);
+      info_ptr->x_green = (float)(green_x/100000.);
+      info_ptr->y_green = (float)(green_y/100000.);
+      info_ptr->x_blue  = (float)( blue_x/100000.);
+      info_ptr->y_blue  = (float)( blue_y/100000.);
+#endif
+      info_ptr->valid |= PNG_INFO_cHRM;
    }
-   info_ptr->int_x_white = white_x;
-   info_ptr->int_y_white = white_y;
-   info_ptr->int_x_red   = red_x;
-   info_ptr->int_y_red   = red_y;
-   info_ptr->int_x_green = green_x;
-   info_ptr->int_y_green = green_y;
-   info_ptr->int_x_blue  = blue_x;
-   info_ptr->int_y_blue  = blue_y;
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-   info_ptr->x_white = (float)(white_x/100000.);
-   info_ptr->y_white = (float)(white_y/100000.);
-   info_ptr->x_red   = (float)(  red_x/100000.);
-   info_ptr->y_red   = (float)(  red_y/100000.);
-   info_ptr->x_green = (float)(green_x/100000.);
-   info_ptr->y_green = (float)(green_y/100000.);
-   info_ptr->x_blue  = (float)( blue_x/100000.);
-   info_ptr->y_blue  = (float)( blue_y/100000.);
-#endif
-   info_ptr->valid |= PNG_INFO_cHRM;
 }
-#endif
-#endif
+#endif /* PNG_FIXED_POINT_SUPPORTED */
+#endif /* PNG_cHRM_SUPPORTED */
 
-#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_gAMA_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 void PNGAPI
 png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
 {
-   double gamma;
-   png_debug1(1, "in %s storage function\n", "gAMA");
+   double png_gamma;
+
+   png_debug1(1, "in %s storage function", "gAMA");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
@@ -176,16 +126,16 @@ png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
    if (file_gamma > 21474.83)
    {
       png_warning(png_ptr, "Limiting gamma to 21474.83");
-      gamma=21474.83;
+      png_gamma=21474.83;
    }
    else
-      gamma=file_gamma;
-   info_ptr->gamma = (float)gamma;
+      png_gamma = file_gamma;
+   info_ptr->gamma = (float)png_gamma;
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   info_ptr->int_gamma = (int)(gamma*100000.+.5);
+   info_ptr->int_gamma = (int)(png_gamma*100000.+.5);
 #endif
    info_ptr->valid |= PNG_INFO_gAMA;
-   if(gamma == 0.0)
+   if (png_gamma == 0.0)
       png_warning(png_ptr, "Setting gamma=0");
 }
 #endif
@@ -193,71 +143,75 @@ void PNGAPI
 png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
    int_gamma)
 {
-   png_fixed_point gamma;
+   png_fixed_point png_gamma;
+
+   png_debug1(1, "in %s storage function", "gAMA");
 
-   png_debug1(1, "in %s storage function\n", "gAMA");
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX)
+   if (int_gamma > (png_fixed_point)PNG_UINT_31_MAX)
    {
-     png_warning(png_ptr, "Limiting gamma to 21474.83");
-     gamma=PNG_UINT_31_MAX;
+      png_warning(png_ptr, "Limiting gamma to 21474.83");
+      png_gamma=PNG_UINT_31_MAX;
    }
    else
    {
-     if (int_gamma < 0)
-     {
-       png_warning(png_ptr, "Setting negative gamma to zero");
-       gamma=0;
-     }
-     else
-       gamma=int_gamma;
+      if (int_gamma < 0)
+      {
+         png_warning(png_ptr, "Setting negative gamma to zero");
+         png_gamma = 0;
+      }
+      else
+         png_gamma = int_gamma;
    }
 #ifdef PNG_FLOATING_POINT_SUPPORTED
-   info_ptr->gamma = (float)(gamma/100000.);
+   info_ptr->gamma = (float)(png_gamma/100000.);
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
-   info_ptr->int_gamma = gamma;
+   info_ptr->int_gamma = png_gamma;
 #endif
    info_ptr->valid |= PNG_INFO_gAMA;
-   if(gamma == 0)
+   if (png_gamma == 0)
       png_warning(png_ptr, "Setting gamma=0");
 }
 #endif
 
-#if defined(PNG_hIST_SUPPORTED)
+#ifdef PNG_hIST_SUPPORTED
 void PNGAPI
 png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
 {
    int i;
 
-   png_debug1(1, "in %s storage function\n", "hIST");
+   png_debug1(1, "in %s storage function", "hIST");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
+
    if (info_ptr->num_palette == 0 || info_ptr->num_palette
        > PNG_MAX_PALETTE_LENGTH)
    {
-       png_warning(png_ptr,
-          "Invalid palette size, hIST allocation skipped.");
-       return;
+      png_warning(png_ptr,
+         "Invalid palette size, hIST allocation skipped.");
+      return;
    }
 
 #ifdef PNG_FREE_ME_SUPPORTED
    png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
 #endif
-   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version
-      1.2.1 */
+   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
+    * version 1.2.1
+    */
    png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,
-      (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof (png_uint_16)));
+      (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)));
    if (png_ptr->hist == NULL)
-     {
-       png_warning(png_ptr, "Insufficient memory for hIST chunk data.");
-       return;
-     }
+   {
+      png_warning(png_ptr, "Insufficient memory for hIST chunk data.");
+      return;
+   }
 
    for (i = 0; i < info_ptr->num_palette; i++)
-       png_ptr->hist[i] = hist[i];
+      png_ptr->hist[i] = hist[i];
    info_ptr->hist = png_ptr->hist;
    info_ptr->valid |= PNG_INFO_hIST;
 
@@ -275,86 +229,23 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
    int color_type, int interlace_type, int compression_type,
    int filter_type)
 {
-   png_debug1(1, "in %s storage function\n", "IHDR");
+   png_debug1(1, "in %s storage function", "IHDR");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   /* check for width and height valid values */
-   if (width == 0 || height == 0)
-      png_error(png_ptr, "Image width or height is zero in IHDR");
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (width > png_ptr->user_width_max || height > png_ptr->user_height_max)
-      png_error(png_ptr, "image size exceeds user limits in IHDR");
-#else
-   if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX)
-      png_error(png_ptr, "image size exceeds user limits in IHDR");
-#endif
-   if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)
-      png_error(png_ptr, "Invalid image size in IHDR");
-   if ( width > (PNG_UINT_32_MAX
-                 >> 3)      /* 8-byte RGBA pixels */
-                 - 64       /* bigrowbuf hack */
-                 - 1        /* filter byte */
-                 - 7*8      /* rounding of width to multiple of 8 pixels */
-                 - 8)       /* extra max_pixel_depth pad */
-      png_warning(png_ptr, "Width is too large for libpng to process pixels");
-
-   /* check other values */
-   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
-      bit_depth != 8 && bit_depth != 16)
-      png_error(png_ptr, "Invalid bit depth in IHDR");
-
-   if (color_type < 0 || color_type == 1 ||
-      color_type == 5 || color_type > 6)
-      png_error(png_ptr, "Invalid color type in IHDR");
-
-   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
-       ((color_type == PNG_COLOR_TYPE_RGB ||
-         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
-         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
-      png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
-
-   if (interlace_type >= PNG_INTERLACE_LAST)
-      png_error(png_ptr, "Unknown interlace method in IHDR");
-
-   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
-      png_error(png_ptr, "Unknown compression method in IHDR");
-
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-   /* Accept filter_method 64 (intrapixel differencing) only if
-    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
-    * 2. Libpng did not read a PNG signature (this filter_method is only
-    *    used in PNG datastreams that are embedded in MNG datastreams) and
-    * 3. The application called png_permit_mng_features with a mask that
-    *    included PNG_FLAG_MNG_FILTER_64 and
-    * 4. The filter_method is 64 and
-    * 5. The color_type is RGB or RGBA
-    */
-   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
-      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream");
-   if(filter_type != PNG_FILTER_TYPE_BASE)
-   {
-     if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
-        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
-        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
-        (color_type == PNG_COLOR_TYPE_RGB ||
-         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
-        png_error(png_ptr, "Unknown filter method in IHDR");
-     if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
-        png_warning(png_ptr, "Invalid filter method in IHDR");
-   }
-#else
-   if(filter_type != PNG_FILTER_TYPE_BASE)
-      png_error(png_ptr, "Unknown filter method in IHDR");
-#endif
-
    info_ptr->width = width;
    info_ptr->height = height;
    info_ptr->bit_depth = (png_byte)bit_depth;
-   info_ptr->color_type =(png_byte) color_type;
+   info_ptr->color_type = (png_byte)color_type;
    info_ptr->compression_type = (png_byte)compression_type;
    info_ptr->filter_type = (png_byte)filter_type;
    info_ptr->interlace_type = (png_byte)interlace_type;
+
+   png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
+       info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
+       info_ptr->compression_type, info_ptr->filter_type);
+
    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       info_ptr->channels = 1;
    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
@@ -365,7 +256,7 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
       info_ptr->channels++;
    info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
 
-   /* check for potential overflow */
+   /* Check for potential overflow */
    if (width > (PNG_UINT_32_MAX
                  >> 3)      /* 8-byte RGBA pixels */
                  - 64       /* bigrowbuf hack */
@@ -374,15 +265,16 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
                  - 8)       /* extra max_pixel_depth pad */
       info_ptr->rowbytes = (png_size_t)0;
    else
-      info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width);
+      info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
 }
 
-#if defined(PNG_oFFs_SUPPORTED)
+#ifdef PNG_oFFs_SUPPORTED
 void PNGAPI
 png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
    png_int_32 offset_x, png_int_32 offset_y, int unit_type)
 {
-   png_debug1(1, "in %s storage function\n", "oFFs");
+   png_debug1(1, "in %s storage function", "oFFs");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
@@ -393,7 +285,7 @@ png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_pCAL_SUPPORTED)
+#ifdef PNG_pCAL_SUPPORTED
 void PNGAPI
 png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
    png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
@@ -402,56 +294,60 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
    png_uint_32 length;
    int i;
 
-   png_debug1(1, "in %s storage function\n", "pCAL");
+   png_debug1(1, "in %s storage function", "pCAL");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
    length = png_strlen(purpose) + 1;
-   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
+   png_debug1(3, "allocating purpose for info (%lu bytes)",
+     (unsigned long)length);
    info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
    if (info_ptr->pcal_purpose == NULL)
-     {
-       png_warning(png_ptr, "Insufficient memory for pCAL purpose.");
-       return;
-     }
+   {
+      png_warning(png_ptr, "Insufficient memory for pCAL purpose.");
+      return;
+   }
    png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
 
-   png_debug(3, "storing X0, X1, type, and nparams in info\n");
+   png_debug(3, "storing X0, X1, type, and nparams in info");
    info_ptr->pcal_X0 = X0;
    info_ptr->pcal_X1 = X1;
    info_ptr->pcal_type = (png_byte)type;
    info_ptr->pcal_nparams = (png_byte)nparams;
 
    length = png_strlen(units) + 1;
-   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
+   png_debug1(3, "allocating units for info (%lu bytes)",
+     (unsigned long)length);
    info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
    if (info_ptr->pcal_units == NULL)
-     {
-       png_warning(png_ptr, "Insufficient memory for pCAL units.");
-       return;
-     }
+   {
+      png_warning(png_ptr, "Insufficient memory for pCAL units.");
+      return;
+   }
    png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
 
    info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
       (png_uint_32)((nparams + 1) * png_sizeof(png_charp)));
    if (info_ptr->pcal_params == NULL)
-     {
-       png_warning(png_ptr, "Insufficient memory for pCAL params.");
-       return;
-     }
+   {
+      png_warning(png_ptr, "Insufficient memory for pCAL params.");
+      return;
+   }
 
-   info_ptr->pcal_params[nparams] = NULL;
+   png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
 
    for (i = 0; i < nparams; i++)
    {
       length = png_strlen(params[i]) + 1;
-      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
+      png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
+        (unsigned long)length);
       info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
       if (info_ptr->pcal_params[i] == NULL)
-        {
-          png_warning(png_ptr, "Insufficient memory for pCAL parameter.");
-          return;
-        }
+      {
+         png_warning(png_ptr, "Insufficient memory for pCAL parameter.");
+         return;
+      }
       png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
    }
 
@@ -468,7 +364,8 @@ void PNGAPI
 png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
              int unit, double width, double height)
 {
-   png_debug1(1, "in %s storage function\n", "sCAL");
+   png_debug1(1, "in %s storage function", "sCAL");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
@@ -486,33 +383,38 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
 {
    png_uint_32 length;
 
-   png_debug1(1, "in %s storage function\n", "sCAL");
+   png_debug1(1, "in %s storage function", "sCAL");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
    info_ptr->scal_unit = (png_byte)unit;
 
    length = png_strlen(swidth) + 1;
-   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
+   png_debug1(3, "allocating unit for info (%u bytes)",
+      (unsigned int)length);
    info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length);
    if (info_ptr->scal_s_width == NULL)
    {
       png_warning(png_ptr,
-       "Memory allocation failed while processing sCAL.");
+         "Memory allocation failed while processing sCAL.");
+      return;
    }
    png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);
 
    length = png_strlen(sheight) + 1;
-   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
+   png_debug1(3, "allocating unit for info (%u bytes)",
+      (unsigned int)length);
    info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length);
    if (info_ptr->scal_s_height == NULL)
    {
       png_free (png_ptr, info_ptr->scal_s_width);
+      info_ptr->scal_s_width = NULL;
       png_warning(png_ptr,
-       "Memory allocation failed while processing sCAL.");
+         "Memory allocation failed while processing sCAL.");
+      return;
    }
    png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
-
    info_ptr->valid |= PNG_INFO_sCAL;
 #ifdef PNG_FREE_ME_SUPPORTED
    info_ptr->free_me |= PNG_FREE_SCAL;
@@ -522,12 +424,13 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
 #endif
 #endif
 
-#if defined(PNG_pHYs_SUPPORTED)
+#ifdef PNG_pHYs_SUPPORTED
 void PNGAPI
 png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
    png_uint_32 res_x, png_uint_32 res_y, int unit_type)
 {
-   png_debug1(1, "in %s storage function\n", "pHYs");
+   png_debug1(1, "in %s storage function", "pHYs");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
@@ -543,23 +446,23 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
    png_colorp palette, int num_palette)
 {
 
-   png_debug1(1, "in %s storage function\n", "PLTE");
+   png_debug1(1, "in %s storage function", "PLTE");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
    if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
-     {
-       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
          png_error(png_ptr, "Invalid palette length");
-       else
-       {
+      else
+      {
          png_warning(png_ptr, "Invalid palette length");
          return;
-       }
-     }
+      }
+   }
 
-   /*
-    * It may not actually be necessary to set png_ptr->palette here;
+   /* It may not actually be necessary to set png_ptr->palette here;
     * we do it for backward compatibility with the way the png_handle_tRNS
     * function used to do the allocation.
     */
@@ -568,13 +471,12 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
 #endif
 
    /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
-      of num_palette entries,
-      in case of an invalid PNG file that has too-large sample values. */
-   png_ptr->palette = (png_colorp)png_malloc(png_ptr,
+    * of num_palette entries, in case of an invalid PNG file that has
+    * too-large sample values.
+    */
+   png_ptr->palette = (png_colorp)png_calloc(png_ptr,
       PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
-   png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH *
-      png_sizeof(png_color));
-   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof (png_color));
+   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
    info_ptr->palette = png_ptr->palette;
    info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
 
@@ -587,25 +489,27 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
    info_ptr->valid |= PNG_INFO_PLTE;
 }
 
-#if defined(PNG_sBIT_SUPPORTED)
+#ifdef PNG_sBIT_SUPPORTED
 void PNGAPI
 png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
    png_color_8p sig_bit)
 {
-   png_debug1(1, "in %s storage function\n", "sBIT");
+   png_debug1(1, "in %s storage function", "sBIT");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof (png_color_8));
+   png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
    info_ptr->valid |= PNG_INFO_sBIT;
 }
 #endif
 
-#if defined(PNG_sRGB_SUPPORTED)
+#ifdef PNG_sRGB_SUPPORTED
 void PNGAPI
 png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
 {
-   png_debug1(1, "in %s storage function\n", "sRGB");
+   png_debug1(1, "in %s storage function", "sRGB");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
@@ -617,7 +521,7 @@ void PNGAPI
 png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
    int intent)
 {
-#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_gAMA_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float file_gamma;
 #endif
@@ -625,22 +529,21 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
    png_fixed_point int_file_gamma;
 #endif
 #endif
-#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_cHRM_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
 #endif
-#ifdef PNG_FIXED_POINT_SUPPORTED
    png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
       int_green_y, int_blue_x, int_blue_y;
 #endif
-#endif
-   png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM");
+   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
    png_set_sRGB(png_ptr, info_ptr, intent);
 
-#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_gAMA_SUPPORTED
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    file_gamma = (float).45455;
    png_set_gAMA(png_ptr, info_ptr, file_gamma);
@@ -651,8 +554,7 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
 #endif
 #endif
 
-#if defined(PNG_cHRM_SUPPORTED)
-#ifdef PNG_FIXED_POINT_SUPPORTED
+#ifdef PNG_cHRM_SUPPORTED
    int_white_x = 31270L;
    int_white_y = 32900L;
    int_red_x   = 64000L;
@@ -662,10 +564,6 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
    int_blue_x  = 15000L;
    int_blue_y  =  6000L;
 
-   png_set_cHRM_fixed(png_ptr, info_ptr,
-      int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y,
-      int_blue_x, int_blue_y);
-#endif
 #ifdef PNG_FLOATING_POINT_SUPPORTED
    white_x = (float).3127;
    white_y = (float).3290;
@@ -675,16 +573,23 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
    green_y = (float).60;
    blue_x  = (float).15;
    blue_y  = (float).06;
+#endif
 
-   png_set_cHRM(png_ptr, info_ptr,
-      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_set_cHRM_fixed(png_ptr, info_ptr,
+       int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
+       int_green_y, int_blue_x, int_blue_y);
 #endif
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   png_set_cHRM(png_ptr, info_ptr,
+       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
 #endif
+#endif /* cHRM */
 }
-#endif
+#endif /* sRGB */
 
 
-#if defined(PNG_iCCP_SUPPORTED)
+#ifdef PNG_iCCP_SUPPORTED
 void PNGAPI
 png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
              png_charp name, int compression_type,
@@ -694,7 +599,8 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
    png_charp new_iccp_profile;
    png_uint_32 length;
 
-   png_debug1(1, "in %s storage function\n", "iCCP");
+   png_debug1(1, "in %s storage function", "iCCP");
+
    if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
       return;
 
@@ -702,7 +608,7 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
    new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
    if (new_iccp_name == NULL)
    {
-      png_warning(png_ptr, "Insufficient memory to process iCCP chunk.");
+        png_warning(png_ptr, "Insufficient memory to process iCCP chunk.");
       return;
    }
    png_memcpy(new_iccp_name, name, length);
@@ -710,7 +616,8 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
    if (new_iccp_profile == NULL)
    {
       png_free (png_ptr, new_iccp_name);
-      png_warning(png_ptr, "Insufficient memory to process iCCP profile.");
+      png_warning(png_ptr,
+          "Insufficient memory to process iCCP profile.");
       return;
    }
    png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
@@ -721,7 +628,8 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
    info_ptr->iccp_name = new_iccp_name;
    info_ptr->iccp_profile = new_iccp_profile;
    /* Compression is always zero but is here so the API and info structure
-    * does not have to change if we introduce multiple compression types */
+    * does not have to change if we introduce multiple compression types
+    */
    info_ptr->iccp_compression = (png_byte)compression_type;
 #ifdef PNG_FREE_ME_SUPPORTED
    info_ptr->free_me |= PNG_FREE_ICCP;
@@ -730,24 +638,25 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
 }
 #endif
 
-#if defined(PNG_TEXT_SUPPORTED)
+#ifdef PNG_TEXT_SUPPORTED
 void PNGAPI
 png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
-   int num_text)
+             int num_text)
 {
    int ret;
-   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
+   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
    if (ret)
-     png_error(png_ptr, "Insufficient memory to store text");
+      png_error(png_ptr, "Insufficient memory to store text");
 }
 
 int /* PRIVATE */
 png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
-   int num_text)
+               int num_text)
 {
    int i;
 
-   png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ?
+   png_debug1(1, "in %s storage function", ((png_ptr == NULL ||
+      png_ptr->chunk_name[0] == '\0') ?
       "text" : (png_const_charp)png_ptr->chunk_name));
 
    if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
@@ -758,22 +667,26 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
     */
    if (info_ptr->num_text + num_text > info_ptr->max_text)
    {
+      int old_max_text = info_ptr->max_text;
+      int old_num_text = info_ptr->num_text;
+
       if (info_ptr->text != NULL)
       {
          png_textp old_text;
-         int old_max;
 
-         old_max = info_ptr->max_text;
          info_ptr->max_text = info_ptr->num_text + num_text + 8;
          old_text = info_ptr->text;
+
          info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
-            (png_uint_32)(info_ptr->max_text * png_sizeof (png_text)));
+            (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));
          if (info_ptr->text == NULL)
-           {
-             png_free(png_ptr, old_text);
-             return(1);
-           }
-         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
+         {
+            /* Restore to previous condition */
+            info_ptr->max_text = old_max_text;
+            info_ptr->text = old_text;
+            return(1);
+         }
+         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text *
             png_sizeof(png_text)));
          png_free(png_ptr, old_text);
       }
@@ -782,20 +695,26 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
          info_ptr->max_text = num_text + 8;
          info_ptr->num_text = 0;
          info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
-            (png_uint_32)(info_ptr->max_text * png_sizeof (png_text)));
+            (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));
          if (info_ptr->text == NULL)
-           return(1);
+         {
+            /* Restore to previous condition */
+            info_ptr->num_text = old_num_text;
+            info_ptr->max_text = old_max_text;
+            return(1);
+         }
 #ifdef PNG_FREE_ME_SUPPORTED
          info_ptr->free_me |= PNG_FREE_TEXT;
 #endif
       }
-      png_debug1(3, "allocated %d entries for info_ptr->text\n",
+      png_debug1(3, "allocated %d entries for info_ptr->text",
          info_ptr->max_text);
    }
+
    for (i = 0; i < num_text; i++)
    {
-      png_size_t text_length,key_len;
-      png_size_t lang_len,lang_key_len;
+      png_size_t text_length, key_len;
+      png_size_t lang_len, lang_key_len;
       png_textp textp = &(info_ptr->text[info_ptr->num_text]);
 
       if (text_ptr[i].key == NULL)
@@ -803,28 +722,30 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
 
       key_len = png_strlen(text_ptr[i].key);
 
-      if(text_ptr[i].compression <= 0)
+      if (text_ptr[i].compression <= 0)
       {
-        lang_len = 0;
-        lang_key_len = 0;
+         lang_len = 0;
+         lang_key_len = 0;
       }
+
       else
 #ifdef PNG_iTXt_SUPPORTED
       {
-        /* set iTXt data */
-        if (text_ptr[i].lang != NULL)
-          lang_len = png_strlen(text_ptr[i].lang);
-        else
-          lang_len = 0;
-        if (text_ptr[i].lang_key != NULL)
-          lang_key_len = png_strlen(text_ptr[i].lang_key);
-        else
-          lang_key_len = 0;
+         /* Set iTXt data */
+
+         if (text_ptr[i].lang != NULL)
+            lang_len = png_strlen(text_ptr[i].lang);
+         else
+            lang_len = 0;
+         if (text_ptr[i].lang_key != NULL)
+            lang_key_len = png_strlen(text_ptr[i].lang_key);
+         else
+            lang_key_len = 0;
       }
-#else
+#else /* PNG_iTXt_SUPPORTED */
       {
-        png_warning(png_ptr, "iTXt chunk not supported.");
-        continue;
+         png_warning(png_ptr, "iTXt chunk not supported.");
+         continue;
       }
 #endif
 
@@ -832,12 +753,13 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
       {
          text_length = 0;
 #ifdef PNG_iTXt_SUPPORTED
-         if(text_ptr[i].compression > 0)
+         if (text_ptr[i].compression > 0)
             textp->compression = PNG_ITXT_COMPRESSION_NONE;
          else
 #endif
             textp->compression = PNG_TEXT_COMPRESSION_NONE;
       }
+
       else
       {
          text_length = png_strlen(text_ptr[i].text);
@@ -845,26 +767,27 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
       }
 
       textp->key = (png_charp)png_malloc_warn(png_ptr,
-         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
+         (png_uint_32)
+         (key_len + text_length + lang_len + lang_key_len + 4));
       if (textp->key == NULL)
-        return(1);
-      png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n",
-         (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4),
-         (int)textp->key);
-
-      png_memcpy(textp->key, text_ptr[i].key,
-         (png_size_t)(key_len));
-      *(textp->key+key_len) = '\0';
+         return(1);
+      png_debug2(2, "Allocated %lu bytes at %x in png_set_text",
+                 (png_uint_32)
+                 (key_len + lang_len + lang_key_len + text_length + 4),
+                 (int)textp->key);
+
+      png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
+      *(textp->key + key_len) = '\0';
 #ifdef PNG_iTXt_SUPPORTED
       if (text_ptr[i].compression > 0)
       {
-         textp->lang=textp->key + key_len + 1;
+         textp->lang = textp->key + key_len + 1;
          png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
-         *(textp->lang+lang_len) = '\0';
-         textp->lang_key=textp->lang + lang_len + 1;
+         *(textp->lang + lang_len) = '\0';
+         textp->lang_key = textp->lang + lang_len + 1;
          png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
-         *(textp->lang_key+lang_key_len) = '\0';
-         textp->text=textp->lang_key + lang_key_len + 1;
+         *(textp->lang_key + lang_key_len) = '\0';
+         textp->text = textp->lang_key + lang_key_len + 1;
       }
       else
 #endif
@@ -873,21 +796,22 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
          textp->lang=NULL;
          textp->lang_key=NULL;
 #endif
-         textp->text=textp->key + key_len + 1;
+         textp->text = textp->key + key_len + 1;
       }
-      if(text_length)
+      if (text_length)
          png_memcpy(textp->text, text_ptr[i].text,
             (png_size_t)(text_length));
-      *(textp->text+text_length) = '\0';
+      *(textp->text + text_length) = '\0';
 
 #ifdef PNG_iTXt_SUPPORTED
-      if(textp->compression > 0)
+      if (textp->compression > 0)
       {
          textp->text_length = 0;
          textp->itxt_length = text_length;
       }
       else
 #endif
+
       {
          textp->text_length = text_length;
 #ifdef PNG_iTXt_SUPPORTED
@@ -895,197 +819,224 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
 #endif
       }
       info_ptr->num_text++;
-      png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
+      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
    }
    return(0);
 }
 #endif
 
-#if defined(PNG_tIME_SUPPORTED)
+#ifdef PNG_tIME_SUPPORTED
 void PNGAPI
 png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
 {
-   png_debug1(1, "in %s storage function\n", "tIME");
+   png_debug1(1, "in %s storage function", "tIME");
+
    if (png_ptr == NULL || info_ptr == NULL ||
        (png_ptr->mode & PNG_WROTE_tIME))
       return;
 
-   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof (png_time));
+   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
    info_ptr->valid |= PNG_INFO_tIME;
 }
 #endif
 
-#if defined(PNG_tRNS_SUPPORTED)
+#ifdef PNG_tRNS_SUPPORTED
 void PNGAPI
 png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
    png_bytep trans, int num_trans, png_color_16p trans_values)
 {
-   png_debug1(1, "in %s storage function\n", "tRNS");
+   png_debug1(1, "in %s storage function", "tRNS");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
    if (trans != NULL)
    {
-       /*
-        * It may not actually be necessary to set png_ptr->trans here;
+       /* It may not actually be necessary to set png_ptr->trans here;
         * we do it for backward compatibility with the way the png_handle_tRNS
         * function used to do the allocation.
         */
+
 #ifdef PNG_FREE_ME_SUPPORTED
        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
 #endif
+
        /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
        png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
            (png_uint_32)PNG_MAX_PALETTE_LENGTH);
-       if (num_trans <= PNG_MAX_PALETTE_LENGTH)
-         png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
-#ifdef PNG_FREE_ME_SUPPORTED
-       info_ptr->free_me |= PNG_FREE_TRNS;
-#else
-       png_ptr->flags |= PNG_FLAG_FREE_TRNS;
-#endif
+       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
+          png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
    }
 
    if (trans_values != NULL)
    {
+      int sample_max = (1 << info_ptr->bit_depth);
+      if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
+          (int)trans_values->gray > sample_max) ||
+          (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+          ((int)trans_values->red > sample_max ||
+          (int)trans_values->green > sample_max ||
+          (int)trans_values->blue > sample_max)))
+         png_warning(png_ptr,
+            "tRNS chunk has out-of-range samples for bit_depth");
       png_memcpy(&(info_ptr->trans_values), trans_values,
          png_sizeof(png_color_16));
       if (num_trans == 0)
-        num_trans = 1;
+         num_trans = 1;
    }
+
    info_ptr->num_trans = (png_uint_16)num_trans;
-   info_ptr->valid |= PNG_INFO_tRNS;
+   if (num_trans != 0)
+   {
+      info_ptr->valid |= PNG_INFO_tRNS;
+#ifdef PNG_FREE_ME_SUPPORTED
+      info_ptr->free_me |= PNG_FREE_TRNS;
+#else
+      png_ptr->flags |= PNG_FLAG_FREE_TRNS;
+#endif
+   }
 }
 #endif
 
-#if defined(PNG_sPLT_SUPPORTED)
+#ifdef PNG_sPLT_SUPPORTED
 void PNGAPI
 png_set_sPLT(png_structp png_ptr,
              png_infop info_ptr, png_sPLT_tp entries, int nentries)
+/*
+ *  entries        - array of png_sPLT_t structures
+ *                   to be added to the list of palettes
+ *                   in the info structure.
+ *  nentries       - number of palette structures to be
+ *                   added.
+ */
 {
-    png_sPLT_tp np;
-    int i;
+   png_sPLT_tp np;
+   int i;
 
-    if (png_ptr == NULL || info_ptr == NULL)
-       return;
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
 
-    np = (png_sPLT_tp)png_malloc_warn(png_ptr,
-        (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t));
-    if (np == NULL)
-    {
+   np = (png_sPLT_tp)png_malloc_warn(png_ptr,
+       (info_ptr->splt_palettes_num + nentries) *
+        (png_uint_32)png_sizeof(png_sPLT_t));
+   if (np == NULL)
+   {
       png_warning(png_ptr, "No memory for sPLT palettes.");
       return;
-    }
-
-    png_memcpy(np, info_ptr->splt_palettes,
-           info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
-    png_free(png_ptr, info_ptr->splt_palettes);
-    info_ptr->splt_palettes=NULL;
-
-    for (i = 0; i < nentries; i++)
-    {
-        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
-        png_sPLT_tp from = entries + i;
-        png_uint_32 length;
-
-        length = png_strlen(from->name) + 1;
-        to->name = (png_charp)png_malloc_warn(png_ptr, length);
-        if (to->name == NULL)
-        {
-           png_warning(png_ptr,
-             "Out of memory while processing sPLT chunk");
-        }
-        /* TODO: use png_malloc_warn */
-        png_memcpy(to->name, from->name, length);
-        to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
-            from->nentries * png_sizeof(png_sPLT_entry));
-        /* TODO: use png_malloc_warn */
-        png_memcpy(to->entries, from->entries,
-            from->nentries * png_sizeof(png_sPLT_entry));
-        if (to->entries == NULL)
-        {
-           png_warning(png_ptr,
-             "Out of memory while processing sPLT chunk");
-           png_free(png_ptr,to->name);
-           to->name = NULL;
-        }
-        to->nentries = from->nentries;
-        to->depth = from->depth;
-    }
-
-    info_ptr->splt_palettes = np;
-    info_ptr->splt_palettes_num += nentries;
-    info_ptr->valid |= PNG_INFO_sPLT;
+   }
+
+   png_memcpy(np, info_ptr->splt_palettes,
+       info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
+   png_free(png_ptr, info_ptr->splt_palettes);
+   info_ptr->splt_palettes=NULL;
+
+   for (i = 0; i < nentries; i++)
+   {
+      png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
+      png_sPLT_tp from = entries + i;
+      png_uint_32 length;
+
+      length = png_strlen(from->name) + 1;
+      to->name = (png_charp)png_malloc_warn(png_ptr, length);
+      if (to->name == NULL)
+      {
+         png_warning(png_ptr,
+           "Out of memory while processing sPLT chunk");
+         continue;
+      }
+      png_memcpy(to->name, from->name, length);
+      to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
+          (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry)));
+      if (to->entries == NULL)
+      {
+         png_warning(png_ptr,
+           "Out of memory while processing sPLT chunk");
+         png_free(png_ptr, to->name);
+         to->name = NULL;
+         continue;
+      }
+      png_memcpy(to->entries, from->entries,
+          from->nentries * png_sizeof(png_sPLT_entry));
+      to->nentries = from->nentries;
+      to->depth = from->depth;
+   }
+
+   info_ptr->splt_palettes = np;
+   info_ptr->splt_palettes_num += nentries;
+   info_ptr->valid |= PNG_INFO_sPLT;
 #ifdef PNG_FREE_ME_SUPPORTED
-    info_ptr->free_me |= PNG_FREE_SPLT;
+   info_ptr->free_me |= PNG_FREE_SPLT;
 #endif
 }
 #endif /* PNG_sPLT_SUPPORTED */
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
 void PNGAPI
 png_set_unknown_chunks(png_structp png_ptr,
    png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
 {
-    png_unknown_chunkp np;
-    int i;
-
-    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
-        return;
-
-    np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
-        (info_ptr->unknown_chunks_num + num_unknowns) *
-        png_sizeof(png_unknown_chunk));
-    if (np == NULL)
-    {
-       png_warning(png_ptr,
+   png_unknown_chunkp np;
+   int i;
+
+   if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
+      return;
+
+   np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
+       (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) *
+       png_sizeof(png_unknown_chunk)));
+   if (np == NULL)
+   {
+      png_warning(png_ptr,
           "Out of memory while processing unknown chunk.");
-       return;
-    }
-
-    png_memcpy(np, info_ptr->unknown_chunks,
-           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
-    png_free(png_ptr, info_ptr->unknown_chunks);
-    info_ptr->unknown_chunks=NULL;
-
-    for (i = 0; i < num_unknowns; i++)
-    {
-        png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
-        png_unknown_chunkp from = unknowns + i;
-
-        png_memcpy((png_charp)to->name, 
-                   (png_charp)from->name, 
-                   png_sizeof(from->name));
-        to->name[png_sizeof(to->name)-1] = '\0';
-
-        to->data = (png_bytep)png_malloc_warn(png_ptr, from->size);
-        if (to->data == NULL)
-        {
-           png_warning(png_ptr,
-              "Out of memory while processing unknown chunk.");
-        }
-        else
-        {
-           png_memcpy(to->data, from->data, from->size);
-           to->size = from->size;
-
-           /* note our location in the read or write sequence */
-           to->location = (png_byte)(png_ptr->mode & 0xff);
-        }
-    }
-
-    info_ptr->unknown_chunks = np;
-    info_ptr->unknown_chunks_num += num_unknowns;
+      return;
+   }
+
+   png_memcpy(np, info_ptr->unknown_chunks,
+       info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
+   png_free(png_ptr, info_ptr->unknown_chunks);
+   info_ptr->unknown_chunks = NULL;
+
+   for (i = 0; i < num_unknowns; i++)
+   {
+      png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
+      png_unknown_chunkp from = unknowns + i;
+
+      png_memcpy((png_charp)to->name, (png_charp)from->name,
+          png_sizeof(from->name));
+      to->name[png_sizeof(to->name)-1] = '\0';
+      to->size = from->size;
+      /* Note our location in the read or write sequence */
+      to->location = (png_byte)(png_ptr->mode & 0xff);
+
+      if (from->size == 0)
+         to->data=NULL;
+      else
+      {
+         to->data = (png_bytep)png_malloc_warn(png_ptr,
+           (png_uint_32)from->size);
+         if (to->data == NULL)
+         {
+            png_warning(png_ptr,
+             "Out of memory while processing unknown chunk.");
+            to->size = 0;
+         }
+         else
+            png_memcpy(to->data, from->data, from->size);
+      }
+   }
+
+   info_ptr->unknown_chunks = np;
+   info_ptr->unknown_chunks_num += num_unknowns;
 #ifdef PNG_FREE_ME_SUPPORTED
-    info_ptr->free_me |= PNG_FREE_UNKN;
+   info_ptr->free_me |= PNG_FREE_UNKN;
 #endif
 }
 void PNGAPI
 png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
    int chunk, int location)
 {
-   if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
-         (int)info_ptr->unknown_chunks_num)
+   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
+       (int)info_ptr->unknown_chunks_num)
       info_ptr->unknown_chunks[chunk].location = (png_byte)location;
 }
 #endif
@@ -1098,7 +1049,9 @@ png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
 {
    /* This function is deprecated in favor of png_permit_mng_features()
       and will be removed from libpng-1.3.0 */
-   png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");
+
+   png_debug(1, "in png_permit_empty_plte, DEPRECATED.");
+
    if (png_ptr == NULL)
       return;
    png_ptr->mng_features_permitted = (png_byte)
@@ -1108,11 +1061,12 @@ png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
 #endif
 #endif
 
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
 png_uint_32 PNGAPI
 png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
 {
-   png_debug(1, "in png_permit_mng_features\n");
+   png_debug(1, "in png_permit_mng_features");
+
    if (png_ptr == NULL)
       return (png_uint_32)0;
    png_ptr->mng_features_permitted =
@@ -1121,96 +1075,97 @@ png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
 }
 #endif
 
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
 void PNGAPI
 png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep
    chunk_list, int num_chunks)
 {
-    png_bytep new_list, p;
-    int i, old_num_chunks;
-    if (png_ptr == NULL)
-       return;
-    if (num_chunks == 0)
-    {
-      if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
-        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+   png_bytep new_list, p;
+   int i, old_num_chunks;
+   if (png_ptr == NULL)
+      return;
+   if (num_chunks == 0)
+   {
+      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
+         png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
       else
-        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+         png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
 
-      if(keep == PNG_HANDLE_CHUNK_ALWAYS)
-        png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+      if (keep == PNG_HANDLE_CHUNK_ALWAYS)
+         png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
       else
-        png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+         png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
       return;
-    }
-    if (chunk_list == NULL)
+   }
+   if (chunk_list == NULL)
       return;
-    old_num_chunks=png_ptr->num_chunk_list;
-    new_list=(png_bytep)png_malloc(png_ptr,
-       (png_uint_32)(5*(num_chunks+old_num_chunks)));
-    if(png_ptr->chunk_list != NULL)
-    {
-       png_memcpy(new_list, png_ptr->chunk_list,
+   old_num_chunks = png_ptr->num_chunk_list;
+   new_list=(png_bytep)png_malloc(png_ptr,
+      (png_uint_32)
+       (5*(num_chunks + old_num_chunks)));
+   if (png_ptr->chunk_list != NULL)
+   {
+      png_memcpy(new_list, png_ptr->chunk_list,
           (png_size_t)(5*old_num_chunks));
-       png_free(png_ptr, png_ptr->chunk_list);
-       png_ptr->chunk_list=NULL;
-    }
-    png_memcpy(new_list+5*old_num_chunks, chunk_list,
+      png_free(png_ptr, png_ptr->chunk_list);
+      png_ptr->chunk_list=NULL;
+   }
+   png_memcpy(new_list + 5*old_num_chunks, chunk_list,
        (png_size_t)(5*num_chunks));
-    for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5)
-       *p=(png_byte)keep;
-    png_ptr->num_chunk_list=old_num_chunks+num_chunks;
-    png_ptr->chunk_list=new_list;
+   for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
+      *p=(png_byte)keep;
+   png_ptr->num_chunk_list = old_num_chunks + num_chunks;
+   png_ptr->chunk_list = new_list;
 #ifdef PNG_FREE_ME_SUPPORTED
-    png_ptr->free_me |= PNG_FREE_LIST;
+   png_ptr->free_me |= PNG_FREE_LIST;
 #endif
 }
 #endif
 
-#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
 void PNGAPI
 png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
    png_user_chunk_ptr read_user_chunk_fn)
 {
-   png_debug(1, "in png_set_read_user_chunk_fn\n");
+   png_debug(1, "in png_set_read_user_chunk_fn");
+
    if (png_ptr == NULL)
       return;
+
    png_ptr->read_user_chunk_fn = read_user_chunk_fn;
    png_ptr->user_chunk_ptr = user_chunk_ptr;
 }
 #endif
 
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
+#ifdef PNG_INFO_IMAGE_SUPPORTED
 void PNGAPI
 png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
 {
-   png_debug1(1, "in %s storage function\n", "rows");
+   png_debug1(1, "in %s storage function", "rows");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
+   if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
       png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
    info_ptr->row_pointers = row_pointers;
-   if(row_pointers)
+   if (row_pointers)
       info_ptr->valid |= PNG_INFO_IDAT;
 }
 #endif
 
-#ifdef PNG_WRITE_SUPPORTED
 void PNGAPI
-png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size)
+png_set_compression_buffer_size(png_structp png_ptr,
+    png_uint_32 size)
 {
     if (png_ptr == NULL)
        return;
-    if(png_ptr->zbuf)
-       png_free(png_ptr, png_ptr->zbuf);
+    png_free(png_ptr, png_ptr->zbuf);
     png_ptr->zbuf_size = (png_size_t)size;
     png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
     png_ptr->zstream.next_out = png_ptr->zbuf;
     png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
 }
-#endif
 
 void PNGAPI
 png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
@@ -1222,16 +1177,17 @@ png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
 
 #ifndef PNG_1_0_X
 #ifdef PNG_ASSEMBLER_CODE_SUPPORTED
-/* function was added to libpng 1.2.0 and should always exist by default */
+/* Function was added to libpng 1.2.0 and should always exist by default */
 void PNGAPI
 png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
 {
 /* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
     if (png_ptr != NULL)
     png_ptr->asm_flags = 0;
+    asm_flags = asm_flags; /* Quiet the compiler */
 }
 
-/* this function was added to libpng 1.2.0 */
+/* This function was added to libpng 1.2.0 */
 void PNGAPI
 png_set_mmx_thresholds (png_structp png_ptr,
                         png_byte mmx_bitdepth_threshold,
@@ -1240,24 +1196,41 @@ png_set_mmx_thresholds (png_structp png_ptr,
 /* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
     if (png_ptr == NULL)
        return;
+    /* Quiet the compiler */
+    mmx_bitdepth_threshold = mmx_bitdepth_threshold;
+    mmx_rowbytes_threshold = mmx_rowbytes_threshold;
 }
 #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
 
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
-/* this function was added to libpng 1.2.6 */
+/* This function was added to libpng 1.2.6 */
 void PNGAPI
 png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
     png_uint_32 user_height_max)
 {
-    /* Images with dimensions larger than these limits will be
-     * rejected by png_set_IHDR().  To accept any PNG datastream
-     * regardless of dimensions, set both limits to 0x7ffffffL.
-     */
-    if(png_ptr == NULL) return;
-    png_ptr->user_width_max = user_width_max;
-    png_ptr->user_height_max = user_height_max;
+   /* Images with dimensions larger than these limits will be
+    * rejected by png_set_IHDR().  To accept any PNG datastream
+    * regardless of dimensions, set both limits to 0x7ffffffL.
+    */
+   if (png_ptr == NULL)
+      return;
+   png_ptr->user_width_max = user_width_max;
+   png_ptr->user_height_max = user_height_max;
 }
 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
 
+
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+void PNGAPI
+png_set_benign_errors(png_structp png_ptr, int allowed)
+{
+   png_debug(1, "in png_set_benign_errors");
+
+   if (allowed)
+      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
+   else
+      png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
+}
+#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
 #endif /* ?PNG_1_0_X */
 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngtrans.c b/graf2d/asimage/src/libAfterImage/libpng/pngtrans.c
index 1640095..6ad9dcf 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngtrans.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngtrans.c
@@ -1,47 +1,57 @@
 
 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
  *
- * Last changed in libpng 1.2.17 May 15, 2007
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.41 [December 3, 2009]
+ * Copyright (c) 1998-2009 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
-
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+
 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-/* turn on BGR-to-RGB mapping */
+/* Turn on BGR-to-RGB mapping */
 void PNGAPI
 png_set_bgr(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_bgr\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_bgr");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_BGR;
 }
 #endif
 
 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-/* turn on 16 bit byte swapping */
+/* Turn on 16 bit byte swapping */
 void PNGAPI
 png_set_swap(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_swap\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_swap");
+
+   if (png_ptr == NULL)
+      return;
    if (png_ptr->bit_depth == 16)
       png_ptr->transformations |= PNG_SWAP_BYTES;
 }
 #endif
 
 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
-/* turn on pixel packing */
+/* Turn on pixel packing */
 void PNGAPI
 png_set_packing(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_packing\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_packing");
+
+   if (png_ptr == NULL)
+      return;
    if (png_ptr->bit_depth < 8)
    {
       png_ptr->transformations |= PNG_PACK;
@@ -51,12 +61,14 @@ png_set_packing(png_structp png_ptr)
 #endif
 
 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-/* turn on packed pixel swapping */
+/* Turn on packed pixel swapping */
 void PNGAPI
 png_set_packswap(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_packswap\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_packswap");
+
+   if (png_ptr == NULL)
+      return;
    if (png_ptr->bit_depth < 8)
       png_ptr->transformations |= PNG_PACKSWAP;
 }
@@ -66,8 +78,10 @@ png_set_packswap(png_structp png_ptr)
 void PNGAPI
 png_set_shift(png_structp png_ptr, png_color_8p true_bits)
 {
-   png_debug(1, "in png_set_shift\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_shift");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_SHIFT;
    png_ptr->shift = *true_bits;
 }
@@ -78,7 +92,8 @@ png_set_shift(png_structp png_ptr, png_color_8p true_bits)
 int PNGAPI
 png_set_interlace_handling(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_interlace handling\n");
+   png_debug(1, "in png_set_interlace handling");
+
    if (png_ptr && png_ptr->interlaced)
    {
       png_ptr->transformations |= PNG_INTERLACE;
@@ -98,10 +113,16 @@ png_set_interlace_handling(png_structp png_ptr)
 void PNGAPI
 png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
 {
-   png_debug(1, "in png_set_filler\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_filler");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_FILLER;
+#ifdef PNG_LEGACY_SUPPORTED
    png_ptr->filler = (png_byte)filler;
+#else
+   png_ptr->filler = (png_uint_16)filler;
+#endif
    if (filler_loc == PNG_FILLER_AFTER)
       png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
    else
@@ -126,13 +147,15 @@ png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
    }
 }
 
-#if !defined(PNG_1_0_X)
+#ifndef PNG_1_0_X
 /* Added to libpng-1.2.7 */
 void PNGAPI
 png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
 {
-   png_debug(1, "in png_set_add_alpha\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_add_alpha");
+
+   if (png_ptr == NULL)
+      return;
    png_set_filler(png_ptr, filler, filler_loc);
    png_ptr->transformations |= PNG_ADD_ALPHA;
 }
@@ -145,8 +168,10 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
 void PNGAPI
 png_set_swap_alpha(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_swap_alpha\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_swap_alpha");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_SWAP_ALPHA;
 }
 #endif
@@ -156,8 +181,10 @@ png_set_swap_alpha(png_structp png_ptr)
 void PNGAPI
 png_set_invert_alpha(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_invert_alpha\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_invert_alpha");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_INVERT_ALPHA;
 }
 #endif
@@ -166,20 +193,23 @@ png_set_invert_alpha(png_structp png_ptr)
 void PNGAPI
 png_set_invert_mono(png_structp png_ptr)
 {
-   png_debug(1, "in png_set_invert_mono\n");
-   if(png_ptr == NULL) return;
+   png_debug(1, "in png_set_invert_mono");
+
+   if (png_ptr == NULL)
+      return;
    png_ptr->transformations |= PNG_INVERT_MONO;
 }
 
-/* invert monochrome grayscale data */
+/* Invert monochrome grayscale data */
 void /* PRIVATE */
 png_do_invert(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_invert\n");
+   png_debug(1, "in png_do_invert");
+
   /* This test removed from libpng version 1.0.13 and 1.2.0:
    *   if (row_info->bit_depth == 1 &&
    */
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row == NULL || row_info == NULL)
      return;
 #endif
@@ -226,13 +256,14 @@ png_do_invert(png_row_infop row_info, png_bytep row)
 #endif
 
 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-/* swaps byte order on 16 bit depth images */
+/* Swaps byte order on 16 bit depth images */
 void /* PRIVATE */
 png_do_swap(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_swap\n");
+   png_debug(1, "in png_do_swap");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
        row_info->bit_depth == 16)
@@ -357,13 +388,14 @@ static PNG_CONST png_byte fourbppswaptable[256] = {
    0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
 };
 
-/* swaps pixel packing order within bytes */
+/* Swaps pixel packing order within bytes */
 void /* PRIVATE */
 png_do_packswap(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_packswap\n");
+   png_debug(1, "in png_do_packswap");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
        row_info->bit_depth < 8)
@@ -389,12 +421,13 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
 
 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-/* remove filler or alpha byte(s) */
+/* Remove filler or alpha byte(s) */
 void /* PRIVATE */
 png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
 {
-   png_debug(1, "in png_do_strip_filler\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_strip_filler");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL)
 #endif
    {
@@ -404,9 +437,9 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
       png_uint_32 i;
 
       if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
-         (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
-         (flags & PNG_FLAG_STRIP_ALPHA))) &&
-         row_info->channels == 4)
+          (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
+          (flags & PNG_FLAG_STRIP_ALPHA))) &&
+          row_info->channels == 4)
       {
          if (row_info->bit_depth == 8)
          {
@@ -547,13 +580,14 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
 #endif
 
 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-/* swaps red and blue bytes within a pixel */
+/* Swaps red and blue bytes within a pixel */
 void /* PRIVATE */
 png_do_bgr(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_bgr\n");
+   png_debug(1, "in png_do_bgr");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
        (row_info->color_type & PNG_COLOR_MASK_COLOR))
@@ -624,20 +658,22 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
 
 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_LEGACY_SUPPORTED)
+    defined(PNG_LEGACY_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
 void PNGAPI
 png_set_user_transform_info(png_structp png_ptr, png_voidp
    user_transform_ptr, int user_transform_depth, int user_transform_channels)
 {
-   png_debug(1, "in png_set_user_transform_info\n");
-   if(png_ptr == NULL) return;
-#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+   png_debug(1, "in png_set_user_transform_info");
+
+   if (png_ptr == NULL)
+      return;
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
    png_ptr->user_transform_ptr = user_transform_ptr;
    png_ptr->user_transform_depth = (png_byte)user_transform_depth;
    png_ptr->user_transform_channels = (png_byte)user_transform_channels;
 #else
-   if(user_transform_ptr || user_transform_depth || user_transform_channels)
+   if (user_transform_ptr || user_transform_depth || user_transform_channels)
       png_warning(png_ptr,
         "This version of libpng does not support user transform info");
 #endif
@@ -652,8 +688,9 @@ png_set_user_transform_info(png_structp png_ptr, png_voidp
 png_voidp PNGAPI
 png_get_user_transform_ptr(png_structp png_ptr)
 {
-#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
-   if (png_ptr == NULL) return (NULL);
+   if (png_ptr == NULL)
+      return (NULL);
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
    return ((png_voidp)png_ptr->user_transform_ptr);
 #else
    return (NULL);
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngwio.c b/graf2d/asimage/src/libAfterImage/libpng/pngwio.c
index b5ac83f..44e5ea9 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngwio.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngwio.c
@@ -1,12 +1,15 @@
 
 /* pngwio.c - functions for data output
  *
- * Last changed in libpng 1.2.13 November 13, 2006
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2006 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.41 [December 3, 2009]
+ * Copyright (c) 1998-2009 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
  * This file provides a location for all output.  Users who need
  * special handling are expected to write functions that have the same
  * arguments as these and perform similar functions, but that possibly
@@ -16,14 +19,16 @@
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
 #ifdef PNG_WRITE_SUPPORTED
 
 /* Write the data to whatever output you are using.  The default routine
-   writes to a file pointer.  Note that this routine sometimes gets called
-   with very small lengths, so you should implement some kind of simple
-   buffering if you are using unbuffered writes.  This should never be asked
-   to write more than 64K on a 16 bit machine.  */
+ * writes to a file pointer.  Note that this routine sometimes gets called
+ * with very small lengths, so you should implement some kind of simple
+ * buffering if you are using unbuffered writes.  This should never be asked
+ * to write more than 64K on a 16 bit machine.
+ */
 
 void /* PRIVATE */
 png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
@@ -34,19 +39,21 @@ png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
       png_error(png_ptr, "Call to NULL write function");
 }
 
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_STDIO_SUPPORTED
 /* This is the function that does the actual writing of data.  If you are
-   not writing to a standard C stream, you should create a replacement
-   write_data function and use it at run time with png_set_write_fn(), rather
-   than changing the library. */
+ * not writing to a standard C stream, you should create a replacement
+ * write_data function and use it at run time with png_set_write_fn(), rather
+ * than changing the library.
+ */
 #ifndef USE_FAR_KEYWORD
 void PNGAPI
 png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 {
    png_uint_32 check;
 
-   if(png_ptr == NULL) return;
-#if defined(_WIN32_WCE)
+   if (png_ptr == NULL)
+      return;
+#ifdef _WIN32_WCE
    if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
       check = 0;
 #else
@@ -56,10 +63,10 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
       png_error(png_ptr, "Write Error");
 }
 #else
-/* this is the model-independent version. Since the standard I/O library
-   can't handle far buffers in the medium and small models, we have to copy
-   the data.
-*/
+/* This is the model-independent version. Since the standard I/O library
+ * can't handle far buffers in the medium and small models, we have to copy
+ * the data.
+ */
 
 #define NEAR_BUF_SIZE 1024
 #define MIN(a,b) (a <= b ? a : b)
@@ -71,13 +78,14 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
    png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
    png_FILE_p io_ptr;
 
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
    /* Check if data really is near. If so, use usual code. */
    near_data = (png_byte *)CVT_PTR_NOCHECK(data);
    io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
    if ((png_bytep)near_data == data)
    {
-#if defined(_WIN32_WCE)
+#ifdef _WIN32_WCE
       if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
          check = 0;
 #else
@@ -93,8 +101,8 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
       do
       {
          written = MIN(NEAR_BUF_SIZE, remaining);
-         png_memcpy(buf, data, written); /* copy far buffer to near buffer */
-#if defined(_WIN32_WCE)
+         png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
+#ifdef _WIN32_WCE
          if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
             err = 0;
 #else
@@ -102,8 +110,10 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 #endif
          if (err != written)
             break;
+
          else
             check += err;
+
          data += written;
          remaining -= written;
       }
@@ -117,9 +127,10 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 #endif
 
 /* This function is called to output any data pending writing (normally
-   to disk).  After png_flush is called, there should be no data pending
-   writing in any buffers. */
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+ * to disk).  After png_flush is called, there should be no data pending
+ * writing in any buffers.
+ */
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
 void /* PRIVATE */
 png_flush(png_structp png_ptr)
 {
@@ -127,65 +138,76 @@ png_flush(png_structp png_ptr)
       (*(png_ptr->output_flush_fn))(png_ptr);
 }
 
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_STDIO_SUPPORTED
 void PNGAPI
 png_default_flush(png_structp png_ptr)
 {
-#if !defined(_WIN32_WCE)
+#ifndef _WIN32_WCE
    png_FILE_p io_ptr;
 #endif
-   if(png_ptr == NULL) return;
-#if !defined(_WIN32_WCE)
+   if (png_ptr == NULL)
+      return;
+#ifndef _WIN32_WCE
    io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
-   if (io_ptr != NULL)
-      fflush(io_ptr);
+   fflush(io_ptr);
 #endif
 }
 #endif
 #endif
 
 /* This function allows the application to supply new output functions for
-   libpng if standard C streams aren't being used.
-
-   This function takes as its arguments:
-   png_ptr       - pointer to a png output data structure
-   io_ptr        - pointer to user supplied structure containing info about
-                   the output functions.  May be NULL.
-   write_data_fn - pointer to a new output function that takes as its
-                   arguments a pointer to a png_struct, a pointer to
-                   data to be written, and a 32-bit unsigned int that is
-                   the number of bytes to be written.  The new write
-                   function should call png_error(png_ptr, "Error msg")
-                   to exit and output any fatal error messages.
-   flush_data_fn - pointer to a new flush function that takes as its
-                   arguments a pointer to a png_struct.  After a call to
-                   the flush function, there should be no data in any buffers
-                   or pending transmission.  If the output method doesn't do
-                   any buffering of output, a function prototype must still be
-                   supplied although it doesn't have to do anything.  If
-                   PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
-                   time, output_flush_fn will be ignored, although it must be
-                   supplied for compatibility. */
+ * libpng if standard C streams aren't being used.
+ *
+ * This function takes as its arguments:
+ * png_ptr       - pointer to a png output data structure
+ * io_ptr        - pointer to user supplied structure containing info about
+ *                 the output functions.  May be NULL.
+ * write_data_fn - pointer to a new output function that takes as its
+ *                 arguments a pointer to a png_struct, a pointer to
+ *                 data to be written, and a 32-bit unsigned int that is
+ *                 the number of bytes to be written.  The new write
+ *                 function should call png_error(png_ptr, "Error msg")
+ *                 to exit and output any fatal error messages.  May be
+ *                 NULL, in which case libpng's default function will
+ *                 be used.
+ * flush_data_fn - pointer to a new flush function that takes as its
+ *                 arguments a pointer to a png_struct.  After a call to
+ *                 the flush function, there should be no data in any buffers
+ *                 or pending transmission.  If the output method doesn't do
+ *                 any buffering of output, a function prototype must still be
+ *                 supplied although it doesn't have to do anything.  If
+ *                 PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
+ *                 time, output_flush_fn will be ignored, although it must be
+ *                 supplied for compatibility.  May be NULL, in which case
+ *                 libpng's default function will be used, if
+ *                 PNG_WRITE_FLUSH_SUPPORTED is defined.  This is not
+ *                 a good idea if io_ptr does not point to a standard
+ *                 *FILE structure.
+ */
 void PNGAPI
 png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
    png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
+
    png_ptr->io_ptr = io_ptr;
 
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_STDIO_SUPPORTED
    if (write_data_fn != NULL)
       png_ptr->write_data_fn = write_data_fn;
+
    else
       png_ptr->write_data_fn = png_default_write_data;
 #else
    png_ptr->write_data_fn = write_data_fn;
 #endif
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
-#if !defined(PNG_NO_STDIO)
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED
    if (output_flush_fn != NULL)
       png_ptr->output_flush_fn = output_flush_fn;
+
    else
       png_ptr->output_flush_fn = png_default_flush;
 #else
@@ -204,29 +226,33 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
    }
 }
 
-#if defined(USE_FAR_KEYWORD)
-#if defined(_MSC_VER)
-void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
+#ifdef USE_FAR_KEYWORD
+#ifdef _MSC_VER
+void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
 {
    void *near_ptr;
    void FAR *far_ptr;
    FP_OFF(near_ptr) = FP_OFF(ptr);
    far_ptr = (void FAR *)near_ptr;
-   if(check != 0)
-      if(FP_SEG(ptr) != FP_SEG(far_ptr))
-         png_error(png_ptr,"segment lost in conversion");
+
+   if (check != 0)
+      if (FP_SEG(ptr) != FP_SEG(far_ptr))
+         png_error(png_ptr, "segment lost in conversion");
+
    return(near_ptr);
 }
 #  else
-void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
+void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
 {
    void *near_ptr;
    void FAR *far_ptr;
    near_ptr = (void FAR *)ptr;
    far_ptr = (void FAR *)near_ptr;
-   if(check != 0)
-      if(far_ptr != ptr)
-         png_error(png_ptr,"segment lost in conversion");
+
+   if (check != 0)
+      if (far_ptr != ptr)
+         png_error(png_ptr, "segment lost in conversion");
+
    return(near_ptr);
 }
 #   endif
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngwrite.c b/graf2d/asimage/src/libAfterImage/libpng/pngwrite.c
index c6df1ef..1d8c53f 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngwrite.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngwrite.c
@@ -1,15 +1,19 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Last changed in libpng 1.2.15 January 5, 2007
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
  */
 
-/* get internal access to png.h */
+/* Get internal access to png.h */
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
 #ifdef PNG_WRITE_SUPPORTED
 
@@ -25,31 +29,35 @@
 void PNGAPI
 png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
 {
-   png_debug(1, "in png_write_info_before_PLTE\n");
+   png_debug(1, "in png_write_info_before_PLTE");
+
    if (png_ptr == NULL || info_ptr == NULL)
       return;
    if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
    {
-   png_write_sig(png_ptr); /* write PNG signature */
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
+   /* Write PNG signature */
+   png_write_sig(png_ptr);
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+   if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \
+      (png_ptr->mng_features_permitted))
    {
-      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream");
-      png_ptr->mng_features_permitted=0;
+      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
+      png_ptr->mng_features_permitted = 0;
    }
 #endif
-   /* write IHDR information. */
+   /* Write IHDR information. */
    png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
       info_ptr->filter_type,
-#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
       info_ptr->interlace_type);
 #else
       0);
 #endif
-   /* the rest of these check to see if the valid field has the appropriate
-      flag set, and if it does, writes the chunk. */
-#if defined(PNG_WRITE_gAMA_SUPPORTED)
+   /* The rest of these check to see if the valid field has the appropriate
+    * flag set, and if it does, writes the chunk.
+    */
+#ifdef PNG_WRITE_gAMA_SUPPORTED
    if (info_ptr->valid & PNG_INFO_gAMA)
    {
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
@@ -61,20 +69,20 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
 #endif
    }
 #endif
-#if defined(PNG_WRITE_sRGB_SUPPORTED)
+#ifdef PNG_WRITE_sRGB_SUPPORTED
    if (info_ptr->valid & PNG_INFO_sRGB)
       png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
 #endif
-#if defined(PNG_WRITE_iCCP_SUPPORTED)
+#ifdef PNG_WRITE_iCCP_SUPPORTED
    if (info_ptr->valid & PNG_INFO_iCCP)
       png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
                      info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
 #endif
-#if defined(PNG_WRITE_sBIT_SUPPORTED)
+#ifdef PNG_WRITE_sBIT_SUPPORTED
    if (info_ptr->valid & PNG_INFO_sBIT)
       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
 #endif
-#if defined(PNG_WRITE_cHRM_SUPPORTED)
+#ifdef PNG_WRITE_cHRM_SUPPORTED
    if (info_ptr->valid & PNG_INFO_cHRM)
    {
 #ifdef PNG_FLOATING_POINT_SUPPORTED
@@ -94,27 +102,29 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
 #endif
    }
 #endif
-#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
    if (info_ptr->unknown_chunks_num)
    {
-       png_unknown_chunk *up;
+      png_unknown_chunk *up;
 
-       png_debug(5, "writing extra chunks\n");
+      png_debug(5, "writing extra chunks");
 
-       for (up = info_ptr->unknown_chunks;
-            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-            up++)
-       {
-         int keep=png_handle_as_unknown(png_ptr, up->name);
+      for (up = info_ptr->unknown_chunks;
+           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+           up++)
+      {
+         int keep = png_handle_as_unknown(png_ptr, up->name);
          if (keep != PNG_HANDLE_CHUNK_NEVER &&
             up->location && !(up->location & PNG_HAVE_PLTE) &&
             !(up->location & PNG_HAVE_IDAT) &&
             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
          {
+            if (up->size == 0)
+               png_warning(png_ptr, "Writing zero-length unknown chunk");
             png_write_chunk(png_ptr, up->name, up->data, up->size);
          }
-       }
+      }
    }
 #endif
       png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
@@ -128,7 +138,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
    int i;
 #endif
 
-   png_debug(1, "in png_write_info\n");
+   png_debug(1, "in png_write_info");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
@@ -141,85 +151,92 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       png_error(png_ptr, "Valid palette required for paletted images");
 
-#if defined(PNG_WRITE_tRNS_SUPPORTED)
+#ifdef PNG_WRITE_tRNS_SUPPORTED
    if (info_ptr->valid & PNG_INFO_tRNS)
+   {
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+      /* Invert the alpha channel (in tRNS) */
+      if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
+         info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       {
-#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
-         /* invert the alpha channel (in tRNS) */
-         if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
-            info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-         {
-            int j;
-            for (j=0; j<(int)info_ptr->num_trans; j++)
-               info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
-         }
+         int j;
+         for (j = 0; j<(int)info_ptr->num_trans; j++)
+            info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
+      }
 #endif
       png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
          info_ptr->num_trans, info_ptr->color_type);
-      }
+   }
 #endif
-#if defined(PNG_WRITE_bKGD_SUPPORTED)
+#ifdef PNG_WRITE_bKGD_SUPPORTED
    if (info_ptr->valid & PNG_INFO_bKGD)
       png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
 #endif
-#if defined(PNG_WRITE_hIST_SUPPORTED)
+#ifdef PNG_WRITE_hIST_SUPPORTED
    if (info_ptr->valid & PNG_INFO_hIST)
       png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
 #endif
-#if defined(PNG_WRITE_oFFs_SUPPORTED)
+#ifdef PNG_WRITE_oFFs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_oFFs)
       png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
          info_ptr->offset_unit_type);
 #endif
-#if defined(PNG_WRITE_pCAL_SUPPORTED)
+#ifdef PNG_WRITE_pCAL_SUPPORTED
    if (info_ptr->valid & PNG_INFO_pCAL)
       png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
          info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
          info_ptr->pcal_units, info_ptr->pcal_params);
 #endif
-#if defined(PNG_WRITE_sCAL_SUPPORTED)
+
+#ifdef PNG_sCAL_SUPPORTED
    if (info_ptr->valid & PNG_INFO_sCAL)
-#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+#ifdef PNG_WRITE_sCAL_SUPPORTED
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
       png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
           info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
-#else
+#else /* !FLOATING_POINT */
 #ifdef PNG_FIXED_POINT_SUPPORTED
       png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
           info_ptr->scal_s_width, info_ptr->scal_s_height);
-#else
+#endif /* FIXED_POINT */
+#endif /* FLOATING_POINT */
+#else  /* !WRITE_sCAL */
       png_warning(png_ptr,
           "png_write_sCAL not supported; sCAL chunk not written.");
-#endif
-#endif
-#endif
-#if defined(PNG_WRITE_pHYs_SUPPORTED)
+#endif /* WRITE_sCAL */
+#endif /* sCAL */
+
+#ifdef PNG_WRITE_pHYs_SUPPORTED
    if (info_ptr->valid & PNG_INFO_pHYs)
       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
-#endif
-#if defined(PNG_WRITE_tIME_SUPPORTED)
+#endif /* pHYs */
+
+#ifdef PNG_WRITE_tIME_SUPPORTED
    if (info_ptr->valid & PNG_INFO_tIME)
    {
       png_write_tIME(png_ptr, &(info_ptr->mod_time));
       png_ptr->mode |= PNG_WROTE_tIME;
    }
-#endif
-#if defined(PNG_WRITE_sPLT_SUPPORTED)
+#endif /* tIME */
+
+#ifdef PNG_WRITE_sPLT_SUPPORTED
    if (info_ptr->valid & PNG_INFO_sPLT)
      for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
        png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
-#endif
-#if defined(PNG_WRITE_TEXT_SUPPORTED)
+#endif /* sPLT */
+
+#ifdef PNG_WRITE_TEXT_SUPPORTED
    /* Check to see if we need to write text chunks */
    for (i = 0; i < info_ptr->num_text; i++)
    {
-      png_debug2(2, "Writing header text chunk %d, type %d\n", i,
+      png_debug2(2, "Writing header text chunk %d, type %d", i,
          info_ptr->text[i].compression);
-      /* an internationalized chunk? */
+      /* An internationalized chunk? */
       if (info_ptr->text[i].compression > 0)
       {
-#if defined(PNG_WRITE_iTXt_SUPPORTED)
-          /* write international chunk */
+#ifdef PNG_WRITE_iTXt_SUPPORTED
+          /* Write international chunk */
           png_write_iTXt(png_ptr,
                          info_ptr->text[i].compression,
                          info_ptr->text[i].key,
@@ -235,8 +252,8 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
       /* If we want a compressed text chunk */
       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
       {
-#if defined(PNG_WRITE_zTXt_SUPPORTED)
-         /* write compressed chunk */
+#ifdef PNG_WRITE_zTXt_SUPPORTED
+         /* Write compressed chunk */
          png_write_zTXt(png_ptr, info_ptr->text[i].key,
             info_ptr->text[i].text, 0,
             info_ptr->text[i].compression);
@@ -248,40 +265,43 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
       }
       else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
       {
-#if defined(PNG_WRITE_tEXt_SUPPORTED)
-         /* write uncompressed chunk */
+#ifdef PNG_WRITE_tEXt_SUPPORTED
+         /* Write uncompressed chunk */
          png_write_tEXt(png_ptr, info_ptr->text[i].key,
                          info_ptr->text[i].text,
                          0);
+         /* Mark this chunk as written */
+         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
 #else
+         /* Can't get here */
          png_warning(png_ptr, "Unable to write uncompressed text");
 #endif
-         /* Mark this chunk as written */
-         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
       }
    }
-#endif
-#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+#endif /* tEXt */
+
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
    if (info_ptr->unknown_chunks_num)
    {
-       png_unknown_chunk *up;
+      png_unknown_chunk *up;
 
-       png_debug(5, "writing extra chunks\n");
+      png_debug(5, "writing extra chunks");
 
-       for (up = info_ptr->unknown_chunks;
-            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-            up++)
-       {
-         int keep=png_handle_as_unknown(png_ptr, up->name);
+      for (up = info_ptr->unknown_chunks;
+           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+           up++)
+      {
+         int keep = png_handle_as_unknown(png_ptr, up->name);
          if (keep != PNG_HANDLE_CHUNK_NEVER &&
             up->location && (up->location & PNG_HAVE_PLTE) &&
             !(up->location & PNG_HAVE_IDAT) &&
+            !(up->location & PNG_AFTER_IDAT) &&
             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
             (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
          {
             png_write_chunk(png_ptr, up->name, up->data, up->size);
          }
-       }
+      }
    }
 #endif
 }
@@ -294,51 +314,52 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
 void PNGAPI
 png_write_end(png_structp png_ptr, png_infop info_ptr)
 {
-   png_debug(1, "in png_write_end\n");
+   png_debug(1, "in png_write_end");
+
    if (png_ptr == NULL)
       return;
    if (!(png_ptr->mode & PNG_HAVE_IDAT))
       png_error(png_ptr, "No IDATs written into file");
 
-   /* see if user wants us to write information chunks */
+   /* See if user wants us to write information chunks */
    if (info_ptr != NULL)
    {
-#if defined(PNG_WRITE_TEXT_SUPPORTED)
+#ifdef PNG_WRITE_TEXT_SUPPORTED
       int i; /* local index variable */
 #endif
-#if defined(PNG_WRITE_tIME_SUPPORTED)
-      /* check to see if user has supplied a time chunk */
+#ifdef PNG_WRITE_tIME_SUPPORTED
+      /* Check to see if user has supplied a time chunk */
       if ((info_ptr->valid & PNG_INFO_tIME) &&
          !(png_ptr->mode & PNG_WROTE_tIME))
          png_write_tIME(png_ptr, &(info_ptr->mod_time));
 #endif
-#if defined(PNG_WRITE_TEXT_SUPPORTED)
-      /* loop through comment chunks */
+#ifdef PNG_WRITE_TEXT_SUPPORTED
+      /* Loop through comment chunks */
       for (i = 0; i < info_ptr->num_text; i++)
       {
-         png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
+         png_debug2(2, "Writing trailer text chunk %d, type %d", i,
             info_ptr->text[i].compression);
-         /* an internationalized chunk? */
+         /* An internationalized chunk? */
          if (info_ptr->text[i].compression > 0)
          {
-#if defined(PNG_WRITE_iTXt_SUPPORTED)
-             /* write international chunk */
-             png_write_iTXt(png_ptr,
-                         info_ptr->text[i].compression,
-                         info_ptr->text[i].key,
-                         info_ptr->text[i].lang,
-                         info_ptr->text[i].lang_key,
-                         info_ptr->text[i].text);
+#ifdef PNG_WRITE_iTXt_SUPPORTED
+            /* Write international chunk */
+            png_write_iTXt(png_ptr,
+                        info_ptr->text[i].compression,
+                        info_ptr->text[i].key,
+                        info_ptr->text[i].lang,
+                        info_ptr->text[i].lang_key,
+                        info_ptr->text[i].text);
 #else
-             png_warning(png_ptr, "Unable to write international text");
+            png_warning(png_ptr, "Unable to write international text");
 #endif
-             /* Mark this chunk as written */
-             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+            /* Mark this chunk as written */
+            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
          }
          else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
          {
-#if defined(PNG_WRITE_zTXt_SUPPORTED)
-            /* write compressed chunk */
+#ifdef PNG_WRITE_zTXt_SUPPORTED
+            /* Write compressed chunk */
             png_write_zTXt(png_ptr, info_ptr->text[i].key,
                info_ptr->text[i].text, 0,
                info_ptr->text[i].compression);
@@ -350,8 +371,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
          }
          else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
          {
-#if defined(PNG_WRITE_tEXt_SUPPORTED)
-            /* write uncompressed chunk */
+#ifdef PNG_WRITE_tEXt_SUPPORTED
+            /* Write uncompressed chunk */
             png_write_tEXt(png_ptr, info_ptr->text[i].key,
                info_ptr->text[i].text, 0);
 #else
@@ -363,18 +384,18 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
          }
       }
 #endif
-#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
    if (info_ptr->unknown_chunks_num)
    {
-       png_unknown_chunk *up;
+      png_unknown_chunk *up;
 
-       png_debug(5, "writing extra chunks\n");
+      png_debug(5, "writing extra chunks");
 
-       for (up = info_ptr->unknown_chunks;
-            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-            up++)
-       {
-         int keep=png_handle_as_unknown(png_ptr, up->name);
+      for (up = info_ptr->unknown_chunks;
+           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+           up++)
+      {
+         int keep = png_handle_as_unknown(png_ptr, up->name);
          if (keep != PNG_HANDLE_CHUNK_NEVER &&
             up->location && (up->location & PNG_AFTER_IDAT) &&
             ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
@@ -382,24 +403,36 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
          {
             png_write_chunk(png_ptr, up->name, up->data, up->size);
          }
-       }
+      }
    }
 #endif
    }
 
    png_ptr->mode |= PNG_AFTER_IDAT;
 
-   /* write end of PNG file */
+   /* Write end of PNG file */
    png_write_IEND(png_ptr);
+   /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
+    * and restored again in libpng-1.2.30, may cause some applications that
+    * do not set png_ptr->output_flush_fn to crash.  If your application
+    * experiences a problem, please try building libpng with
+    * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
+    * png-mng-implement at lists.sf.net .
+    */
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+#  ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
+   png_flush(png_ptr);
+#  endif
+#endif
 }
 
-#if defined(PNG_WRITE_tIME_SUPPORTED)
-#if !defined(_WIN32_WCE)
-/* "time.h" functions are not supported on WindowsCE */
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+/* "tm" structure is not supported on WindowsCE */
 void PNGAPI
 png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
 {
-   png_debug(1, "in png_convert_from_struct_tm\n");
+   png_debug(1, "in png_convert_from_struct_tm");
+
    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
    ptime->month = (png_byte)(ttime->tm_mon + 1);
    ptime->day = (png_byte)ttime->tm_mday;
@@ -413,12 +446,12 @@ png_convert_from_time_t(png_timep ptime, time_t ttime)
 {
    struct tm *tbuf;
 
-   png_debug(1, "in png_convert_from_time_t\n");
+   png_debug(1, "in png_convert_from_time_t");
+
    tbuf = gmtime(&ttime);
    png_convert_from_struct_tm(ptime, tbuf);
 }
 #endif
-#endif
 
 /* Initialize png_ptr structure, and allocate any memory needed */
 png_structp PNGAPI
@@ -437,6 +470,9 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
    png_malloc_ptr malloc_fn, png_free_ptr free_fn)
 {
 #endif /* PNG_USER_MEM_SUPPORTED */
+#ifdef PNG_SETJMP_SUPPORTED
+   volatile
+#endif
    png_structp png_ptr;
 #ifdef PNG_SETJMP_SUPPORTED
 #ifdef USE_FAR_KEYWORD
@@ -444,7 +480,9 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 #endif
 #endif
    int i;
-   png_debug(1, "in png_create_write_struct\n");
+
+   png_debug(1, "in png_create_write_struct");
+
 #ifdef PNG_USER_MEM_SUPPORTED
    png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
       (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
@@ -454,10 +492,10 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
    if (png_ptr == NULL)
       return (NULL);
 
-   /* added at libpng-1.2.6 */
+   /* Added at libpng-1.2.6 */
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
-   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
+   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
@@ -468,12 +506,17 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 #endif
    {
       png_free(png_ptr, png_ptr->zbuf);
-      png_ptr->zbuf=NULL;
-      png_destroy_struct(png_ptr);
+      png_ptr->zbuf = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)png_ptr,
+         (png_free_ptr)free_fn, (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)png_ptr);
+#endif
       return (NULL);
    }
 #ifdef USE_FAR_KEYWORD
-   png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
+   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
 #endif
 #endif
 
@@ -482,12 +525,15 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
 #endif /* PNG_USER_MEM_SUPPORTED */
    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
 
-   i=0;
-   do
+   if (user_png_ver)
    {
-     if(user_png_ver[i] != png_libpng_ver[i])
-        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-   } while (png_libpng_ver[i++]);
+      i = 0;
+      do
+      {
+         if (user_png_ver[i] != png_libpng_ver[i])
+            png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+      } while (png_libpng_ver[i++]);
+   }
 
    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
    {
@@ -500,14 +546,14 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
      {
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
         char msg[80];
         if (user_png_ver)
         {
-          png_snprintf(msg, 80,
-             "Application was compiled with png.h from libpng-%.20s",
-             user_png_ver);
-          png_warning(png_ptr, msg);
+           png_snprintf(msg, 80,
+              "Application was compiled with png.h from libpng-%.20s",
+              user_png_ver);
+           png_warning(png_ptr, msg);
         }
         png_snprintf(msg, 80,
            "Application  is  running with png.c from libpng-%.20s",
@@ -515,34 +561,35 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
         png_warning(png_ptr, msg);
 #endif
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-        png_ptr->flags=0;
+        png_ptr->flags = 0;
 #endif
         png_error(png_ptr,
            "Incompatible libpng version in application and library");
      }
    }
 
-   /* initialize zbuf - compression buffer */
+   /* Initialize zbuf - compression buffer */
    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
-      (png_uint_32)png_ptr->zbuf_size);
+     (png_uint_32)png_ptr->zbuf_size);
 
    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
       png_flush_ptr_NULL);
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
       1, png_doublep_NULL, png_doublep_NULL);
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
-/* Applications that neglect to set up their own setjmp() and then encounter
-   a png_error() will longjmp here.  Since the jmpbuf is then meaningless we
-   abort instead of returning. */
+   /* Applications that neglect to set up their own setjmp() and then
+    * encounter a png_error() will longjmp here.  Since the jmpbuf is
+    * then meaningless we abort instead of returning.
+    */
 #ifdef USE_FAR_KEYWORD
    if (setjmp(jmpbuf))
       PNG_ABORT();
-   png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
+   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
 #else
    if (setjmp(png_ptr->jmpbuf))
       PNG_ABORT();
@@ -567,19 +614,19 @@ png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
    png_size_t png_struct_size, png_size_t png_info_size)
 {
    /* We only come here via pre-1.0.12-compiled applications */
-   if(png_ptr == NULL) return;
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
-   if(png_sizeof(png_struct) > png_struct_size ||
+   if (png_ptr == NULL) return;
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+   if (png_sizeof(png_struct) > png_struct_size ||
       png_sizeof(png_info) > png_info_size)
    {
       char msg[80];
-      png_ptr->warning_fn=NULL;
+      png_ptr->warning_fn = NULL;
       if (user_png_ver)
       {
-        png_snprintf(msg, 80,
-           "Application was compiled with png.h from libpng-%.20s",
-           user_png_ver);
-        png_warning(png_ptr, msg);
+         png_snprintf(msg, 80,
+            "Application was compiled with png.h from libpng-%.20s",
+            user_png_ver);
+         png_warning(png_ptr, msg);
       }
       png_snprintf(msg, 80,
          "Application  is  running with png.c from libpng-%.20s",
@@ -587,24 +634,26 @@ png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
       png_warning(png_ptr, msg);
    }
 #endif
-   if(png_sizeof(png_struct) > png_struct_size)
-     {
-       png_ptr->error_fn=NULL;
+   if (png_sizeof(png_struct) > png_struct_size)
+   {
+      png_ptr->error_fn = NULL;
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-       png_ptr->flags=0;
+      png_ptr->flags = 0;
 #endif
-       png_error(png_ptr,
-       "The png struct allocated by the application for writing is too small.");
-     }
-   if(png_sizeof(png_info) > png_info_size)
-     {
-       png_ptr->error_fn=NULL;
+      png_error(png_ptr,
+      "The png struct allocated by the application for writing is"
+      " too small.");
+   }
+   if (png_sizeof(png_info) > png_info_size)
+   {
+      png_ptr->error_fn = NULL;
 #ifdef PNG_ERROR_NUMBERS_SUPPORTED
-       png_ptr->flags=0;
+      png_ptr->flags = 0;
 #endif
-       png_error(png_ptr,
-       "The info struct allocated by the application for writing is too small.");
-     }
+      png_error(png_ptr,
+      "The info struct allocated by the application for writing is"
+      " too small.");
+   }
    png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
 }
 #endif /* PNG_1_0_X || PNG_1_2_X */
@@ -614,7 +663,7 @@ void PNGAPI
 png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
    png_size_t png_struct_size)
 {
-   png_structp png_ptr=*ptr_ptr;
+   png_structp png_ptr = *ptr_ptr;
 #ifdef PNG_SETJMP_SUPPORTED
    jmp_buf tmp_jmp; /* to save current jump buffer */
 #endif
@@ -626,56 +675,54 @@ png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
 
    do
    {
-     if (user_png_ver[i] != png_libpng_ver[i])
-     {
+      if (user_png_ver[i] != png_libpng_ver[i])
+      {
 #ifdef PNG_LEGACY_SUPPORTED
-       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+         png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
 #else
-       png_ptr->warning_fn=NULL;
-       png_warning(png_ptr,
-     "Application uses deprecated png_write_init() and should be recompiled.");
-       break;
+         png_ptr->warning_fn = NULL;
+         png_warning(png_ptr,
+ "Application uses deprecated png_write_init() and should be recompiled.");
 #endif
-     }
+      }
    } while (png_libpng_ver[i++]);
 
-   png_debug(1, "in png_write_init_3\n");
+   png_debug(1, "in png_write_init_3");
 
 #ifdef PNG_SETJMP_SUPPORTED
-   /* save jump buffer and error functions */
-   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
+   /* Save jump buffer and error functions */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
 #endif
 
    if (png_sizeof(png_struct) > png_struct_size)
-     {
-       png_destroy_struct(png_ptr);
-       png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-       *ptr_ptr = png_ptr;
-     }
+   {
+      png_destroy_struct(png_ptr);
+      png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+      *ptr_ptr = png_ptr;
+   }
 
-   /* reset all variables to 0 */
-   png_memset(png_ptr, 0, png_sizeof (png_struct));
+   /* Reset all variables to 0 */
+   png_memset(png_ptr, 0, png_sizeof(png_struct));
 
-   /* added at libpng-1.2.6 */
+   /* Added at libpng-1.2.6 */
 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
-   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
+   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
-   /* restore jump buffer */
-   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
+   /* Restore jump buffer */
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
 #endif
 
    png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
       png_flush_ptr_NULL);
 
-   /* initialize zbuf - compression buffer */
+   /* Initialize zbuf - compression buffer */
    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
-      (png_uint_32)png_ptr->zbuf_size);
-
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+     (png_uint_32)png_ptr->zbuf_size);
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
    png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
       1, png_doublep_NULL, png_doublep_NULL);
 #endif
@@ -693,12 +740,12 @@ png_write_rows(png_structp png_ptr, png_bytepp row,
    png_uint_32 i; /* row counter */
    png_bytepp rp; /* row pointer */
 
-   png_debug(1, "in png_write_rows\n");
+   png_debug(1, "in png_write_rows");
 
    if (png_ptr == NULL)
       return;
 
-   /* loop through the rows */
+   /* Loop through the rows */
    for (i = 0, rp = row; i < num_rows; i++, rp++)
    {
       png_write_row(png_ptr, *rp);
@@ -718,18 +765,20 @@ png_write_image(png_structp png_ptr, png_bytepp image)
    if (png_ptr == NULL)
       return;
 
-   png_debug(1, "in png_write_image\n");
-#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
-   /* intialize interlace handling.  If image is not interlaced,
-      this will set pass to 1 */
+   png_debug(1, "in png_write_image");
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   /* Initialize interlace handling.  If image is not interlaced,
+    * this will set pass to 1
+    */
    num_pass = png_set_interlace_handling(png_ptr);
 #else
    num_pass = 1;
 #endif
-   /* loop through passes */
+   /* Loop through passes */
    for (pass = 0; pass < num_pass; pass++)
    {
-      /* loop through image */
+      /* Loop through image */
       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
       {
          png_write_row(png_ptr, *rp);
@@ -737,58 +786,63 @@ png_write_image(png_structp png_ptr, png_bytepp image)
    }
 }
 
-/* called by user to write a row of image data */
+/* Called by user to write a row of image data */
 void PNGAPI
 png_write_row(png_structp png_ptr, png_bytep row)
 {
    if (png_ptr == NULL)
       return;
-   png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
+
+   png_debug2(1, "in png_write_row (row %ld, pass %d)",
       png_ptr->row_number, png_ptr->pass);
 
-   /* initialize transformations and other stuff if first time */
+   /* Initialize transformations and other stuff if first time */
    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
    {
-   /* make sure we wrote the header info */
-   if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
-      png_error(png_ptr,
-         "png_write_info was never called before png_write_row.");
+      /* Make sure we wrote the header info */
+      if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+         png_error(png_ptr,
+            "png_write_info was never called before png_write_row.");
 
-   /* check for transforms that have been set but were defined out */
+      /* Check for transforms that have been set but were defined out */
 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
-   if (png_ptr->transformations & PNG_INVERT_MONO)
-      png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
+      if (png_ptr->transformations & PNG_INVERT_MONO)
+         png_warning(png_ptr,
+             "PNG_WRITE_INVERT_SUPPORTED is not defined.");
 #endif
 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
-   if (png_ptr->transformations & PNG_FILLER)
-      png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
+      if (png_ptr->transformations & PNG_FILLER)
+         png_warning(png_ptr,
+             "PNG_WRITE_FILLER_SUPPORTED is not defined.");
 #endif
-#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
-   if (png_ptr->transformations & PNG_PACKSWAP)
-      png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
+#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
+    defined(PNG_READ_PACKSWAP_SUPPORTED)
+      if (png_ptr->transformations & PNG_PACKSWAP)
+         png_warning(png_ptr,
+             "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
 #endif
 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
-   if (png_ptr->transformations & PNG_PACK)
-      png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
+      if (png_ptr->transformations & PNG_PACK)
+         png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
 #endif
 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
-   if (png_ptr->transformations & PNG_SHIFT)
-      png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
+      if (png_ptr->transformations & PNG_SHIFT)
+         png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
 #endif
 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
-   if (png_ptr->transformations & PNG_BGR)
-      png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
+      if (png_ptr->transformations & PNG_BGR)
+         png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
 #endif
 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
-   if (png_ptr->transformations & PNG_SWAP_BYTES)
-      png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
+      if (png_ptr->transformations & PNG_SWAP_BYTES)
+         png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
 #endif
 
       png_write_start_row(png_ptr);
    }
 
-#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
-   /* if interlaced and not interested in row, return */
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   /* If interlaced and not interested in row, return */
    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
    {
       switch (png_ptr->pass)
@@ -846,7 +900,7 @@ png_write_row(png_structp png_ptr, png_bytep row)
    }
 #endif
 
-   /* set up row info for transformations */
+   /* Set up row info for transformations */
    png_ptr->row_info.color_type = png_ptr->color_type;
    png_ptr->row_info.width = png_ptr->usr_width;
    png_ptr->row_info.channels = png_ptr->usr_channels;
@@ -857,25 +911,25 @@ png_write_row(png_structp png_ptr, png_bytep row)
    png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
       png_ptr->row_info.width);
 
-   png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
-   png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width);
-   png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels);
-   png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
-   png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
-   png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes);
+   png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type);
+   png_debug1(3, "row_info->width = %lu", png_ptr->row_info.width);
+   png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels);
+   png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth);
+   png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth);
+   png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes);
 
    /* Copy user's row into buffer, leaving room for filter byte. */
    png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
       png_ptr->row_info.rowbytes);
 
-#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
-   /* handle interlacing */
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   /* Handle interlacing */
    if (png_ptr->interlaced && png_ptr->pass < 6 &&
       (png_ptr->transformations & PNG_INTERLACE))
    {
       png_do_write_interlace(&(png_ptr->row_info),
          png_ptr->row_buf + 1, png_ptr->pass);
-      /* this should always get caught above, but still ... */
+      /* This should always get caught above, but still ... */
       if (!(png_ptr->row_info.width))
       {
          png_write_finish_row(png_ptr);
@@ -884,11 +938,11 @@ png_write_row(png_structp png_ptr, png_bytep row)
    }
 #endif
 
-   /* handle other transformations */
+   /* Handle other transformations */
    if (png_ptr->transformations)
       png_do_write_transformations(png_ptr);
 
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
    /* Write filter_method 64 (intrapixel differencing) only if
     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
     * 2. Libpng did not write a PNG signature (this filter_method is only
@@ -898,7 +952,7 @@ png_write_row(png_structp png_ptr, png_bytep row)
     * 4. The filter_method is 64 and
     * 5. The color_type is RGB or RGBA
     */
-   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
    {
       /* Intrapixel differencing */
@@ -913,39 +967,41 @@ png_write_row(png_structp png_ptr, png_bytep row)
       (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
 }
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
 /* Set the automatic flush interval or 0 to turn flushing off */
 void PNGAPI
 png_set_flush(png_structp png_ptr, int nrows)
 {
-   png_debug(1, "in png_set_flush\n");
+   png_debug(1, "in png_set_flush");
+
    if (png_ptr == NULL)
       return;
    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
 }
 
-/* flush the current output buffers now */
+/* Flush the current output buffers now */
 void PNGAPI
 png_write_flush(png_structp png_ptr)
 {
    int wrote_IDAT;
 
-   png_debug(1, "in png_write_flush\n");
+   png_debug(1, "in png_write_flush");
+
    if (png_ptr == NULL)
       return;
    /* We have already written out all of the data */
    if (png_ptr->row_number >= png_ptr->num_rows)
-     return;
+      return;
 
    do
    {
       int ret;
 
-      /* compress the data */
+      /* Compress the data */
       ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
       wrote_IDAT = 0;
 
-      /* check for compression errors */
+      /* Check for compression errors */
       if (ret != Z_OK)
       {
          if (png_ptr->zstream.msg != NULL)
@@ -956,7 +1012,7 @@ png_write_flush(png_structp png_ptr)
 
       if (!(png_ptr->zstream.avail_out))
       {
-         /* write the IDAT and reset the zlib output buffer */
+         /* Write the IDAT and reset the zlib output buffer */
          png_write_IDAT(png_ptr, png_ptr->zbuf,
                         png_ptr->zbuf_size);
          png_ptr->zstream.next_out = png_ptr->zbuf;
@@ -968,7 +1024,7 @@ png_write_flush(png_structp png_ptr)
    /* If there is any data left to be output, write it into a new IDAT */
    if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
    {
-      /* write the IDAT and reset the zlib output buffer */
+      /* Write the IDAT and reset the zlib output buffer */
       png_write_IDAT(png_ptr, png_ptr->zbuf,
                      png_ptr->zbuf_size - png_ptr->zstream.avail_out);
       png_ptr->zstream.next_out = png_ptr->zbuf;
@@ -979,7 +1035,7 @@ png_write_flush(png_structp png_ptr)
 }
 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
 
-/* free all memory used by the write */
+/* Free all memory used by the write */
 void PNGAPI
 png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
 {
@@ -990,7 +1046,8 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
    png_voidp mem_ptr = NULL;
 #endif
 
-   png_debug(1, "in png_destroy_write_struct\n");
+   png_debug(1, "in png_destroy_write_struct");
+
    if (png_ptr_ptr != NULL)
    {
       png_ptr = *png_ptr_ptr;
@@ -1000,21 +1057,32 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
 #endif
    }
 
+#ifdef PNG_USER_MEM_SUPPORTED
+   if (png_ptr != NULL)
+   {
+      free_fn = png_ptr->free_fn;
+      mem_ptr = png_ptr->mem_ptr;
+   }
+#endif
+
    if (info_ptr_ptr != NULL)
       info_ptr = *info_ptr_ptr;
 
    if (info_ptr != NULL)
    {
-      png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-      if (png_ptr->num_chunk_list)
+      if (png_ptr != NULL)
       {
-         png_free(png_ptr, png_ptr->chunk_list);
-         png_ptr->chunk_list=NULL;
-         png_ptr->num_chunk_list=0;
-      }
+        png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+        if (png_ptr->num_chunk_list)
+        {
+           png_free(png_ptr, png_ptr->chunk_list);
+           png_ptr->chunk_list = NULL;
+           png_ptr->num_chunk_list = 0;
+        }
 #endif
+      }
 
 #ifdef PNG_USER_MEM_SUPPORTED
       png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
@@ -1044,7 +1112,7 @@ void /* PRIVATE */
 png_write_destroy(png_structp png_ptr)
 {
 #ifdef PNG_SETJMP_SUPPORTED
-   jmp_buf tmp_jmp; /* save jump buffer */
+   jmp_buf tmp_jmp; /* Save jump buffer */
 #endif
    png_error_ptr error_fn;
    png_error_ptr warning_fn;
@@ -1053,24 +1121,27 @@ png_write_destroy(png_structp png_ptr)
    png_free_ptr free_fn;
 #endif
 
-   png_debug(1, "in png_write_destroy\n");
-   /* free any memory zlib uses */
+   png_debug(1, "in png_write_destroy");
+
+   /* Free any memory zlib uses */
    deflateEnd(&png_ptr->zstream);
 
-   /* free our memory.  png_free checks NULL for us. */
+   /* Free our memory.  png_free checks NULL for us. */
    png_free(png_ptr, png_ptr->zbuf);
    png_free(png_ptr, png_ptr->row_buf);
+#ifdef PNG_WRITE_FILTER_SUPPORTED
    png_free(png_ptr, png_ptr->prev_row);
    png_free(png_ptr, png_ptr->sub_row);
    png_free(png_ptr, png_ptr->up_row);
    png_free(png_ptr, png_ptr->avg_row);
    png_free(png_ptr, png_ptr->paeth_row);
+#endif
 
-#if defined(PNG_TIME_RFC1123_SUPPORTED)
+#ifdef PNG_TIME_RFC1123_SUPPORTED
    png_free(png_ptr, png_ptr->time_buffer);
 #endif
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
    png_free(png_ptr, png_ptr->prev_filters);
    png_free(png_ptr, png_ptr->filter_weights);
    png_free(png_ptr, png_ptr->inv_filter_weights);
@@ -1079,8 +1150,8 @@ png_write_destroy(png_structp png_ptr)
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
-   /* reset structure */
-   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
+   /* Reset structure */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
 #endif
 
    error_fn = png_ptr->error_fn;
@@ -1090,7 +1161,7 @@ png_write_destroy(png_structp png_ptr)
    free_fn = png_ptr->free_fn;
 #endif
 
-   png_memset(png_ptr, 0, png_sizeof (png_struct));
+   png_memset(png_ptr, 0, png_sizeof(png_struct));
 
    png_ptr->error_fn = error_fn;
    png_ptr->warning_fn = warning_fn;
@@ -1100,7 +1171,7 @@ png_write_destroy(png_structp png_ptr)
 #endif
 
 #ifdef PNG_SETJMP_SUPPORTED
-   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
 #endif
 }
 
@@ -1108,11 +1179,12 @@ png_write_destroy(png_structp png_ptr)
 void PNGAPI
 png_set_filter(png_structp png_ptr, int method, int filters)
 {
-   png_debug(1, "in png_set_filter\n");
+   png_debug(1, "in png_set_filter");
+
    if (png_ptr == NULL)
       return;
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
       (method == PNG_INTRAPIXEL_DIFFERENCING))
          method = PNG_FILTER_TYPE_BASE;
 #endif
@@ -1120,26 +1192,26 @@ png_set_filter(png_structp png_ptr, int method, int filters)
    {
       switch (filters & (PNG_ALL_FILTERS | 0x07))
       {
-#ifndef PNG_NO_WRITE_FILTER
+#ifdef PNG_WRITE_FILTER_SUPPORTED
          case 5:
          case 6:
          case 7: png_warning(png_ptr, "Unknown row filter for method 0");
-#endif /* PNG_NO_WRITE_FILTER */
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
          case PNG_FILTER_VALUE_NONE:
-              png_ptr->do_filter=PNG_FILTER_NONE; break;
-#ifndef PNG_NO_WRITE_FILTER
+              png_ptr->do_filter = PNG_FILTER_NONE; break;
+#ifdef PNG_WRITE_FILTER_SUPPORTED
          case PNG_FILTER_VALUE_SUB:
-              png_ptr->do_filter=PNG_FILTER_SUB; break;
+              png_ptr->do_filter = PNG_FILTER_SUB; break;
          case PNG_FILTER_VALUE_UP:
-              png_ptr->do_filter=PNG_FILTER_UP; break;
+              png_ptr->do_filter = PNG_FILTER_UP; break;
          case PNG_FILTER_VALUE_AVG:
-              png_ptr->do_filter=PNG_FILTER_AVG; break;
+              png_ptr->do_filter = PNG_FILTER_AVG; break;
          case PNG_FILTER_VALUE_PAETH:
-              png_ptr->do_filter=PNG_FILTER_PAETH; break;
+              png_ptr->do_filter = PNG_FILTER_PAETH; break;
          default: png_ptr->do_filter = (png_byte)filters; break;
 #else
          default: png_warning(png_ptr, "Unknown row filter for method 0");
-#endif /* PNG_NO_WRITE_FILTER */
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
       }
 
       /* If we have allocated the row_buf, this means we have already started
@@ -1153,7 +1225,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
        */
       if (png_ptr->row_buf != NULL)
       {
-#ifndef PNG_NO_WRITE_FILTER
+#ifdef PNG_WRITE_FILTER_SUPPORTED
          if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
          {
             png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
@@ -1208,7 +1280,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
          }
 
          if (png_ptr->do_filter == PNG_NO_FILTERS)
-#endif /* PNG_NO_WRITE_FILTER */
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
             png_ptr->do_filter = PNG_FILTER_NONE;
       }
    }
@@ -1223,7 +1295,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
  * filtered data going to zlib more consistent, hopefully resulting in
  * better compression.
  */
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      /* GRR 970116 */
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED      /* GRR 970116 */
 void PNGAPI
 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
    int num_weights, png_doublep filter_weights,
@@ -1231,7 +1303,8 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
 {
    int i;
 
-   png_debug(1, "in png_set_filter_heuristics\n");
+   png_debug(1, "in png_set_filter_heuristics");
+
    if (png_ptr == NULL)
       return;
    if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
@@ -1345,7 +1418,8 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
 void PNGAPI
 png_set_compression_level(png_structp png_ptr, int level)
 {
-   png_debug(1, "in png_set_compression_level\n");
+   png_debug(1, "in png_set_compression_level");
+
    if (png_ptr == NULL)
       return;
    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
@@ -1355,7 +1429,8 @@ png_set_compression_level(png_structp png_ptr, int level)
 void PNGAPI
 png_set_compression_mem_level(png_structp png_ptr, int mem_level)
 {
-   png_debug(1, "in png_set_compression_mem_level\n");
+   png_debug(1, "in png_set_compression_mem_level");
+
    if (png_ptr == NULL)
       return;
    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
@@ -1365,7 +1440,8 @@ png_set_compression_mem_level(png_structp png_ptr, int mem_level)
 void PNGAPI
 png_set_compression_strategy(png_structp png_ptr, int strategy)
 {
-   png_debug(1, "in png_set_compression_strategy\n");
+   png_debug(1, "in png_set_compression_strategy");
+
    if (png_ptr == NULL)
       return;
    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
@@ -1382,11 +1458,11 @@ png_set_compression_window_bits(png_structp png_ptr, int window_bits)
    else if (window_bits < 8)
       png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
 #ifndef WBITS_8_OK
-   /* avoid libpng bug with 256-byte windows */
+   /* Avoid libpng bug with 256-byte windows */
    if (window_bits == 8)
      {
        png_warning(png_ptr, "Compression window is being reset to 512");
-       window_bits=9;
+       window_bits = 9;
      }
 #endif
    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
@@ -1396,7 +1472,8 @@ png_set_compression_window_bits(png_structp png_ptr, int window_bits)
 void PNGAPI
 png_set_compression_method(png_structp png_ptr, int method)
 {
-   png_debug(1, "in png_set_compression_method\n");
+   png_debug(1, "in png_set_compression_method");
+
    if (png_ptr == NULL)
       return;
    if (method != 8)
@@ -1413,12 +1490,13 @@ png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
    png_ptr->write_row_fn = write_row_fn;
 }
 
-#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
 void PNGAPI
 png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
    write_user_transform_fn)
 {
-   png_debug(1, "in png_set_write_user_transform_fn\n");
+   png_debug(1, "in png_set_write_user_transform_fn");
+
    if (png_ptr == NULL)
       return;
    png_ptr->transformations |= PNG_USER_TRANSFORM;
@@ -1427,87 +1505,88 @@ png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
 #endif
 
 
-#if defined(PNG_INFO_IMAGE_SUPPORTED)
+#ifdef PNG_INFO_IMAGE_SUPPORTED
 void PNGAPI
 png_write_png(png_structp png_ptr, png_infop info_ptr,
               int transforms, voidp params)
 {
    if (png_ptr == NULL || info_ptr == NULL)
       return;
-#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
-   /* invert the alpha channel from opacity to transparency */
-   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
-       png_set_invert_alpha(png_ptr);
-#endif
 
    /* Write the file header information. */
    png_write_info(png_ptr, info_ptr);
 
    /* ------ these transformations don't touch the info structure ------- */
 
-#if defined(PNG_WRITE_INVERT_SUPPORTED)
-   /* invert monochrome pixels */
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+   /* Invert monochrome pixels */
    if (transforms & PNG_TRANSFORM_INVERT_MONO)
-       png_set_invert_mono(png_ptr);
+      png_set_invert_mono(png_ptr);
 #endif
 
-#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
    /* Shift the pixels up to a legal bit depth and fill in
     * as appropriate to correctly scale the image.
     */
    if ((transforms & PNG_TRANSFORM_SHIFT)
                && (info_ptr->valid & PNG_INFO_sBIT))
-       png_set_shift(png_ptr, &info_ptr->sig_bit);
+      png_set_shift(png_ptr, &info_ptr->sig_bit);
 #endif
 
-#if defined(PNG_WRITE_PACK_SUPPORTED)
-   /* pack pixels into bytes */
+#ifdef PNG_WRITE_PACK_SUPPORTED
+   /* Pack pixels into bytes */
    if (transforms & PNG_TRANSFORM_PACKING)
        png_set_packing(png_ptr);
 #endif
 
-#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
-   /* swap location of alpha bytes from ARGB to RGBA */
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+   /* Swap location of alpha bytes from ARGB to RGBA */
    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
-       png_set_swap_alpha(png_ptr);
+      png_set_swap_alpha(png_ptr);
 #endif
 
-#if defined(PNG_WRITE_FILLER_SUPPORTED)
-   /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
-    * RGB (4 channels -> 3 channels). The second parameter is not used.
-    */
-   if (transforms & PNG_TRANSFORM_STRIP_FILLER)
-       png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#ifdef PNG_WRITE_FILLER_SUPPORTED
+   /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */
+   if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
+      png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+   else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
+      png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
 #endif
 
-#if defined(PNG_WRITE_BGR_SUPPORTED)
-   /* flip BGR pixels to RGB */
+#ifdef PNG_WRITE_BGR_SUPPORTED
+   /* Flip BGR pixels to RGB */
    if (transforms & PNG_TRANSFORM_BGR)
-       png_set_bgr(png_ptr);
+      png_set_bgr(png_ptr);
 #endif
 
-#if defined(PNG_WRITE_SWAP_SUPPORTED)
-   /* swap bytes of 16-bit files to most significant byte first */
+#ifdef PNG_WRITE_SWAP_SUPPORTED
+   /* Swap bytes of 16-bit files to most significant byte first */
    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
-       png_set_swap(png_ptr);
+      png_set_swap(png_ptr);
 #endif
 
-#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-   /* swap bits of 1, 2, 4 bit packed pixel formats */
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+   /* Swap bits of 1, 2, 4 bit packed pixel formats */
    if (transforms & PNG_TRANSFORM_PACKSWAP)
-       png_set_packswap(png_ptr);
+      png_set_packswap(png_ptr);
+#endif
+
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+   /* Invert the alpha channel from opacity to transparency */
+   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+      png_set_invert_alpha(png_ptr);
 #endif
 
    /* ----------------------- end of transformations ------------------- */
 
-   /* write the bits */
+   /* Write the bits */
    if (info_ptr->valid & PNG_INFO_IDAT)
        png_write_image(png_ptr, info_ptr->row_pointers);
 
    /* It is REQUIRED to call this to finish writing the rest of the file */
    png_write_end(png_ptr, info_ptr);
 
-   transforms = transforms; /* quiet compiler warnings */
+   transforms = transforms; /* Quiet compiler warnings */
    params = params;
 }
 #endif
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngwtran.c b/graf2d/asimage/src/libAfterImage/libpng/pngwtran.c
index 0372fe6..0ce9b9b 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngwtran.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngwtran.c
@@ -1,14 +1,18 @@
 
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
- * Last changed in libpng 1.2.9 April 14, 2006
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2006 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
 #ifdef PNG_WRITE_SUPPORTED
 
@@ -18,15 +22,16 @@
 void /* PRIVATE */
 png_do_write_transformations(png_structp png_ptr)
 {
-   png_debug(1, "in png_do_write_transformations\n");
+   png_debug(1, "in png_do_write_transformations");
 
    if (png_ptr == NULL)
       return;
 
-#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
    if (png_ptr->transformations & PNG_USER_TRANSFORM)
-      if(png_ptr->write_user_transform_fn != NULL)
-        (*(png_ptr->write_user_transform_fn)) /* user write transform function */
+      if (png_ptr->write_user_transform_fn != NULL)
+        (*(png_ptr->write_user_transform_fn)) /* User write transform
+                                                 function */
           (png_ptr,                    /* png_ptr */
            &(png_ptr->row_info),       /* row_info:     */
              /*  png_uint_32 width;          width of row */
@@ -37,48 +42,48 @@ png_do_write_transformations(png_structp png_ptr)
              /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
            png_ptr->row_buf + 1);      /* start of pixel data for row */
 #endif
-#if defined(PNG_WRITE_FILLER_SUPPORTED)
+#ifdef PNG_WRITE_FILLER_SUPPORTED
    if (png_ptr->transformations & PNG_FILLER)
       png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
          png_ptr->flags);
 #endif
-#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
    if (png_ptr->transformations & PNG_PACKSWAP)
       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
-#if defined(PNG_WRITE_PACK_SUPPORTED)
+#ifdef PNG_WRITE_PACK_SUPPORTED
    if (png_ptr->transformations & PNG_PACK)
       png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->bit_depth);
 #endif
-#if defined(PNG_WRITE_SWAP_SUPPORTED)
+#ifdef PNG_WRITE_SWAP_SUPPORTED
    if (png_ptr->transformations & PNG_SWAP_BYTES)
       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
-#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
    if (png_ptr->transformations & PNG_SHIFT)
       png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
          &(png_ptr->shift));
 #endif
-#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
    if (png_ptr->transformations & PNG_SWAP_ALPHA)
       png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
-#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
    if (png_ptr->transformations & PNG_INVERT_ALPHA)
       png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
-#if defined(PNG_WRITE_BGR_SUPPORTED)
+#ifdef PNG_WRITE_BGR_SUPPORTED
    if (png_ptr->transformations & PNG_BGR)
       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
-#if defined(PNG_WRITE_INVERT_SUPPORTED)
+#ifdef PNG_WRITE_INVERT_SUPPORTED
    if (png_ptr->transformations & PNG_INVERT_MONO)
       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
 #endif
 }
 
-#if defined(PNG_WRITE_PACK_SUPPORTED)
+#ifdef PNG_WRITE_PACK_SUPPORTED
 /* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
  * row_info bit depth should be 8 (one pixel per byte).  The channels
  * should be 1 (this only happens on grayscale and paletted images).
@@ -86,9 +91,10 @@ png_do_write_transformations(png_structp png_ptr)
 void /* PRIVATE */
 png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
 {
-   png_debug(1, "in png_do_pack\n");
+   png_debug(1, "in png_do_pack");
+
    if (row_info->bit_depth == 8 &&
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
       row_info->channels == 1)
@@ -201,7 +207,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
 }
 #endif
 
-#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
 /* Shift pixel values to take advantage of whole range.  Pass the
  * true number of bits in bit_depth.  The row should be packed
  * according to row_info->bit_depth.  Thus, if you had a row of
@@ -212,8 +218,9 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
 void /* PRIVATE */
 png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
 {
-   png_debug(1, "in png_do_shift\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_shift");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL &&
 #else
    if (
@@ -248,7 +255,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
          channels++;
       }
 
-      /* with low row depths, could only be grayscale, so one channel */
+      /* With low row depths, could only be grayscale, so one channel */
       if (row_info->bit_depth < 8)
       {
          png_bytep bp = row;
@@ -332,12 +339,13 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
 }
 #endif
 
-#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
 void /* PRIVATE */
 png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_write_swap_alpha\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_write_swap_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL)
 #endif
    {
@@ -420,12 +428,13 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
 }
 #endif
 
-#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
 void /* PRIVATE */
 png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_write_invert_alpha\n");
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_write_invert_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL)
 #endif
    {
@@ -439,7 +448,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
             png_uint_32 row_width = row_info->width;
             for (i = 0, sp = dp = row; i < row_width; i++)
             {
-               /* does nothing
+               /* Does nothing
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
@@ -457,7 +466,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
 
             for (i = 0, sp = dp = row; i < row_width; i++)
             {
-               /* does nothing
+               /* Does nothing
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
@@ -495,7 +504,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
 
             for (i = 0, sp = dp = row; i < row_width; i++)
             {
-               /* does nothing
+               /* Does nothing
                *(dp++) = *(sp++);
                *(dp++) = *(sp++);
                */
@@ -509,14 +518,15 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
 }
 #endif
 
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-/* undoes intrapixel differencing  */
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Undoes intrapixel differencing  */
 void /* PRIVATE */
 png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
 {
-   png_debug(1, "in png_do_write_intrapixel\n");
+   png_debug(1, "in png_do_write_intrapixel");
+
    if (
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+#ifdef PNG_USELESS_TESTS_SUPPORTED
        row != NULL && row_info != NULL &&
 #endif
        (row_info->color_type & PNG_COLOR_MASK_COLOR))
@@ -558,8 +568,8 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
             png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
             png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
             png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
-            png_uint_32 red  = (png_uint_32)((s0-s1) & 0xffffL);
-            png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL);
+            png_uint_32 red  = (png_uint_32)((s0 - s1) & 0xffffL);
+            png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
             *(rp  ) = (png_byte)((red >> 8) & 0xff);
             *(rp+1) = (png_byte)(red & 0xff);
             *(rp+4) = (png_byte)((blue >> 8) & 0xff);
diff --git a/graf2d/asimage/src/libAfterImage/libpng/pngwutil.c b/graf2d/asimage/src/libAfterImage/libpng/pngwutil.c
index fef38ae..c75f53e 100644
--- a/graf2d/asimage/src/libAfterImage/libpng/pngwutil.c
+++ b/graf2d/asimage/src/libAfterImage/libpng/pngwutil.c
@@ -1,14 +1,18 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * Last changed in libpng 1.2.20 Septhember 3, 2007
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2007 Glenn Randers-Pehrson
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
  */
 
 #define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
 #include "png.h"
 #ifdef PNG_WRITE_SUPPORTED
 
@@ -49,6 +53,24 @@ png_save_uint_16(png_bytep buf, unsigned int i)
    buf[1] = (png_byte)(i & 0xff);
 }
 
+/* Simple function to write the signature.  If we have already written
+ * the magic bytes of the signature, or more likely, the PNG stream is
+ * being embedded into another stream and doesn't need its own signature,
+ * we should call png_set_sig_bytes() to tell libpng how many of the
+ * bytes have already been written.
+ */
+void /* PRIVATE */
+png_write_sig(png_structp png_ptr)
+{
+   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+
+   /* Write the rest of the 8 byte signature */
+   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
+      (png_size_t)(8 - png_ptr->sig_bytes));
+   if (png_ptr->sig_bytes < 3)
+      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+}
+
 /* Write a PNG chunk all at once.  The type is an array of ASCII characters
  * representing the chunk name.  The array must be at least 4 bytes in
  * length, and does not need to be null terminated.  To be safe, pass the
@@ -62,9 +84,10 @@ void PNGAPI
 png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
    png_bytep data, png_size_t length)
 {
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL)
+      return;
    png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
-   png_write_chunk_data(png_ptr, data, length);
+   png_write_chunk_data(png_ptr, data, (png_size_t)length);
    png_write_chunk_end(png_ptr);
 }
 
@@ -76,17 +99,22 @@ void PNGAPI
 png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
    png_uint_32 length)
 {
-   png_byte buf[4];
-   png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length);
-   if(png_ptr == NULL) return;
+   png_byte buf[8];
 
-   /* write the length */
-   png_save_uint_32(buf, length);
-   png_write_data(png_ptr, buf, (png_size_t)4);
+   png_debug2(0, "Writing %s chunk, length = %lu", chunk_name,
+      (unsigned long)length);
+
+   if (png_ptr == NULL)
+      return;
 
-   /* write the chunk name */
-   png_write_data(png_ptr, chunk_name, (png_size_t)4);
-   /* reset the crc and run it over the chunk name */
+
+   /* Write the length and the chunk name */
+   png_save_uint_32(buf, length);
+   png_memcpy(buf + 4, chunk_name, 4);
+   png_write_data(png_ptr, buf, (png_size_t)8);
+   /* Put the chunk name into png_ptr->chunk_name */
+   png_memcpy(png_ptr->chunk_name, chunk_name, 4);
+   /* Reset the crc and run it over the chunk name */
    png_reset_crc(png_ptr);
    png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
 }
@@ -99,12 +127,16 @@ png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
 void PNGAPI
 png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
 {
-   /* write the data, and run the CRC over it */
-   if(png_ptr == NULL) return;
+   /* Write the data, and run the CRC over it */
+   if (png_ptr == NULL)
+      return;
    if (data != NULL && length > 0)
    {
-      png_calculate_crc(png_ptr, data, length);
       png_write_data(png_ptr, data, length);
+      /* Update the CRC after writing the data,
+       * in case that the user I/O routine alters it.
+       */
+      png_calculate_crc(png_ptr, data, length);
    }
 }
 
@@ -114,34 +146,16 @@ png_write_chunk_end(png_structp png_ptr)
 {
    png_byte buf[4];
 
-   if(png_ptr == NULL) return;
+   if (png_ptr == NULL) return;
 
-   /* write the crc */
+   /* Write the crc in a single operation */
    png_save_uint_32(buf, png_ptr->crc);
 
    png_write_data(png_ptr, buf, (png_size_t)4);
 }
 
-/* Simple function to write the signature.  If we have already written
- * the magic bytes of the signature, or more likely, the PNG stream is
- * being embedded into another stream and doesn't need its own signature,
- * we should call png_set_sig_bytes() to tell libpng how many of the
- * bytes have already been written.
- */
-void /* PRIVATE */
-png_write_sig(png_structp png_ptr)
-{
-   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
-   /* write the rest of the 8 byte signature */
-   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
-      (png_size_t)8 - png_ptr->sig_bytes);
-   if(png_ptr->sig_bytes < 3)
-      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
-}
-
 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
-/*
- * This pair of functions encapsulates the operation of (a) compressing a
+/* This pair of functions encapsulates the operation of (a) compressing a
  * text string, and (b) issuing it later as a series of chunk data writes.
  * The compression_state structure is shared context for these functions
  * set up by the caller in order to make the whole mess thread-safe.
@@ -149,14 +163,14 @@ png_write_sig(png_structp png_ptr)
 
 typedef struct
 {
-    char *input;   /* the uncompressed input data */
-    int input_len;   /* its length */
-    int num_output_ptr; /* number of output pointers used */
-    int max_output_ptr; /* size of output_ptr */
-    png_charpp output_ptr; /* array of pointers to output */
+   char *input;   /* The uncompressed input data */
+   int input_len;   /* Its length */
+   int num_output_ptr; /* Number of output pointers used */
+   int max_output_ptr; /* Size of output_ptr */
+   png_charpp output_ptr; /* Array of pointers to output */
 } compression_state;
 
-/* compress given text into storage in the png_ptr structure */
+/* Compress given text into storage in the png_ptr structure */
 static int /* PRIVATE */
 png_text_compress(png_structp png_ptr,
         png_charp text, png_size_t text_len, int compression,
@@ -170,7 +184,7 @@ png_text_compress(png_structp png_ptr,
    comp->input = NULL;
    comp->input_len = 0;
 
-   /* we may just want to pass the text right through */
+   /* We may just want to pass the text right through */
    if (compression == PNG_TEXT_COMPRESSION_NONE)
    {
        comp->input = text;
@@ -180,7 +194,7 @@ png_text_compress(png_structp png_ptr,
 
    if (compression >= PNG_TEXT_COMPRESSION_LAST)
    {
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
       char msg[50];
       png_snprintf(msg, 50, "Unknown compression type %d", compression);
       png_warning(png_ptr, msg);
@@ -204,29 +218,29 @@ png_text_compress(png_structp png_ptr,
     * wouldn't cause a failure, just a slowdown due to swapping).
     */
 
-   /* set up the compression buffers */
+   /* Set up the compression buffers */
    png_ptr->zstream.avail_in = (uInt)text_len;
    png_ptr->zstream.next_in = (Bytef *)text;
    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
 
-   /* this is the same compression loop as in png_write_row() */
+   /* This is the same compression loop as in png_write_row() */
    do
    {
-      /* compress the data */
+      /* Compress the data */
       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
       if (ret != Z_OK)
       {
-         /* error */
+         /* Error */
          if (png_ptr->zstream.msg != NULL)
             png_error(png_ptr, png_ptr->zstream.msg);
          else
             png_error(png_ptr, "zlib error");
       }
-      /* check to see if we need more room */
+      /* Check to see if we need more room */
       if (!(png_ptr->zstream.avail_out))
       {
-         /* make sure the output array has room */
+         /* Make sure the output array has room */
          if (comp->num_output_ptr >= comp->max_output_ptr)
          {
             int old_max;
@@ -239,20 +253,21 @@ png_text_compress(png_structp png_ptr,
 
                old_ptr = comp->output_ptr;
                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
-                  (png_uint_32)(comp->max_output_ptr *
-                  png_sizeof (png_charpp)));
+                  (png_uint_32)
+                  (comp->max_output_ptr * png_sizeof(png_charpp)));
                png_memcpy(comp->output_ptr, old_ptr, old_max
-                  * png_sizeof (png_charp));
+                  * png_sizeof(png_charp));
                png_free(png_ptr, old_ptr);
             }
             else
                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
-                  (png_uint_32)(comp->max_output_ptr *
-                  png_sizeof (png_charp)));
+                  (png_uint_32)
+                  (comp->max_output_ptr * png_sizeof(png_charp)));
          }
 
-         /* save the data */
-         comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr,
+         /* Save the data */
+         comp->output_ptr[comp->num_output_ptr] =
+            (png_charp)png_malloc(png_ptr,
             (png_uint_32)png_ptr->zbuf_size);
          png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
             png_ptr->zbuf_size);
@@ -262,21 +277,21 @@ png_text_compress(png_structp png_ptr,
          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
          png_ptr->zstream.next_out = png_ptr->zbuf;
       }
-   /* continue until we don't have any more to compress */
+   /* Continue until we don't have any more to compress */
    } while (png_ptr->zstream.avail_in);
 
-   /* finish the compression */
+   /* Finish the compression */
    do
    {
-      /* tell zlib we are finished */
+      /* Tell zlib we are finished */
       ret = deflate(&png_ptr->zstream, Z_FINISH);
 
       if (ret == Z_OK)
       {
-         /* check to see if we need more room */
+         /* Check to see if we need more room */
          if (!(png_ptr->zstream.avail_out))
          {
-            /* check to make sure our output array has room */
+            /* Check to make sure our output array has room */
             if (comp->num_output_ptr >= comp->max_output_ptr)
             {
                int old_max;
@@ -291,20 +306,21 @@ png_text_compress(png_structp png_ptr,
                   /* This could be optimized to realloc() */
                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
                      (png_uint_32)(comp->max_output_ptr *
-                     png_sizeof (png_charpp)));
+                     png_sizeof(png_charp)));
                   png_memcpy(comp->output_ptr, old_ptr,
-                     old_max * png_sizeof (png_charp));
+                     old_max * png_sizeof(png_charp));
                   png_free(png_ptr, old_ptr);
                }
                else
                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
                      (png_uint_32)(comp->max_output_ptr *
-                     png_sizeof (png_charp)));
+                     png_sizeof(png_charp)));
             }
 
-            /* save off the data */
+            /* Save the data */
             comp->output_ptr[comp->num_output_ptr] =
-               (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size);
+               (png_charp)png_malloc(png_ptr,
+               (png_uint_32)png_ptr->zbuf_size);
             png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
                png_ptr->zbuf_size);
             comp->num_output_ptr++;
@@ -316,7 +332,7 @@ png_text_compress(png_structp png_ptr,
       }
       else if (ret != Z_STREAM_END)
       {
-         /* we got an error */
+         /* We got an error */
          if (png_ptr->zstream.msg != NULL)
             png_error(png_ptr, png_ptr->zstream.msg);
          else
@@ -324,7 +340,7 @@ png_text_compress(png_structp png_ptr,
       }
    } while (ret != Z_STREAM_END);
 
-   /* text length is number of buffers plus last buffer */
+   /* Text length is number of buffers plus last buffer */
    text_len = png_ptr->zbuf_size * comp->num_output_ptr;
    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
       text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
@@ -332,37 +348,37 @@ png_text_compress(png_structp png_ptr,
    return((int)text_len);
 }
 
-/* ship the compressed text out via chunk writes */
+/* Ship the compressed text out via chunk writes */
 static void /* PRIVATE */
 png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
 {
    int i;
 
-   /* handle the no-compression case */
+   /* Handle the no-compression case */
    if (comp->input)
    {
-       png_write_chunk_data(png_ptr, (png_bytep)comp->input,
+      png_write_chunk_data(png_ptr, (png_bytep)comp->input,
                             (png_size_t)comp->input_len);
-       return;
+      return;
    }
 
-   /* write saved output buffers, if any */
+   /* Write saved output buffers, if any */
    for (i = 0; i < comp->num_output_ptr; i++)
    {
-      png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i],
-         png_ptr->zbuf_size);
+      png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i],
+         (png_size_t)png_ptr->zbuf_size);
       png_free(png_ptr, comp->output_ptr[i]);
-      comp->output_ptr[i]=NULL;
+       comp->output_ptr[i]=NULL;
    }
    if (comp->max_output_ptr != 0)
       png_free(png_ptr, comp->output_ptr);
-      comp->output_ptr=NULL;
-   /* write anything left in zbuf */
+       comp->output_ptr=NULL;
+   /* Write anything left in zbuf */
    if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
       png_write_chunk_data(png_ptr, png_ptr->zbuf,
-         png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+         (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
 
-   /* reset zlib for another zTXt/iTXt or image data */
+   /* Reset zlib for another zTXt/iTXt or image data */
    deflateReset(&png_ptr->zstream);
    png_ptr->zstream.data_type = Z_BINARY;
 }
@@ -380,9 +396,12 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_IHDR;
 #endif
-   png_byte buf[13]; /* buffer to store the IHDR info */
+   int ret;
+
+   png_byte buf[13]; /* Buffer to store the IHDR info */
+
+   png_debug(1, "in png_write_IHDR");
 
-   png_debug(1, "in png_write_IHDR\n");
    /* Check that we have valid input data from the application info */
    switch (color_type)
    {
@@ -394,7 +413,8 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
             case 4:
             case 8:
             case 16: png_ptr->channels = 1; break;
-            default: png_error(png_ptr,"Invalid bit depth for grayscale image");
+            default: png_error(png_ptr,
+                         "Invalid bit depth for grayscale image");
          }
          break;
       case PNG_COLOR_TYPE_RGB:
@@ -442,7 +462,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
     * 5. The color_type is RGB or RGBA
     */
    if (
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
       ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
       (color_type == PNG_COLOR_TYPE_RGB ||
@@ -466,11 +486,11 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
    interlace_type=PNG_INTERLACE_NONE;
 #endif
 
-   /* save off the relevent information */
+   /* Save the relevent information */
    png_ptr->bit_depth = (png_byte)bit_depth;
    png_ptr->color_type = (png_byte)color_type;
    png_ptr->interlaced = (png_byte)interlace_type;
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
    png_ptr->filter_type = (png_byte)filter_type;
 #endif
    png_ptr->compression_type = (png_byte)compression_type;
@@ -479,12 +499,12 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
 
    png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
-   /* set the usr info, so any transformations can modify it */
+   /* Set the usr info, so any transformations can modify it */
    png_ptr->usr_width = png_ptr->width;
    png_ptr->usr_bit_depth = png_ptr->bit_depth;
    png_ptr->usr_channels = png_ptr->channels;
 
-   /* pack the header information into the buffer */
+   /* Pack the header information into the buffer */
    png_save_uint_32(buf, width);
    png_save_uint_32(buf + 4, height);
    buf[8] = (png_byte)bit_depth;
@@ -493,10 +513,10 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
    buf[11] = (png_byte)filter_type;
    buf[12] = (png_byte)interlace_type;
 
-   /* write the chunk */
-   png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
+   /* Write the chunk */
+   png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
 
-   /* initialize zlib with PNG info */
+   /* Initialize zlib with PNG info */
    png_ptr->zstream.zalloc = png_zalloc;
    png_ptr->zstream.zfree = png_zfree;
    png_ptr->zstream.opaque = (voidpf)png_ptr;
@@ -523,20 +543,29 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
       png_ptr->zlib_window_bits = 15;
    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
       png_ptr->zlib_method = 8;
-   if (deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
-      png_ptr->zlib_method, png_ptr->zlib_window_bits,
-      png_ptr->zlib_mem_level, png_ptr->zlib_strategy) != Z_OK)
-       png_error(png_ptr, "zlib failed to initialize compressor");
+   ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
+         png_ptr->zlib_method, png_ptr->zlib_window_bits,
+         png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
+   if (ret != Z_OK)
+   {
+      if (ret == Z_VERSION_ERROR) png_error(png_ptr,
+          "zlib failed to initialize compressor -- version error");
+      if (ret == Z_STREAM_ERROR) png_error(png_ptr,
+           "zlib failed to initialize compressor -- stream error");
+      if (ret == Z_MEM_ERROR) png_error(png_ptr,
+           "zlib failed to initialize compressor -- mem error");
+      png_error(png_ptr, "zlib failed to initialize compressor");
+   }
    png_ptr->zstream.next_out = png_ptr->zbuf;
    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    /* libpng is not interested in zstream.data_type */
-   /* set it to a predefined value, to avoid its evaluation inside zlib */
+   /* Set it to a predefined value, to avoid its evaluation inside zlib */
    png_ptr->zstream.data_type = Z_BINARY;
 
    png_ptr->mode = PNG_HAVE_IHDR;
 }
 
-/* write the palette.  We are careful not to trust png_color to be in the
+/* Write the palette.  We are careful not to trust png_color to be in the
  * correct order for PNG, so people can redefine it to any convenient
  * structure.
  */
@@ -550,9 +579,10 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
    png_colorp pal_ptr;
    png_byte buf[3];
 
-   png_debug(1, "in png_write_PLTE\n");
+   png_debug(1, "in png_write_PLTE");
+
    if ((
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
         !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
 #endif
         num_pal == 0) || num_pal > 256)
@@ -576,10 +606,11 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
    }
 
    png_ptr->num_palette = (png_uint_16)num_pal;
-   png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
+   png_debug1(3, "num_palette = %d", png_ptr->num_palette);
 
-   png_write_chunk_start(png_ptr, png_PLTE, num_pal * 3);
-#ifndef PNG_NO_POINTER_INDEXING
+   png_write_chunk_start(png_ptr, (png_bytep)png_PLTE,
+     (png_uint_32)(num_pal * 3));
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
    {
       buf[0] = pal_ptr->red;
@@ -588,7 +619,9 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
    }
 #else
-   /* This is a little slower but some buggy compilers need to do this instead */
+   /* This is a little slower but some buggy compilers need to do this
+    * instead
+    */
    pal_ptr=palette;
    for (i = 0; i < num_pal; i++)
    {
@@ -602,14 +635,15 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
    png_ptr->mode |= PNG_HAVE_PLTE;
 }
 
-/* write an IDAT chunk */
+/* Write an IDAT chunk */
 void /* PRIVATE */
 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_IDAT;
 #endif
-   png_debug(1, "in png_write_IDAT\n");
+
+   png_debug(1, "in png_write_IDAT");
 
    /* Optimize the CMF field in the zlib stream. */
    /* This hack of the zlib stream is compliant to the stream specification. */
@@ -619,9 +653,11 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
       unsigned int z_cmf = data[0];  /* zlib compression method and flags */
       if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
       {
-         /* Avoid memory underflows and multiplication overflows. */
-         /* The conditions below are practically always satisfied;
-            however, they still must be checked. */
+         /* Avoid memory underflows and multiplication overflows.
+          *
+          * The conditions below are practically always satisfied;
+          * however, they still must be checked.
+          */
          if (length >= 2 &&
              png_ptr->height < 16384 && png_ptr->width < 16384)
          {
@@ -650,25 +686,27 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
             "Invalid zlib compression method or flags in IDAT");
    }
 
-   png_write_chunk(png_ptr, png_IDAT, data, length);
+   png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
    png_ptr->mode |= PNG_HAVE_IDAT;
 }
 
-/* write an IEND chunk */
+/* Write an IEND chunk */
 void /* PRIVATE */
 png_write_IEND(png_structp png_ptr)
 {
 #ifdef PNG_USE_LOCAL_ARRAYS
    PNG_IEND;
 #endif
-   png_debug(1, "in png_write_IEND\n");
-   png_write_chunk(png_ptr, png_IEND, png_bytep_NULL,
+
+   png_debug(1, "in png_write_IEND");
+
+   png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL,
      (png_size_t)0);
    png_ptr->mode |= PNG_HAVE_IEND;
 }
 
-#if defined(PNG_WRITE_gAMA_SUPPORTED)
-/* write a gAMA chunk */
+#ifdef PNG_WRITE_gAMA_SUPPORTED
+/* Write a gAMA chunk */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 void /* PRIVATE */
 png_write_gAMA(png_structp png_ptr, double file_gamma)
@@ -679,11 +717,12 @@ png_write_gAMA(png_structp png_ptr, double file_gamma)
    png_uint_32 igamma;
    png_byte buf[4];
 
-   png_debug(1, "in png_write_gAMA\n");
+   png_debug(1, "in png_write_gAMA");
+
    /* file_gamma is saved in 1/100,000ths */
    igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
    png_save_uint_32(buf, igamma);
-   png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
+   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
 }
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
@@ -695,16 +734,17 @@ png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
 #endif
    png_byte buf[4];
 
-   png_debug(1, "in png_write_gAMA\n");
+   png_debug(1, "in png_write_gAMA");
+
    /* file_gamma is saved in 1/100,000ths */
    png_save_uint_32(buf, (png_uint_32)file_gamma);
-   png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
+   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
 }
 #endif
 #endif
 
-#if defined(PNG_WRITE_sRGB_SUPPORTED)
-/* write a sRGB chunk */
+#ifdef PNG_WRITE_sRGB_SUPPORTED
+/* Write a sRGB chunk */
 void /* PRIVATE */
 png_write_sRGB(png_structp png_ptr, int srgb_intent)
 {
@@ -713,17 +753,18 @@ png_write_sRGB(png_structp png_ptr, int srgb_intent)
 #endif
    png_byte buf[1];
 
-   png_debug(1, "in png_write_sRGB\n");
-   if(srgb_intent >= PNG_sRGB_INTENT_LAST)
+   png_debug(1, "in png_write_sRGB");
+
+   if (srgb_intent >= PNG_sRGB_INTENT_LAST)
          png_warning(png_ptr,
             "Invalid sRGB rendering intent specified");
    buf[0]=(png_byte)srgb_intent;
-   png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
+   png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
 }
 #endif
 
-#if defined(PNG_WRITE_iCCP_SUPPORTED)
-/* write an iCCP chunk */
+#ifdef PNG_WRITE_iCCP_SUPPORTED
+/* Write an iCCP chunk */
 void /* PRIVATE */
 png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
    png_charp profile, int profile_len)
@@ -736,7 +777,7 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
    compression_state comp;
    int embedded_profile_len = 0;
 
-   png_debug(1, "in png_write_iCCP\n");
+   png_debug(1, "in png_write_iCCP");
 
    comp.num_output_ptr = 0;
    comp.max_output_ptr = 0;
@@ -744,12 +785,9 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
    comp.input = NULL;
    comp.input_len = 0;
 
-   if (name == NULL || (name_len = png_check_keyword(png_ptr, name,
+   if ((name_len = png_check_keyword(png_ptr, name,
       &new_name)) == 0)
-   {
-      png_warning(png_ptr, "Empty keyword in iCCP chunk");
       return;
-   }
 
    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
       png_warning(png_ptr, "Unknown compression type in iCCP chunk");
@@ -759,34 +797,44 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
 
    if (profile_len > 3)
       embedded_profile_len =
-          ((*( (png_bytep)profile  ))<<24) |
-          ((*( (png_bytep)profile+1))<<16) |
-          ((*( (png_bytep)profile+2))<< 8) |
-          ((*( (png_bytep)profile+3))    );
+          ((*( (png_bytep)profile    ))<<24) |
+          ((*( (png_bytep)profile + 1))<<16) |
+          ((*( (png_bytep)profile + 2))<< 8) |
+          ((*( (png_bytep)profile + 3))    );
+
+   if (embedded_profile_len < 0)
+   {
+      png_warning(png_ptr,
+        "Embedded profile length in iCCP chunk is negative");
+      png_free(png_ptr, new_name);
+      return;
+   }
 
    if (profile_len < embedded_profile_len)
-     {
-        png_warning(png_ptr,
-          "Embedded profile length too large in iCCP chunk");
-        return;
-     }
+   {
+      png_warning(png_ptr,
+        "Embedded profile length too large in iCCP chunk");
+      png_free(png_ptr, new_name);
+      return;
+   }
 
    if (profile_len > embedded_profile_len)
-     {
-        png_warning(png_ptr,
-          "Truncating profile to actual length in iCCP chunk");
-        profile_len = embedded_profile_len;
-     }
+   {
+      png_warning(png_ptr,
+        "Truncating profile to actual length in iCCP chunk");
+      profile_len = embedded_profile_len;
+   }
 
    if (profile_len)
-       profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len,
-          PNG_COMPRESSION_TYPE_BASE, &comp);
+      profile_len = png_text_compress(png_ptr, profile,
+        (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
 
-   /* make sure we include the NULL after the name and the compression type */
-   png_write_chunk_start(png_ptr, png_iCCP,
-          (png_uint_32)name_len+profile_len+2);
-   new_name[name_len+1]=0x00;
-   png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2);
+   /* Make sure we include the NULL after the name and the compression type */
+   png_write_chunk_start(png_ptr, (png_bytep)png_iCCP,
+          (png_uint_32)(name_len + profile_len + 2));
+   new_name[name_len + 1] = 0x00;
+   png_write_chunk_data(png_ptr, (png_bytep)new_name,
+     (png_size_t)(name_len + 2));
 
    if (profile_len)
       png_write_compressed_data_out(png_ptr, &comp);
@@ -796,8 +844,8 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
 }
 #endif
 
-#if defined(PNG_WRITE_sPLT_SUPPORTED)
-/* write a sPLT chunk */
+#ifdef PNG_WRITE_sPLT_SUPPORTED
+/* Write a sPLT chunk */
 void /* PRIVATE */
 png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
 {
@@ -810,67 +858,65 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
    int entry_size = (spalette->depth == 8 ? 6 : 10);
    int palette_size = entry_size * spalette->nentries;
    png_sPLT_entryp ep;
-#ifdef PNG_NO_POINTER_INDEXING
+#ifndef PNG_POINTER_INDEXING_SUPPORTED
    int i;
 #endif
 
-   png_debug(1, "in png_write_sPLT\n");
-   if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr,
-      spalette->name, &new_name))==0)
-   {
-      png_warning(png_ptr, "Empty keyword in sPLT chunk");
+   png_debug(1, "in png_write_sPLT");
+
+   if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
       return;
-   }
 
-   /* make sure we include the NULL after the name */
-   png_write_chunk_start(png_ptr, png_sPLT,
-          (png_uint_32)(name_len + 2 + palette_size));
-   png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1);
-   png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1);
-
-   /* loop through each palette entry, writing appropriately */
-#ifndef PNG_NO_POINTER_INDEXING
-   for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++)
-   {
-       if (spalette->depth == 8)
-       {
-           entrybuf[0] = (png_byte)ep->red;
-           entrybuf[1] = (png_byte)ep->green;
-           entrybuf[2] = (png_byte)ep->blue;
-           entrybuf[3] = (png_byte)ep->alpha;
-           png_save_uint_16(entrybuf + 4, ep->frequency);
-       }
-       else
-       {
-           png_save_uint_16(entrybuf + 0, ep->red);
-           png_save_uint_16(entrybuf + 2, ep->green);
-           png_save_uint_16(entrybuf + 4, ep->blue);
-           png_save_uint_16(entrybuf + 6, ep->alpha);
-           png_save_uint_16(entrybuf + 8, ep->frequency);
-       }
-       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+   /* Make sure we include the NULL after the name */
+   png_write_chunk_start(png_ptr, (png_bytep)png_sPLT,
+     (png_uint_32)(name_len + 2 + palette_size));
+   png_write_chunk_data(png_ptr, (png_bytep)new_name,
+     (png_size_t)(name_len + 1));
+   png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1);
+
+   /* Loop through each palette entry, writing appropriately */
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
+   for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
+   {
+      if (spalette->depth == 8)
+      {
+          entrybuf[0] = (png_byte)ep->red;
+          entrybuf[1] = (png_byte)ep->green;
+          entrybuf[2] = (png_byte)ep->blue;
+          entrybuf[3] = (png_byte)ep->alpha;
+          png_save_uint_16(entrybuf + 4, ep->frequency);
+      }
+      else
+      {
+          png_save_uint_16(entrybuf + 0, ep->red);
+          png_save_uint_16(entrybuf + 2, ep->green);
+          png_save_uint_16(entrybuf + 4, ep->blue);
+          png_save_uint_16(entrybuf + 6, ep->alpha);
+          png_save_uint_16(entrybuf + 8, ep->frequency);
+      }
+      png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
    }
 #else
    ep=spalette->entries;
    for (i=0; i>spalette->nentries; i++)
    {
-       if (spalette->depth == 8)
-       {
-           entrybuf[0] = (png_byte)ep[i].red;
-           entrybuf[1] = (png_byte)ep[i].green;
-           entrybuf[2] = (png_byte)ep[i].blue;
-           entrybuf[3] = (png_byte)ep[i].alpha;
-           png_save_uint_16(entrybuf + 4, ep[i].frequency);
-       }
-       else
-       {
-           png_save_uint_16(entrybuf + 0, ep[i].red);
-           png_save_uint_16(entrybuf + 2, ep[i].green);
-           png_save_uint_16(entrybuf + 4, ep[i].blue);
-           png_save_uint_16(entrybuf + 6, ep[i].alpha);
-           png_save_uint_16(entrybuf + 8, ep[i].frequency);
-       }
-       png_write_chunk_data(png_ptr, entrybuf, entry_size);
+      if (spalette->depth == 8)
+      {
+          entrybuf[0] = (png_byte)ep[i].red;
+          entrybuf[1] = (png_byte)ep[i].green;
+          entrybuf[2] = (png_byte)ep[i].blue;
+          entrybuf[3] = (png_byte)ep[i].alpha;
+          png_save_uint_16(entrybuf + 4, ep[i].frequency);
+      }
+      else
+      {
+          png_save_uint_16(entrybuf + 0, ep[i].red);
+          png_save_uint_16(entrybuf + 2, ep[i].green);
+          png_save_uint_16(entrybuf + 4, ep[i].blue);
+          png_save_uint_16(entrybuf + 6, ep[i].alpha);
+          png_save_uint_16(entrybuf + 8, ep[i].frequency);
+      }
+      png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
    }
 #endif
 
@@ -879,8 +925,8 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
 }
 #endif
 
-#if defined(PNG_WRITE_sBIT_SUPPORTED)
-/* write the sBIT chunk */
+#ifdef PNG_WRITE_sBIT_SUPPORTED
+/* Write the sBIT chunk */
 void /* PRIVATE */
 png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
 {
@@ -890,8 +936,9 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
    png_byte buf[4];
    png_size_t size;
 
-   png_debug(1, "in png_write_sBIT\n");
-   /* make sure we don't depend upon the order of PNG_COLOR_8 */
+   png_debug(1, "in png_write_sBIT");
+
+   /* Make sure we don't depend upon the order of PNG_COLOR_8 */
    if (color_type & PNG_COLOR_MASK_COLOR)
    {
       png_byte maxbits;
@@ -931,12 +978,12 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
       buf[size++] = sbit->alpha;
    }
 
-   png_write_chunk(png_ptr, png_sBIT, buf, size);
+   png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
 }
 #endif
 
-#if defined(PNG_WRITE_cHRM_SUPPORTED)
-/* write the cHRM chunk */
+#ifdef PNG_WRITE_cHRM_SUPPORTED
+/* Write the cHRM chunk */
 #ifdef PNG_FLOATING_POINT_SUPPORTED
 void /* PRIVATE */
 png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
@@ -947,55 +994,42 @@ png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
    PNG_cHRM;
 #endif
    png_byte buf[32];
-   png_uint_32 itemp;
 
-   png_debug(1, "in png_write_cHRM\n");
-   /* each value is saved in 1/100,000ths */
-   if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
-       white_x + white_y > 1.0)
-   {
-      png_warning(png_ptr, "Invalid cHRM white point specified");
-#if !defined(PNG_NO_CONSOLE_IO)
-      fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y);
-#endif
-      return;
-   }
-   itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
-   png_save_uint_32(buf, itemp);
-   itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
-   png_save_uint_32(buf + 4, itemp);
+   png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y,
+      int_green_x, int_green_y, int_blue_x, int_blue_y;
 
-   if (red_x < 0 ||  red_y < 0 || red_x + red_y > 1.0)
-   {
-      png_warning(png_ptr, "Invalid cHRM red point specified");
-      return;
-   }
-   itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
-   png_save_uint_32(buf + 8, itemp);
-   itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
-   png_save_uint_32(buf + 12, itemp);
+   png_debug(1, "in png_write_cHRM");
 
-   if (green_x < 0 || green_y < 0 || green_x + green_y > 1.0)
-   {
-      png_warning(png_ptr, "Invalid cHRM green point specified");
-      return;
-   }
-   itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
-   png_save_uint_32(buf + 16, itemp);
-   itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
-   png_save_uint_32(buf + 20, itemp);
+   int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5);
+   int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5);
+   int_red_x   = (png_uint_32)(red_x   * 100000.0 + 0.5);
+   int_red_y   = (png_uint_32)(red_y   * 100000.0 + 0.5);
+   int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5);
+   int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5);
+   int_blue_x  = (png_uint_32)(blue_x  * 100000.0 + 0.5);
+   int_blue_y  = (png_uint_32)(blue_y  * 100000.0 + 0.5);
 
-   if (blue_x < 0 || blue_y < 0 || blue_x + blue_y > 1.0)
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+   if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y,
+      int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y))
+#endif
    {
-      png_warning(png_ptr, "Invalid cHRM blue point specified");
-      return;
-   }
-   itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
-   png_save_uint_32(buf + 24, itemp);
-   itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
-   png_save_uint_32(buf + 28, itemp);
+      /* Each value is saved in 1/100,000ths */
+
+      png_save_uint_32(buf, int_white_x);
+      png_save_uint_32(buf + 4, int_white_y);
+
+      png_save_uint_32(buf + 8, int_red_x);
+      png_save_uint_32(buf + 12, int_red_y);
+
+      png_save_uint_32(buf + 16, int_green_x);
+      png_save_uint_32(buf + 20, int_green_y);
 
-   png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
+      png_save_uint_32(buf + 24, int_blue_x);
+      png_save_uint_32(buf + 28, int_blue_y);
+
+      png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+   }
 }
 #endif
 #ifdef PNG_FIXED_POINT_SUPPORTED
@@ -1010,50 +1044,34 @@ png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
 #endif
    png_byte buf[32];
 
-   png_debug(1, "in png_write_cHRM\n");
-   /* each value is saved in 1/100,000ths */
-   if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid fixed cHRM white point specified");
-#if !defined(PNG_NO_CONSOLE_IO)
-      fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y);
-#endif
-      return;
-   }
-   png_save_uint_32(buf, (png_uint_32)white_x);
-   png_save_uint_32(buf + 4, (png_uint_32)white_y);
+   png_debug(1, "in png_write_cHRM");
 
-   if (red_x + red_y > 100000L)
+   /* Each value is saved in 1/100,000ths */
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+   if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
+      green_x, green_y, blue_x, blue_y))
+#endif
    {
-      png_warning(png_ptr, "Invalid cHRM fixed red point specified");
-      return;
-   }
-   png_save_uint_32(buf + 8, (png_uint_32)red_x);
-   png_save_uint_32(buf + 12, (png_uint_32)red_y);
+      png_save_uint_32(buf, (png_uint_32)white_x);
+      png_save_uint_32(buf + 4, (png_uint_32)white_y);
 
-   if (green_x + green_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid fixed cHRM green point specified");
-      return;
-   }
-   png_save_uint_32(buf + 16, (png_uint_32)green_x);
-   png_save_uint_32(buf + 20, (png_uint_32)green_y);
+      png_save_uint_32(buf + 8, (png_uint_32)red_x);
+      png_save_uint_32(buf + 12, (png_uint_32)red_y);
 
-   if (blue_x + blue_y > 100000L)
-   {
-      png_warning(png_ptr, "Invalid fixed cHRM blue point specified");
-      return;
-   }
-   png_save_uint_32(buf + 24, (png_uint_32)blue_x);
-   png_save_uint_32(buf + 28, (png_uint_32)blue_y);
+      png_save_uint_32(buf + 16, (png_uint_32)green_x);
+      png_save_uint_32(buf + 20, (png_uint_32)green_y);
+
+      png_save_uint_32(buf + 24, (png_uint_32)blue_x);
+      png_save_uint_32(buf + 28, (png_uint_32)blue_y);
 
-   png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
+      png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+   }
 }
 #endif
 #endif
 
-#if defined(PNG_WRITE_tRNS_SUPPORTED)
-/* write the tRNS chunk */
+#ifdef PNG_WRITE_tRNS_SUPPORTED
+/* Write the tRNS chunk */
 void /* PRIVATE */
 png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
    int num_trans, int color_type)
@@ -1063,42 +1081,44 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
 #endif
    png_byte buf[6];
 
-   png_debug(1, "in png_write_tRNS\n");
+   png_debug(1, "in png_write_tRNS");
+
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
       if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
       {
-         png_warning(png_ptr,"Invalid number of transparent colors specified");
+         png_warning(png_ptr, "Invalid number of transparent colors specified");
          return;
       }
-      /* write the chunk out as it is */
-      png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans);
+      /* Write the chunk out as it is */
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans,
+        (png_size_t)num_trans);
    }
    else if (color_type == PNG_COLOR_TYPE_GRAY)
    {
-      /* one 16 bit value */
-      if(tran->gray >= (1 << png_ptr->bit_depth))
+      /* One 16 bit value */
+      if (tran->gray >= (1 << png_ptr->bit_depth))
       {
          png_warning(png_ptr,
            "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
          return;
       }
       png_save_uint_16(buf, tran->gray);
-      png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
    }
    else if (color_type == PNG_COLOR_TYPE_RGB)
    {
-      /* three 16 bit values */
+      /* Three 16 bit values */
       png_save_uint_16(buf, tran->red);
       png_save_uint_16(buf + 2, tran->green);
       png_save_uint_16(buf + 4, tran->blue);
-      if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
-         {
-            png_warning(png_ptr,
-              "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
-            return;
-         }
-      png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
+      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+      {
+         png_warning(png_ptr,
+           "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
+         return;
+      }
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
    }
    else
    {
@@ -1107,8 +1127,8 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
 }
 #endif
 
-#if defined(PNG_WRITE_bKGD_SUPPORTED)
-/* write the background chunk */
+#ifdef PNG_WRITE_bKGD_SUPPORTED
+/* Write the background chunk */
 void /* PRIVATE */
 png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
 {
@@ -1117,51 +1137,52 @@ png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
 #endif
    png_byte buf[6];
 
-   png_debug(1, "in png_write_bKGD\n");
+   png_debug(1, "in png_write_bKGD");
+
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
       if (
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
           (png_ptr->num_palette ||
           (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
 #endif
-         back->index > png_ptr->num_palette)
+         back->index >= png_ptr->num_palette)
       {
          png_warning(png_ptr, "Invalid background palette index");
          return;
       }
       buf[0] = back->index;
-      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
    }
    else if (color_type & PNG_COLOR_MASK_COLOR)
    {
       png_save_uint_16(buf, back->red);
       png_save_uint_16(buf + 2, back->green);
       png_save_uint_16(buf + 4, back->blue);
-      if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
-         {
-            png_warning(png_ptr,
-              "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
-            return;
-         }
-      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
+      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+      {
+         png_warning(png_ptr,
+           "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
+         return;
+      }
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
    }
    else
    {
-      if(back->gray >= (1 << png_ptr->bit_depth))
+      if (back->gray >= (1 << png_ptr->bit_depth))
       {
          png_warning(png_ptr,
            "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
          return;
       }
       png_save_uint_16(buf, back->gray);
-      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
    }
 }
 #endif
 
-#if defined(PNG_WRITE_hIST_SUPPORTED)
-/* write the histogram */
+#ifdef PNG_WRITE_hIST_SUPPORTED
+/* Write the histogram */
 void /* PRIVATE */
 png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
 {
@@ -1171,16 +1192,18 @@ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
    int i;
    png_byte buf[3];
 
-   png_debug(1, "in png_write_hIST\n");
+   png_debug(1, "in png_write_hIST");
+
    if (num_hist > (int)png_ptr->num_palette)
    {
-      png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
+      png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
          png_ptr->num_palette);
       png_warning(png_ptr, "Invalid number of histogram entries specified");
       return;
    }
 
-   png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
+   png_write_chunk_start(png_ptr, (png_bytep)png_hIST,
+     (png_uint_32)(num_hist * 2));
    for (i = 0; i < num_hist; i++)
    {
       png_save_uint_16(buf, hist[i]);
@@ -1210,7 +1233,8 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
    int kflag;
    int kwarn=0;
 
-   png_debug(1, "in png_check_keyword\n");
+   png_debug(1, "in png_check_keyword");
+
    *new_key = NULL;
 
    if (key == NULL || (key_len = png_strlen(key)) == 0)
@@ -1219,7 +1243,7 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
       return ((png_size_t)0);
    }
 
-   png_debug1(2, "Keyword to be checked is '%s'\n", key);
+   png_debug1(2, "Keyword to be checked is '%s'", key);
 
    *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
    if (*new_key == NULL)
@@ -1234,7 +1258,7 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
       if ((png_byte)*kp < 0x20 ||
          ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
       {
-#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
          char msg[40];
 
          png_snprintf(msg, 40,
@@ -1260,8 +1284,8 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
 
       while (*kp == ' ')
       {
-        *(kp--) = '\0';
-        key_len--;
+         *(kp--) = '\0';
+         key_len--;
       }
    }
 
@@ -1273,12 +1297,12 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
 
       while (*kp == ' ')
       {
-        kp++;
-        key_len--;
+         kp++;
+         key_len--;
       }
    }
 
-   png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
+   png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
 
    /* Remove multiple internal spaces. */
    for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
@@ -1300,20 +1324,20 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
       }
    }
    *dp = '\0';
-   if(kwarn)
+   if (kwarn)
       png_warning(png_ptr, "extra interior spaces removed from keyword");
 
    if (key_len == 0)
    {
       png_free(png_ptr, *new_key);
-      *new_key=NULL;
+       *new_key=NULL;
       png_warning(png_ptr, "Zero length keyword");
    }
 
    if (key_len > 79)
    {
       png_warning(png_ptr, "keyword length must be 1 - 79 characters");
-      new_key[79] = '\0';
+      (*new_key)[79] = '\0';
       key_len = 79;
    }
 
@@ -1321,8 +1345,8 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
 }
 #endif
 
-#if defined(PNG_WRITE_tEXt_SUPPORTED)
-/* write a tEXt chunk */
+#ifdef PNG_WRITE_tEXt_SUPPORTED
+/* Write a tEXt chunk */
 void /* PRIVATE */
 png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
    png_size_t text_len)
@@ -1333,37 +1357,37 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
    png_size_t key_len;
    png_charp new_key;
 
-   png_debug(1, "in png_write_tEXt\n");
-   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
-   {
-      png_warning(png_ptr, "Empty keyword in tEXt chunk");
+   png_debug(1, "in png_write_tEXt");
+
+   if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
       return;
-   }
 
    if (text == NULL || *text == '\0')
       text_len = 0;
    else
       text_len = png_strlen(text);
 
-   /* make sure we include the 0 after the key */
-   png_write_chunk_start(png_ptr, png_tEXt, (png_uint_32)key_len+text_len+1);
+   /* Make sure we include the 0 after the key */
+   png_write_chunk_start(png_ptr, (png_bytep)png_tEXt,
+      (png_uint_32)(key_len + text_len + 1));
    /*
     * We leave it to the application to meet PNG-1.0 requirements on the
     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
     */
-   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
+   png_write_chunk_data(png_ptr, (png_bytep)new_key,
+     (png_size_t)(key_len + 1));
    if (text_len)
-      png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
+      png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len);
 
    png_write_chunk_end(png_ptr);
    png_free(png_ptr, new_key);
 }
 #endif
 
-#if defined(PNG_WRITE_zTXt_SUPPORTED)
-/* write a compressed text chunk */
+#ifdef PNG_WRITE_zTXt_SUPPORTED
+/* Write a compressed text chunk */
 void /* PRIVATE */
 png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
    png_size_t text_len, int compression)
@@ -1376,7 +1400,7 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
    png_charp new_key;
    compression_state comp;
 
-   png_debug(1, "in png_write_zTXt\n");
+   png_debug(1, "in png_write_zTXt");
 
    comp.num_output_ptr = 0;
    comp.max_output_ptr = 0;
@@ -1384,9 +1408,9 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
    comp.input = NULL;
    comp.input_len = 0;
 
-   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+   if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
    {
-      png_warning(png_ptr, "Empty keyword in zTXt chunk");
+      png_free(png_ptr, new_key);
       return;
    }
 
@@ -1399,30 +1423,31 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
 
    text_len = png_strlen(text);
 
-   /* compute the compressed data; do it now for the length */
+   /* Compute the compressed data; do it now for the length */
    text_len = png_text_compress(png_ptr, text, text_len, compression,
        &comp);
 
-   /* write start of chunk */
-   png_write_chunk_start(png_ptr, png_zTXt, (png_uint_32)
-      (key_len+text_len+2));
-   /* write key */
-   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
+   /* Write start of chunk */
+   png_write_chunk_start(png_ptr, (png_bytep)png_zTXt,
+     (png_uint_32)(key_len+text_len + 2));
+   /* Write key */
+   png_write_chunk_data(png_ptr, (png_bytep)new_key,
+     (png_size_t)(key_len + 1));
    png_free(png_ptr, new_key);
 
    buf[0] = (png_byte)compression;
-   /* write compression */
+   /* Write compression */
    png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
-   /* write the compressed data */
+   /* Write the compressed data */
    png_write_compressed_data_out(png_ptr, &comp);
 
-   /* close the chunk */
+   /* Close the chunk */
    png_write_chunk_end(png_ptr);
 }
 #endif
 
-#if defined(PNG_WRITE_iTXt_SUPPORTED)
-/* write an iTXt chunk */
+#ifdef PNG_WRITE_iTXt_SUPPORTED
+/* Write an iTXt chunk */
 void /* PRIVATE */
 png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
     png_charp lang, png_charp lang_key, png_charp text)
@@ -1431,23 +1456,22 @@ png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
    PNG_iTXt;
 #endif
    png_size_t lang_len, key_len, lang_key_len, text_len;
-   png_charp new_lang, new_key;
+   png_charp new_lang;
+   png_charp new_key = NULL;
    png_byte cbuf[2];
    compression_state comp;
 
-   png_debug(1, "in png_write_iTXt\n");
+   png_debug(1, "in png_write_iTXt");
 
    comp.num_output_ptr = 0;
    comp.max_output_ptr = 0;
    comp.output_ptr = NULL;
    comp.input = NULL;
 
-   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
-   {
-      png_warning(png_ptr, "Empty keyword in iTXt chunk");
+   if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
       return;
-   }
-   if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0)
+
+   if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0)
    {
       png_warning(png_ptr, "Empty language field in iTXt chunk");
       new_lang = NULL;
@@ -1455,24 +1479,24 @@ png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
    }
 
    if (lang_key == NULL)
-     lang_key_len = 0;
+      lang_key_len = 0;
    else
-     lang_key_len = png_strlen(lang_key);
+      lang_key_len = png_strlen(lang_key);
 
    if (text == NULL)
       text_len = 0;
    else
-     text_len = png_strlen(text);
+      text_len = png_strlen(text);
 
-   /* compute the compressed data; do it now for the length */
+   /* Compute the compressed data; do it now for the length */
    text_len = png_text_compress(png_ptr, text, text_len, compression-2,
       &comp);
 
 
-   /* make sure we include the compression flag, the compression byte,
+   /* Make sure we include the compression flag, the compression byte,
     * and the NULs after the key, lang, and lang_key parts */
 
-   png_write_chunk_start(png_ptr, png_iTXt,
+   png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
           (png_uint_32)(
         5 /* comp byte, comp flag, terminators for key, lang and lang_key */
         + key_len
@@ -1480,38 +1504,39 @@ png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
         + lang_key_len
         + text_len));
 
-   /*
-    * We leave it to the application to meet PNG-1.0 requirements on the
+   /* We leave it to the application to meet PNG-1.0 requirements on the
     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
     */
-   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
+   png_write_chunk_data(png_ptr, (png_bytep)new_key,
+     (png_size_t)(key_len + 1));
 
-   /* set the compression flag */
+   /* Set the compression flag */
    if (compression == PNG_ITXT_COMPRESSION_NONE || \
        compression == PNG_TEXT_COMPRESSION_NONE)
        cbuf[0] = 0;
    else /* compression == PNG_ITXT_COMPRESSION_zTXt */
        cbuf[0] = 1;
-   /* set the compression method */
+   /* Set the compression method */
    cbuf[1] = 0;
-   png_write_chunk_data(png_ptr, cbuf, 2);
+   png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
 
    cbuf[0] = 0;
-   png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), lang_len + 1);
-   png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), lang_key_len + 1);
+   png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf),
+     (png_size_t)(lang_len + 1));
+   png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf),
+     (png_size_t)(lang_key_len + 1));
    png_write_compressed_data_out(png_ptr, &comp);
 
    png_write_chunk_end(png_ptr);
    png_free(png_ptr, new_key);
-   if (new_lang)
-     png_free(png_ptr, new_lang);
+   png_free(png_ptr, new_lang);
 }
 #endif
 
-#if defined(PNG_WRITE_oFFs_SUPPORTED)
-/* write the oFFs chunk */
+#ifdef PNG_WRITE_oFFs_SUPPORTED
+/* Write the oFFs chunk */
 void /* PRIVATE */
 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
    int unit_type)
@@ -1521,7 +1546,8 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
 #endif
    png_byte buf[9];
 
-   png_debug(1, "in png_write_oFFs\n");
+   png_debug(1, "in png_write_oFFs");
+
    if (unit_type >= PNG_OFFSET_LAST)
       png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
 
@@ -1529,11 +1555,11 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
    png_save_int_32(buf + 4, y_offset);
    buf[8] = (png_byte)unit_type;
 
-   png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
+   png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
 }
 #endif
-#if defined(PNG_WRITE_pCAL_SUPPORTED)
-/* write the pCAL chunk (described in the PNG extensions document) */
+#ifdef PNG_WRITE_pCAL_SUPPORTED
+/* Write the pCAL chunk (described in the PNG extensions document) */
 void /* PRIVATE */
 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
    png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
@@ -1547,31 +1573,34 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
    png_charp new_purpose;
    int i;
 
-   png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
+   png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
+
    if (type >= PNG_EQUATION_LAST)
       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
 
    purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
-   png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len);
+   png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
    units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
-   png_debug1(3, "pCAL units length = %d\n", (int)units_len);
+   png_debug1(3, "pCAL units length = %d", (int)units_len);
    total_len = purpose_len + units_len + 10;
 
-   params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams
-      *png_sizeof(png_uint_32)));
+   params_len = (png_uint_32p)png_malloc(png_ptr,
+      (png_uint_32)(nparams * png_sizeof(png_uint_32)));
 
    /* Find the length of each parameter, making sure we don't count the
       null terminator for the last parameter. */
    for (i = 0; i < nparams; i++)
    {
       params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
-      png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]);
+      png_debug2(3, "pCAL parameter %d length = %lu", i,
+        (unsigned long) params_len[i]);
       total_len += (png_size_t)params_len[i];
    }
 
-   png_debug1(3, "pCAL total length = %d\n", (int)total_len);
-   png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len);
-   png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len);
+   png_debug1(3, "pCAL total length = %d", (int)total_len);
+   png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len);
+   png_write_chunk_data(png_ptr, (png_bytep)new_purpose,
+     (png_size_t)purpose_len);
    png_save_int_32(buf, X0);
    png_save_int_32(buf + 4, X1);
    buf[8] = (png_byte)type;
@@ -1592,9 +1621,9 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
 }
 #endif
 
-#if defined(PNG_WRITE_sCAL_SUPPORTED)
-/* write the sCAL chunk */
-#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+#ifdef PNG_WRITE_sCAL_SUPPORTED
+/* Write the sCAL chunk */
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
 void /* PRIVATE */
 png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
 {
@@ -1604,17 +1633,18 @@ png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
    char buf[64];
    png_size_t total_len;
 
-   png_debug(1, "in png_write_sCAL\n");
+   png_debug(1, "in png_write_sCAL");
 
    buf[0] = (char)unit;
-#if defined(_WIN32_WCE)
+#ifdef _WIN32_WCE
 /* sprintf() function is not supported on WindowsCE */
    {
       wchar_t wc_buf[32];
       size_t wc_len;
       swprintf(wc_buf, TEXT("%12.12e"), width);
       wc_len = wcslen(wc_buf);
-      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL);
+      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL,
+          NULL);
       total_len = wc_len + 2;
       swprintf(wc_buf, TEXT("%12.12e"), height);
       wc_len = wcslen(wc_buf);
@@ -1629,8 +1659,8 @@ png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
    total_len += png_strlen(buf + total_len);
 #endif
 
-   png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len);
-   png_write_chunk(png_ptr, png_sCAL, (png_bytep)buf, total_len);
+   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
+   png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len);
 }
 #else
 #ifdef PNG_FIXED_POINT_SUPPORTED
@@ -1644,7 +1674,7 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
    png_byte buf[64];
    png_size_t wlen, hlen, total_len;
 
-   png_debug(1, "in png_write_sCAL_s\n");
+   png_debug(1, "in png_write_sCAL_s");
 
    wlen = png_strlen(width);
    hlen = png_strlen(height);
@@ -1656,18 +1686,18 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
    }
 
    buf[0] = (png_byte)unit;
-   png_memcpy(buf + 1, width, wlen + 1);      /* append the '\0' here */
-   png_memcpy(buf + wlen + 2, height, hlen);  /* do NOT append the '\0' here */
+   png_memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
+   png_memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
 
-   png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len);
-   png_write_chunk(png_ptr, png_sCAL, buf, total_len);
+   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
+   png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len);
 }
 #endif
 #endif
 #endif
 
-#if defined(PNG_WRITE_pHYs_SUPPORTED)
-/* write the pHYs chunk */
+#ifdef PNG_WRITE_pHYs_SUPPORTED
+/* Write the pHYs chunk */
 void /* PRIVATE */
 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
    png_uint_32 y_pixels_per_unit,
@@ -1678,7 +1708,8 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
 #endif
    png_byte buf[9];
 
-   png_debug(1, "in png_write_pHYs\n");
+   png_debug(1, "in png_write_pHYs");
+
    if (unit_type >= PNG_RESOLUTION_LAST)
       png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
 
@@ -1686,11 +1717,11 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
    png_save_uint_32(buf + 4, y_pixels_per_unit);
    buf[8] = (png_byte)unit_type;
 
-   png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
+   png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
 }
 #endif
 
-#if defined(PNG_WRITE_tIME_SUPPORTED)
+#ifdef PNG_WRITE_tIME_SUPPORTED
 /* Write the tIME chunk.  Use either png_convert_from_struct_tm()
  * or png_convert_from_time_t(), or fill in the structure yourself.
  */
@@ -1702,7 +1733,8 @@ png_write_tIME(png_structp png_ptr, png_timep mod_time)
 #endif
    png_byte buf[7];
 
-   png_debug(1, "in png_write_tIME\n");
+   png_debug(1, "in png_write_tIME");
+
    if (mod_time->month  > 12 || mod_time->month  < 1 ||
        mod_time->day    > 31 || mod_time->day    < 1 ||
        mod_time->hour   > 23 || mod_time->second > 60)
@@ -1718,83 +1750,83 @@ png_write_tIME(png_structp png_ptr, png_timep mod_time)
    buf[5] = mod_time->minute;
    buf[6] = mod_time->second;
 
-   png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
+   png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7);
 }
 #endif
 
-/* initializes the row writing capability of libpng */
+/* Initializes the row writing capability of libpng */
 void /* PRIVATE */
 png_write_start_row(png_structp png_ptr)
 {
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
-#ifdef PNG_USE_LOCAL_ARRAYS
-   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
-   /* start of interlace block */
+   /* Start of interlace block */
    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
 
-   /* offset to next interlace block */
+   /* Offset to next interlace block */
    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
 
-   /* start of interlace block in the y direction */
+   /* Start of interlace block in the y direction */
    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
 
-   /* offset to next interlace block in the y direction */
+   /* Offset to next interlace block in the y direction */
    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
 #endif
-#endif
 
    png_size_t buf_size;
 
-   png_debug(1, "in png_write_start_row\n");
+   png_debug(1, "in png_write_start_row");
+
    buf_size = (png_size_t)(PNG_ROWBYTES(
-      png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1);
+      png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1);
 
-   /* set up row buffer */
-   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
+   /* Set up row buffer */
+   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
+     (png_uint_32)buf_size);
    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
 
-#ifndef PNG_NO_WRITE_FILTERING
-   /* set up filtering buffer, if using this filter */
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+   /* Set up filtering buffer, if using this filter */
    if (png_ptr->do_filter & PNG_FILTER_SUB)
    {
       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
-         (png_ptr->rowbytes + 1));
+         (png_uint_32)(png_ptr->rowbytes + 1));
       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
    }
 
    /* We only need to keep the previous row if we are using one of these. */
    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
    {
-     /* set up previous row buffer */
-      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
-      png_memset(png_ptr->prev_row, 0, buf_size);
+      /* Set up previous row buffer */
+      png_ptr->prev_row = (png_bytep)png_calloc(png_ptr,
+         (png_uint_32)buf_size);
 
       if (png_ptr->do_filter & PNG_FILTER_UP)
       {
          png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
-            (png_ptr->rowbytes + 1));
+            (png_uint_32)(png_ptr->rowbytes + 1));
          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
       }
 
       if (png_ptr->do_filter & PNG_FILTER_AVG)
       {
          png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
-            (png_ptr->rowbytes + 1));
+            (png_uint_32)(png_ptr->rowbytes + 1));
          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
       }
 
       if (png_ptr->do_filter & PNG_FILTER_PAETH)
       {
          png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
-            (png_ptr->rowbytes + 1));
+            (png_uint_32)(png_ptr->rowbytes + 1));
          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
       }
-#endif /* PNG_NO_WRITE_FILTERING */
    }
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
 
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* if interlaced, we need to set up width and height of pass */
+   /* If interlaced, we need to set up width and height of pass */
    if (png_ptr->interlaced)
    {
       if (!(png_ptr->transformations & PNG_INTERLACE))
@@ -1825,35 +1857,34 @@ void /* PRIVATE */
 png_write_finish_row(png_structp png_ptr)
 {
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
-#ifdef PNG_USE_LOCAL_ARRAYS
-   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
-   /* start of interlace block */
+   /* Start of interlace block */
    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
 
-   /* offset to next interlace block */
+   /* Offset to next interlace block */
    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
 
-   /* start of interlace block in the y direction */
+   /* Start of interlace block in the y direction */
    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
 
-   /* offset to next interlace block in the y direction */
+   /* Offset to next interlace block in the y direction */
    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
 #endif
-#endif
 
    int ret;
 
-   png_debug(1, "in png_write_finish_row\n");
-   /* next row */
+   png_debug(1, "in png_write_finish_row");
+
+   /* Next row */
    png_ptr->row_number++;
 
-   /* see if we are done */
+   /* See if we are done */
    if (png_ptr->row_number < png_ptr->num_rows)
       return;
 
 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* if interlaced, go to next pass */
+   /* If interlaced, go to next pass */
    if (png_ptr->interlaced)
    {
       png_ptr->row_number = 0;
@@ -1863,7 +1894,7 @@ png_write_finish_row(png_structp png_ptr)
       }
       else
       {
-         /* loop until we find a non-zero width or height pass */
+         /* Loop until we find a non-zero width or height pass */
          do
          {
             png_ptr->pass++;
@@ -1883,28 +1914,28 @@ png_write_finish_row(png_structp png_ptr)
 
       }
 
-      /* reset the row above the image for the next pass */
+      /* Reset the row above the image for the next pass */
       if (png_ptr->pass < 7)
       {
          if (png_ptr->prev_row != NULL)
             png_memset(png_ptr->prev_row, 0,
                (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
-               png_ptr->usr_bit_depth,png_ptr->width))+1);
+               png_ptr->usr_bit_depth, png_ptr->width)) + 1);
          return;
       }
    }
 #endif
 
-   /* if we get here, we've just written the last row, so we need
+   /* If we get here, we've just written the last row, so we need
       to flush the compressor */
    do
    {
-      /* tell the compressor we are done */
+      /* Tell the compressor we are done */
       ret = deflate(&png_ptr->zstream, Z_FINISH);
-      /* check for an error */
+      /* Check for an error */
       if (ret == Z_OK)
       {
-         /* check to see if we need more room */
+         /* Check to see if we need more room */
          if (!(png_ptr->zstream.avail_out))
          {
             png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
@@ -1921,7 +1952,7 @@ png_write_finish_row(png_structp png_ptr)
       }
    } while (ret != Z_STREAM_END);
 
-   /* write any extra space */
+   /* Write any extra space */
    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
    {
       png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
@@ -1932,7 +1963,7 @@ png_write_finish_row(png_structp png_ptr)
    png_ptr->zstream.data_type = Z_BINARY;
 }
 
-#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
 /* Pick out the correct pixels for the interlace pass.
  * The basic idea here is to go through the row with a source
  * pointer and a destination pointer (sp and dp), and copy the
@@ -1943,25 +1974,24 @@ png_write_finish_row(png_structp png_ptr)
 void /* PRIVATE */
 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
 {
-#ifdef PNG_USE_LOCAL_ARRAYS
-   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 
-   /* start of interlace block */
+   /* Start of interlace block */
    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
 
-   /* offset to next interlace block */
+   /* Offset to next interlace block */
    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-#endif
 
-   png_debug(1, "in png_do_write_interlace\n");
-   /* we don't have to do anything on the last pass (6) */
-#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   png_debug(1, "in png_do_write_interlace");
+
+   /* We don't have to do anything on the last pass (6) */
+#ifdef PNG_USELESS_TESTS_SUPPORTED
    if (row != NULL && row_info != NULL && pass < 6)
 #else
    if (pass < 6)
 #endif
    {
-      /* each pixel depth is handled separately */
+      /* Each pixel depth is handled separately */
       switch (row_info->pixel_depth)
       {
          case 1:
@@ -2072,27 +2102,27 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
             png_uint_32 row_width = row_info->width;
             png_size_t pixel_bytes;
 
-            /* start at the beginning */
+            /* Start at the beginning */
             dp = row;
-            /* find out how many bytes each pixel takes up */
+            /* Find out how many bytes each pixel takes up */
             pixel_bytes = (row_info->pixel_depth >> 3);
-            /* loop through the row, only looking at the pixels that
+            /* Loop through the row, only looking at the pixels that
                matter */
             for (i = png_pass_start[pass]; i < row_width;
                i += png_pass_inc[pass])
             {
-               /* find out where the original pixel is */
+               /* Find out where the original pixel is */
                sp = row + (png_size_t)i * pixel_bytes;
-               /* move the pixel */
+               /* Move the pixel */
                if (dp != sp)
                   png_memcpy(dp, sp, pixel_bytes);
-               /* next pixel */
+               /* Next pixel */
                dp += pixel_bytes;
             }
             break;
          }
       }
-      /* set new row width */
+      /* Set new row width */
       row_info->width = (row_info->width +
          png_pass_inc[pass] - 1 -
          png_pass_start[pass]) /
@@ -2115,23 +2145,32 @@ void /* PRIVATE */
 png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 {
    png_bytep best_row;
-#ifndef PNG_NO_WRITE_FILTER
+#ifdef PNG_WRITE_FILTER_SUPPORTED
    png_bytep prev_row, row_buf;
    png_uint_32 mins, bpp;
    png_byte filter_to_do = png_ptr->do_filter;
    png_uint_32 row_bytes = row_info->rowbytes;
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
    int num_p_filters = (int)png_ptr->num_prev_filters;
-#endif
+#endif 
+
+   png_debug(1, "in png_write_find_filter");
 
-   png_debug(1, "in png_write_find_filter\n");
-   /* find out how many bytes offset each pixel is */
+#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+  if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
+  {
+      /* These will never be selected so we need not test them. */
+      filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
+  }
+#endif 
+
+   /* Find out how many bytes offset each pixel is */
    bpp = (row_info->pixel_depth + 7) >> 3;
 
    prev_row = png_ptr->prev_row;
 #endif
    best_row = png_ptr->row_buf;
-#ifndef PNG_NO_WRITE_FILTER
+#ifdef PNG_WRITE_FILTER_SUPPORTED
    row_buf = best_row;
    mins = PNG_MAXSUM;
 
@@ -2174,7 +2213,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
          sum += (v < 128) ? v : 256 - v;
       }
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          png_uint_32 sumhi, sumlo;
@@ -2212,9 +2251,9 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       mins = sum;
    }
 
-   /* sub filter */
+   /* Sub filter */
    if (filter_to_do == PNG_FILTER_SUB)
-   /* it's the only filter so no testing is needed */
+   /* It's the only filter so no testing is needed */
    {
       png_bytep rp, lp, dp;
       png_uint_32 i;
@@ -2238,7 +2277,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_uint_32 i;
       int v;
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       /* We temporarily increase the "minimum sum" by the factor we
        * would reduce the sum of this filter, so that we can do the
        * early exit comparison without scaling the sum each time.
@@ -2291,7 +2330,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          int j;
@@ -2329,7 +2368,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       }
    }
 
-   /* up filter */
+   /* Up filter */
    if (filter_to_do == PNG_FILTER_UP)
    {
       png_bytep rp, dp, pp;
@@ -2352,7 +2391,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       int v;
 
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          int j;
@@ -2394,7 +2433,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          int j;
@@ -2432,7 +2471,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       }
    }
 
-   /* avg filter */
+   /* Avg filter */
    if (filter_to_do == PNG_FILTER_AVG)
    {
       png_bytep rp, dp, pp, lp;
@@ -2457,7 +2496,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_uint_32 i;
       int v;
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          int j;
@@ -2506,7 +2545,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          int j;
@@ -2590,7 +2629,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_uint_32 i;
       int v;
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          int j;
@@ -2671,7 +2710,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
             break;
       }
 
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
       {
          int j;
@@ -2707,13 +2746,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
          best_row = png_ptr->paeth_row;
       }
    }
-#endif /* PNG_NO_WRITE_FILTER */
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
    /* Do the actual writing of the filtered row data from the chosen filter. */
 
    png_write_filtered_row(png_ptr, best_row);
 
-#ifndef PNG_NO_WRITE_FILTER
-#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
    /* Save the type of filter we picked this time for future calculations */
    if (png_ptr->num_prev_filters > 0)
    {
@@ -2725,7 +2764,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
       png_ptr->prev_filters[j] = best_row[0];
    }
 #endif
-#endif /* PNG_NO_WRITE_FILTER */
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
 }
 
 
@@ -2733,20 +2772,21 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
 void /* PRIVATE */
 png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
 {
-   png_debug(1, "in png_write_filtered_row\n");
-   png_debug1(2, "filter = %d\n", filtered_row[0]);
-   /* set up the zlib input buffer */
+   png_debug(1, "in png_write_filtered_row");
+
+   png_debug1(2, "filter = %d", filtered_row[0]);
+   /* Set up the zlib input buffer */
 
    png_ptr->zstream.next_in = filtered_row;
    png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
-   /* repeat until we have compressed all the data */
+   /* Repeat until we have compressed all the data */
    do
    {
-      int ret; /* return of zlib */
+      int ret; /* Return of zlib */
 
-      /* compress the data */
+      /* Compress the data */
       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
-      /* check for compression errors */
+      /* Check for compression errors */
       if (ret != Z_OK)
       {
          if (png_ptr->zstream.msg != NULL)
@@ -2755,18 +2795,18 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
             png_error(png_ptr, "zlib error");
       }
 
-      /* see if it is time to write another IDAT */
+      /* See if it is time to write another IDAT */
       if (!(png_ptr->zstream.avail_out))
       {
-         /* write the IDAT and reset the zlib output buffer */
+         /* Write the IDAT and reset the zlib output buffer */
          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
          png_ptr->zstream.next_out = png_ptr->zbuf;
          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
       }
-   /* repeat until all data has been compressed */
+   /* Repeat until all data has been compressed */
    } while (png_ptr->zstream.avail_in);
 
-   /* swap the current and previous rows */
+   /* Swap the current and previous rows */
    if (png_ptr->prev_row != NULL)
    {
       png_bytep tptr;
@@ -2776,10 +2816,10 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
       png_ptr->row_buf = tptr;
    }
 
-   /* finish row - updates counters and flushes zlib if last row */
+   /* Finish row - updates counters and flushes zlib if last row */
    png_write_finish_row(png_ptr);
 
-#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
    png_ptr->flush_rows++;
 
    if (png_ptr->flush_dist > 0 &&
diff --git a/graf2d/cocoa/inc/CocoaPrivate.h b/graf2d/cocoa/inc/CocoaPrivate.h
index 690bfd3..6cf64b6 100644
--- a/graf2d/cocoa/inc/CocoaPrivate.h
+++ b/graf2d/cocoa/inc/CocoaPrivate.h
@@ -9,7 +9,6 @@
  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
  *************************************************************************/
 
-
 #ifndef ROOT_CocoaPrivate
 #define ROOT_CocoaPrivate
 
@@ -59,8 +58,8 @@ namespace MacOSX {
 namespace Details {
 
 class CocoaPrivate {
-   friend class TGCocoa;
-   friend class TGQuartz;
+   friend class ::TGCocoa;
+   friend class ::TGQuartz;
    friend class X11::CommandBuffer;
 public:
    ~CocoaPrivate();
diff --git a/graf2d/cocoa/inc/MenuLoader.h b/graf2d/cocoa/inc/MenuLoader.h
index 5dfe66b..5798904 100644
--- a/graf2d/cocoa/inc/MenuLoader.h
+++ b/graf2d/cocoa/inc/MenuLoader.h
@@ -1,7 +1,7 @@
 #ifndef ROOT_MenuLoader
 #define ROOT_MenuLoader
 
-#import <Cocoa/Cocoa.h>
+#include <Cocoa/Cocoa.h>
 
 namespace ROOT {
 namespace MacOSX {
diff --git a/graf2d/cocoa/inc/QuartzPixmap.h b/graf2d/cocoa/inc/QuartzPixmap.h
index 2b8ec0e..17c9ff4 100644
--- a/graf2d/cocoa/inc/QuartzPixmap.h
+++ b/graf2d/cocoa/inc/QuartzPixmap.h
@@ -13,11 +13,17 @@
 #ifndef ROOT_QuartzPixmap
 #define ROOT_QuartzPixmap
 
-#import <Cocoa/Cocoa.h>
+#include <Cocoa/Cocoa.h>
 
-#import "CocoaGuiTypes.h"
-#import "X11Drawable.h"
-#import "GuiTypes.h"
+#ifndef ROOT_CocoaGuiTypes
+#include "CocoaGuiTypes.h"
+#endif
+#ifndef ROOT_X11Drawable
+#include "X11Drawable.h"
+#endif
+#ifndef ROOT_GuiTypes
+#include "GuiTypes.h"
+#endif
 
 ///////////////////////////////////////////////////////
 //                                                   //
diff --git a/graf2d/cocoa/inc/QuartzWindow.h b/graf2d/cocoa/inc/QuartzWindow.h
index 8d38351..b689928 100644
--- a/graf2d/cocoa/inc/QuartzWindow.h
+++ b/graf2d/cocoa/inc/QuartzWindow.h
@@ -12,11 +12,17 @@
 #ifndef ROOT_QuartzWindow
 #define ROOT_QuartzWindow
 
-#import <Cocoa/Cocoa.h>
+#include <Cocoa/Cocoa.h>
 
-#import "CocoaGuiTypes.h"
-#import "X11Drawable.h"
-#import "GuiTypes.h"
+#ifndef ROOT_CocoaGuiTypes
+#include "CocoaGuiTypes.h"
+#endif
+#ifndef ROOT_X11Drawable
+#include "X11Drawable.h"
+#endif
+#ifndef ROOT_GuiTypes
+#include "GuiTypes.h"
+#endif
 
 ////////////////////////////////////////////////
 //                                            //
diff --git a/graf2d/cocoa/inc/ROOTApplicationDelegate.h b/graf2d/cocoa/inc/ROOTApplicationDelegate.h
index 27408e9..572aee2 100644
--- a/graf2d/cocoa/inc/ROOTApplicationDelegate.h
+++ b/graf2d/cocoa/inc/ROOTApplicationDelegate.h
@@ -1,7 +1,7 @@
 #ifndef ROOT_ROOTApplicationDelegate
 #define ROOT_ROOTApplicationDelegate
 
-#import <Cocoa/Cocoa.h>
+#include <Cocoa/Cocoa.h>
 
 @interface ROOTApplicationDelegate : NSObject<NSApplicationDelegate>
 @end
diff --git a/graf2d/cocoa/inc/ROOTOpenGLView.h b/graf2d/cocoa/inc/ROOTOpenGLView.h
index b85ed70..914d682 100644
--- a/graf2d/cocoa/inc/ROOTOpenGLView.h
+++ b/graf2d/cocoa/inc/ROOTOpenGLView.h
@@ -12,7 +12,9 @@
 #ifndef ROOT_ROOTOpenGLView
 #define ROOT_ROOTOpenGLView
 
-#import "QuartzWindow.h"
+#ifndef ROOT_QuartzWindow
+#include "QuartzWindow.h"
+#endif
 
 ///////////////////////////////////////////
 //                                       //
diff --git a/graf2d/cocoa/inc/X11Drawable.h b/graf2d/cocoa/inc/X11Drawable.h
index dadd430..0f5a0a4 100644
--- a/graf2d/cocoa/inc/X11Drawable.h
+++ b/graf2d/cocoa/inc/X11Drawable.h
@@ -12,11 +12,17 @@
 #ifndef ROOT_X11Drawable
 #define ROOT_X11Drawable
 
-#import <Cocoa/Cocoa.h>
+#include <Cocoa/Cocoa.h>
 
-#import "CocoaGuiTypes.h"
-#import "TVirtualX.h"
-#import "GuiTypes.h"
+#ifndef ROOT_CocoaGuiTypes
+#include "CocoaGuiTypes.h"
+#endif
+#ifndef ROOT_TVirtualX
+#include "TVirtualX.h"
+#endif
+#ifndef ROOT_GuiTypes
+#include "GuiTypes.h"
+#endif
 
 @class PassiveKeyGrab;
 @class QuartzWindow;
diff --git a/graf2d/cocoa/src/QuartzPixmap.mm b/graf2d/cocoa/src/QuartzPixmap.mm
index 78f105c..359ede8 100644
--- a/graf2d/cocoa/src/QuartzPixmap.mm
+++ b/graf2d/cocoa/src/QuartzPixmap.mm
@@ -11,19 +11,19 @@
 
 //#define NDEBUG
 
-#import <algorithm>
-#import <utility>
-#import <cassert>
-#import <cstddef>
-#import <limits>
-#import <new>
-
-#import "CocoaGuiTypes.h"
-#import "QuartzWindow.h"
-#import "QuartzPixmap.h"
-#import "QuartzUtils.h"
-#import "CocoaUtils.h"
-#import "X11Colors.h"
+#include <algorithm>
+#include <utility>
+#include <cassert>
+#include <cstddef>
+#include <limits>
+#include <new>
+
+#include "CocoaGuiTypes.h"
+#include "QuartzWindow.h"
+#include "QuartzPixmap.h"
+#include "QuartzUtils.h"
+#include "CocoaUtils.h"
+#include "X11Colors.h"
 
 //Call backs for data provider.
 extern "C" {
diff --git a/graf2d/cocoa/src/QuartzWindow.mm b/graf2d/cocoa/src/QuartzWindow.mm
index 981e305..6b923f1 100644
--- a/graf2d/cocoa/src/QuartzWindow.mm
+++ b/graf2d/cocoa/src/QuartzWindow.mm
@@ -14,28 +14,28 @@
 //#define NDEBUG
 
 #ifdef DEBUG_ROOT_COCOA
-#import <iostream>
-#import <fstream>
+#include <iostream>
+#include <fstream>
 
-#import "TClass.h"
+#include "TClass.h"
 #endif
 
-#import <algorithm>
-#import <stdexcept>
-#import <cassert>
-
-#import "ROOTOpenGLView.h"
-#import "QuartzWindow.h"
-#import "QuartzPixmap.h"
-#import "QuartzUtils.h"
-#import "CocoaUtils.h"
-#import "X11Colors.h"
-#import "X11Buffer.h"
-#import "X11Events.h"
-#import "TGWindow.h"
-#import "TGClient.h"
-#import "TSystem.h"
-#import "TGCocoa.h"
+#include <algorithm>
+#include <stdexcept>
+#include <cassert>
+
+#include "ROOTOpenGLView.h"
+#include "QuartzWindow.h"
+#include "QuartzPixmap.h"
+#include "QuartzUtils.h"
+#include "CocoaUtils.h"
+#include "X11Colors.h"
+#include "X11Buffer.h"
+#include "X11Events.h"
+#include "TGWindow.h"
+#include "TGClient.h"
+#include "TSystem.h"
+#include "TGCocoa.h"
 
 namespace ROOT {
 namespace MacOSX {
diff --git a/graf2d/cocoa/src/ROOTApplicationDelegate.mm b/graf2d/cocoa/src/ROOTApplicationDelegate.mm
index c759b18..03c9f0a 100644
--- a/graf2d/cocoa/src/ROOTApplicationDelegate.mm
+++ b/graf2d/cocoa/src/ROOTApplicationDelegate.mm
@@ -1,5 +1,5 @@
-#import "ROOTApplicationDelegate.h"
-#import "TApplication.h"
+#include "ROOTApplicationDelegate.h"
+#include "TApplication.h"
 
 @implementation ROOTApplicationDelegate
 
diff --git a/graf2d/cocoa/src/ROOTOpenGLView.mm b/graf2d/cocoa/src/ROOTOpenGLView.mm
index 2007f9d..c348ac5 100644
--- a/graf2d/cocoa/src/ROOTOpenGLView.mm
+++ b/graf2d/cocoa/src/ROOTOpenGLView.mm
@@ -9,11 +9,11 @@
  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
  *************************************************************************/
 
-#import <cassert>
+#include <cassert>
 
-#import "ROOTOpenGLView.h"
-#import "X11Events.h"
-#import "TGCocoa.h"
+#include "ROOTOpenGLView.h"
+#include "X11Events.h"
+#include "TGCocoa.h"
 
 namespace ROOT {
 namespace MacOSX {
diff --git a/graf2d/cocoa/src/TGCocoa.mm b/graf2d/cocoa/src/TGCocoa.mm
index 8753018..a3a03d2 100644
--- a/graf2d/cocoa/src/TGCocoa.mm
+++ b/graf2d/cocoa/src/TGCocoa.mm
@@ -23,6 +23,7 @@
 #include <OpenGL/gl.h>
 
 #include "ROOTOpenGLView.h"
+#include "TMacOSXSystem.h"
 #include "CocoaPrivate.h"
 #include "QuartzWindow.h"
 #include "QuartzPixmap.h"
@@ -355,6 +356,12 @@ TGCocoa::TGCocoa()
               fForegroundProcess(false),
               fSetApp(true)
 {
+   assert(dynamic_cast<TMacOSXSystem *>(gSystem) != nullptr && "TGCocoa, gSystem is eihter null or has a wrong type");
+   TMacOSXSystem * const system = (TMacOSXSystem *)gSystem;
+   
+   if (!system->CocoaInitialized())
+      system->InitializeCocoa();
+
    fPimpl.reset(new Details::CocoaPrivate);
 
    X11::InitWithPredefinedAtoms(fNameToAtom, fAtomToName);
@@ -371,6 +378,12 @@ TGCocoa::TGCocoa(const char *name, const char *title)
               fForegroundProcess(false),
               fSetApp(true)
 {
+   assert(dynamic_cast<TMacOSXSystem *>(gSystem) != nullptr && "TGCocoa, gSystem is eihter null or has a wrong type");
+   TMacOSXSystem * const system = (TMacOSXSystem *)gSystem;
+   
+   if (!system->CocoaInitialized())
+      system->InitializeCocoa();
+
    fPimpl.reset(new Details::CocoaPrivate);
    
    X11::InitWithPredefinedAtoms(fNameToAtom, fAtomToName);
diff --git a/graf2d/cocoa/src/TGQuartz.mm b/graf2d/cocoa/src/TGQuartz.mm
index 058b7a9..22494eb 100644
--- a/graf2d/cocoa/src/TGQuartz.mm
+++ b/graf2d/cocoa/src/TGQuartz.mm
@@ -84,11 +84,11 @@ TGQuartz::TGQuartz()
    //Default ctor.
    
 
-   if (!TTF::fgInit)
+   if (!TTF::IsInitialized())
       TTF::Init();
 
    //I do not know why TTF::Init returns void and I have to check fgInit again.
-   if (!TTF::fgInit)
+   if (!TTF::IsInitialized())
       Error("TGQuartz", "TTF::Init() failed");
 
    fAlign.x = 0;
@@ -101,11 +101,11 @@ TGQuartz::TGQuartz(const char *name, const char *title)
             : TGCocoa(name, title)
 {
    //Constructor.
-   if (!TTF::fgInit)
+   if (!TTF::IsInitialized())
       TTF::Init();
 
    //I do not know why TTF::Init returns void and I have to check fgInit again.
-   if (!TTF::fgInit)
+   if (!TTF::IsInitialized())
       Error("TGQuartz", "TTF::Init() failed");
 
    fAlign.x = 0;
@@ -376,7 +376,7 @@ void TGQuartz::DrawText(Int_t x, Int_t y, Float_t angle, Float_t /*mgn*/, const
    if (!text || !text[0])
       return;
 
-   if (!TTF::fgInit) {
+   if (!TTF::IsInitialized()) {
       Error("DrawText", "wchar_t string to draw, but TTF initialization failed");
       return;
    }
@@ -545,15 +545,19 @@ void TGQuartz::SetTextFont(Font_t fontNumber)
 
    TAttText::SetTextFont(fontNumber);
    
-   if (TTF::fgInit)
-      TTF::SetTextFont(fontNumber);
+   if (!TTF::IsInitialized()) {
+      Error("SetTextFont", "TTF is not initialized");
+      return;
+   }
+
+   TTF::SetTextFont(fontNumber);
 }
 
 //______________________________________________________________________________
 Int_t TGQuartz::SetTextFont(char *fontName, ETextSetMode /*mode*/)
 {
    //This function is never used in gPad (in normal text rendering, so I'm not setting anything for CoreText).
-   if (!TTF::fgInit) {
+   if (!TTF::IsInitialized()) {
       Error("SetTextFont", "TTF is not initialized");
       return 0;
    }
@@ -568,8 +572,12 @@ void TGQuartz::SetTextSize(Float_t textsize)
    
    TAttText::SetTextSize(textsize);
    
-   if (TTF::fgInit)
-      TTF::SetTextSize(textsize);
+   if (!TTF::IsInitialized()) {
+      Error("SetTextSize", "TTF is not initialized");
+      return;
+   }
+
+   TTF::SetTextSize(textsize);
 }
 
 
@@ -601,23 +609,23 @@ void TGQuartz::AlignTTFString()
 
    // vertical alignment
    if (align == kTLeft || align == kTCenter || align == kTRight) {
-      fAlign.y = TTF::fgAscent;
+      fAlign.y = TTF::GetAscent();
    } else if (align == kMLeft || align == kMCenter || align == kMRight) {
-      fAlign.y = TTF::fgAscent / 2;
+      fAlign.y = TTF::GetAscent() / 2;
    } else {
       fAlign.y = 0;
    }
 
    // horizontal alignment
    if (align == kTRight || align == kMRight || align == kBRight) {
-      fAlign.x = TTF::fgWidth;
+      fAlign.x = TTF::GetWidth();
    } else if (align == kTCenter || align == kMCenter || align == kBCenter) {
-      fAlign.x = TTF::fgWidth / 2;
+      fAlign.x = TTF::GetWidth() / 2;
    } else {
       fAlign.x = 0;
    }
 
-   FT_Vector_Transform(&fAlign, TTF::fgRotMatrix);
+   FT_Vector_Transform(&fAlign, TTF::GetRotMatrix());
    //This shift is from the original code.
    fAlign.x = fAlign.x >> 6;
    fAlign.y = fAlign.y >> 6;
@@ -738,9 +746,9 @@ void TGQuartz::RenderTTFString(Int_t x, Int_t y, ETextMode mode)
    
    CGContextSetRGBStrokeColor(ctx, 0., 0., 1., 1.);
    // paint the glyphs in the pixmap.
-   TTGlyph *glyph = TTF::fgGlyphs;
-   for (int n = 0; n < TTF::fgNumGlyphs; ++n, ++glyph) {
-      if (FT_Glyph_To_Bitmap(&glyph->fImage, TTF::fgSmoothing ? ft_render_mode_normal : ft_render_mode_mono, 0, 1 ))
+   TTGlyph *glyph = TTF::GetGlyphs();
+   for (int n = 0; n < TTF::GetNumGlyphs(); ++n, ++glyph) {
+      if (FT_Glyph_To_Bitmap(&glyph->fImage, TTF::GetSmoothing() ? ft_render_mode_normal : ft_render_mode_mono, 0, 1 ))
          continue;
 
       FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
@@ -770,7 +778,7 @@ void TGQuartz::DrawFTGlyphIntoPixmap(void *pHack, FT_Bitmap *source, ULong_t for
    assert(pixmap != nil && "DrawFTGlyphIntoPixmap, pixmap parameter is nil");
    assert(source != 0 && "DrawFTGlyphIntoPixmap, source parameter is null");
 
-   if (TTF::fgSmoothing) {
+   if (TTF::GetSmoothing()) {
       static ColorStruct_t col[5];
       // background kClear, i.e. transparent, we take as background color
       // the average of the rgb values of all pixels covered by this character
diff --git a/graf2d/gpad/src/TCanvas.cxx b/graf2d/gpad/src/TCanvas.cxx
index 1198fea..da4111a 100644
--- a/graf2d/gpad/src/TCanvas.cxx
+++ b/graf2d/gpad/src/TCanvas.cxx
@@ -111,9 +111,10 @@ of the canvas. It gives a short explanation about the canvas' menus.
 <p>
 A canvas may be automatically divided into pads via <tt>TPad::Divide</tt>.
 <p>
-At creation time, the canvas size defines the size of the canvas window
-(including the window manager's decoration). To define precisely the graphics
-area size of a canvas, the following four lines of code should be used:
+At creation time, in interactive mode, the canvas size defines the size of the
+canvas window (including the window manager's decoration). To define precisely
+the graphics area size of a canvas, the following four lines of code should be
+used:
 <pre>
    {
       Double_t w = 600;
@@ -122,6 +123,10 @@ area size of a canvas, the following four lines of code should be used:
       c->SetWindowSize(w + (w - c->GetWw()), h + (h - c->GetWh()));
    }
 </pre>
+in batch mode simply do:
+<pre>
+      c->SetCanvasSize(w,h);
+</pre>
 End_Html */
 
 
diff --git a/graf2d/gpad/src/TPad.cxx b/graf2d/gpad/src/TPad.cxx
index 9205e02..d4ad632 100644
--- a/graf2d/gpad/src/TPad.cxx
+++ b/graf2d/gpad/src/TPad.cxx
@@ -396,14 +396,15 @@ TLegend *TPad::BuildLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2,
 {
    // Build a legend from the graphical objects in the pad
    //
-   // A simple method to to build automatically a TLegend from the primitives in
-   // a TPad. Only those deriving from TAttLine, TAttMarker and TAttFill are
-   // added, excluding TPave and TFrame derived classes.
-   // x1, y1, x2, y2 are the Tlegend coordinates.
-   // title is the legend title. By default it is " ".
+   // A simple method to to build automatically a TLegend from the
+   // primitives in a TPad. Only those deriving from TAttLine,
+   // TAttMarker and TAttFill are added, excluding TPave and TFrame
+   // derived classes. x1, y1, x2, y2 are the TLegend coordinates.
+   // title is the legend title. By default it is " ". The caller 
+   // program owns the returned TLegend.
    //
-   // If the pad contains some TMultiGraph or THStack the individual graphs or
-   // histograms in them are added to the TLegend.
+   // If the pad contains some TMultiGraph or THStack the individual
+   // graphs or histograms in them are added to the TLegend.
 
    TList *lop=GetListOfPrimitives();
    if (!lop) return 0;
@@ -4182,6 +4183,7 @@ void TPad::Print(const char *filenam, Option_t *option)
    //           "Preview" - an Encapsulated Postscript file with preview is produced.
    //               "pdf" - a PDF file is produced
    //               "svg" - a SVG file is produced
+   //               "tex" - a TeX file is produced
    //               "gif" - a GIF file is produced
    //            "gif+NN" - an animated GIF file is produced, where NN is delay in 10ms units
    //               "xpm" - a XPM file is produced
@@ -4454,6 +4456,49 @@ void TPad::Print(const char *filenam, Option_t *option)
 
       return;
    }
+   
+   //==============Save pad/canvas as a TeX file================================
+   if (strstr(opt,"tex")) {
+      gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
+
+      Bool_t noScreen = kFALSE;
+      if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
+         noScreen = kTRUE;
+         GetCanvas()->SetBatch(kTRUE);
+      }
+
+      TPad *padsav = (TPad*)gPad;
+      cd();
+      TVirtualPS *psave = gVirtualPS;
+
+      if (!gVirtualPS) {
+         // Plugin Postscript/SVG driver
+         TPluginHandler *h;
+         if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualPS", "tex"))) {
+            if (h->LoadPlugin() == -1)
+               return;
+            h->ExecPlugin(0);
+         }
+      }
+
+      // Create a new SVG file
+      gVirtualPS->SetName(psname);
+      gVirtualPS->Open(psname);
+      gVirtualPS->SetBit(kPrintingPS);
+      gVirtualPS->NewPage();
+      Paint();
+
+      if (noScreen)  GetCanvas()->SetBatch(kFALSE);
+
+      if (!gSystem->AccessPathName(psname)) Info("Print", "TeX file %s has been created", psname.Data());
+
+      delete gVirtualPS;
+      gVirtualPS = psave;
+      gVirtualPS = 0;
+      padsav->cd();
+
+      return;
+   }
 
    //==============Save pad/canvas as a Postscript file=========================
 
@@ -4463,13 +4508,13 @@ void TPad::Print(const char *filenam, Option_t *option)
    char *l;
    Bool_t mustOpen  = kTRUE;
    Bool_t mustClose = kTRUE;
-   char *copen=0, *cclose=0, *copenb=0, *ccloseb=0;
+   Bool_t copen=kFALSE, cclose=kFALSE, copenb=kFALSE, ccloseb=kFALSE;
    if (!image) {
       // The parenthesis mechanism is only valid for PS and PDF files.
-      copen   = (char*)strstr(psname.Data(),"("); if (copen)   *copen   = 0;
-      cclose  = (char*)strstr(psname.Data(),")"); if (cclose)  *cclose  = 0;
-      copenb  = (char*)strstr(psname.Data(),"["); if (copenb)  *copenb  = 0;
-      ccloseb = (char*)strstr(psname.Data(),"]"); if (ccloseb) *ccloseb = 0;
+      copen   = psname.EndsWith("("); if (copen)   psname[psname.Length()-1] = 0;
+      cclose  = psname.EndsWith(")"); if (cclose)  psname[psname.Length()-1] = 0;
+      copenb  = psname.EndsWith("["); if (copenb)  psname[psname.Length()-1] = 0;
+      ccloseb = psname.EndsWith("]"); if (ccloseb) psname[psname.Length()-1] = 0;
    }
    gVirtualPS = (TVirtualPS*)gROOT->GetListOfSpecials()->FindObject(psname);
    if (gVirtualPS) {mustOpen = kFALSE; mustClose = kFALSE;}
@@ -4529,7 +4574,6 @@ void TPad::Print(const char *filenam, Option_t *option)
          Paint();
       }
       if (noScreen) GetCanvas()->SetBatch(kFALSE);
-      if (!gSystem->AccessPathName(psname)) Info("Print", "%s file %s has been created", opt, psname.Data());
 
       if (mustClose) {
          gROOT->GetListOfSpecials()->Remove(gVirtualPS);
@@ -4539,6 +4583,8 @@ void TPad::Print(const char *filenam, Option_t *option)
          gROOT->GetListOfSpecials()->Add(gVirtualPS);
          gVirtualPS = 0;
       }
+
+      if (!gSystem->AccessPathName(psname)) Info("Print", "%s file %s has been created", opt, psname.Data());
    } else {
       // Append to existing Postscript, PDF or GIF file
       if (!ccloseb) {
@@ -4920,6 +4966,7 @@ void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
    //   if filename contains .eps, an Encapsulated Postscript file is produced
    //   if filename contains .pdf, a PDF file is produced
    //   if filename contains .svg, a SVG file is produced
+   //   if filename contains .tex, a TeX file is produced
    //   if filename contains .gif, a GIF file is produced
    //   if filename contains .gif+NN, an  animated GIF file is produced
    //   if filename contains .xpm, a XPM file is produced
@@ -4971,6 +5018,8 @@ void TPad::SaveAs(const char *filename, Option_t * /*option*/) const
       ((TPad*)this)->Print(psname,"pdf");
    else if (psname.EndsWith(".svg"))
       ((TPad*)this)->Print(psname,"svg");
+   else if (psname.EndsWith(".tex"))
+      ((TPad*)this)->Print(psname,"tex");
    else if (psname.EndsWith(".xpm"))
       ((TPad*)this)->Print(psname,"xpm");
    else if (psname.EndsWith(".png"))
@@ -5160,9 +5209,13 @@ void TPad::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
 
    TIter next(GetListOfPrimitives());
    TObject *obj;
+   Int_t grnum = 0;
 
-   while ((obj = next()))
-         obj->SavePrimitive(out, (Option_t *)next.GetOption());
+   while ((obj = next())) {
+      if (obj->InheritsFrom(TGraph::Class()))
+         if (!strcmp(obj->GetName(),"Graph")) ((TGraph*)obj)->SetName(Form("Graph%d",grnum++));
+      obj->SavePrimitive(out, (Option_t *)next.GetOption());
+   }
    out<<"   "<<cname<<"->Modified();"<<std::endl;
    out<<"   "<<GetMother()->GetName()<<"->cd();"<<std::endl;
    if (padsav) padsav->cd();
diff --git a/graf2d/graf/inc/TTF.h b/graf2d/graf/inc/TTF.h
index a8bd4bf..838f786 100644
--- a/graf2d/graf/inc/TTF.h
+++ b/graf2d/graf/inc/TTF.h
@@ -62,7 +62,6 @@ class TTF {
 friend class TGX11TTF;
 friend class TGWin32;
 friend class TMathTextRenderer;
-friend class TGQuartz;
 
 protected:
    enum { kTTMaxFonts = 32, kMaxGlyphs = 1024 };
diff --git a/graf2d/graf/src/TLatex.cxx b/graf2d/graf/src/TLatex.cxx
index f013043..2769e67 100644
--- a/graf2d/graf/src/TLatex.cxx
+++ b/graf2d/graf/src/TLatex.cxx
@@ -19,7 +19,6 @@
 #include "TVirtualPS.h"
 
 const Double_t kPI = TMath::Pi();
-const Int_t kLatex = BIT(10);
 
 ClassImp(TLatex)
 
@@ -1879,11 +1878,29 @@ void TLatex::PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, c
 
    TAttText::Modify();  // Change text attributes only if necessary.
 
+   TVirtualPS *saveps = gVirtualPS;
+               
+   if (gVirtualPS) {
+      if (gVirtualPS->InheritsFrom("TTeXDump")) {
+         gVirtualPS->SetTextAngle(angle);
+         TString t(text1);
+         if (t.Index("#")>=0 || t.Index("^")>=0 || t.Index("\\")>=0) {
+            t.ReplaceAll("#","\\");
+            t.ReplaceAll("%","\\%");
+            t.Prepend("$");
+            t.Append("$");
+         }
+         gVirtualPS->Text(x,y,t.Data());
+         gVirtualPS = 0;
+      }
+   }
+   
    // Do not use Latex if font is low precision.
    if (fTextFont%10 < 2) {
       if (gVirtualX) gVirtualX->SetTextAngle(angle);
       if (gVirtualPS) gVirtualPS->SetTextAngle(angle);
       gPad->PaintText(x,y,text1);
+      if (saveps) gVirtualPS = saveps;
       return;
    }
 
@@ -1892,6 +1909,7 @@ void TLatex::PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, c
       TMathText tm;
       tm.SetTextAlign(GetTextAlign());
       tm.PaintMathText(x, y, angle, size, text1);
+      if (saveps) gVirtualPS = saveps;
       return;
    }
 
@@ -1911,12 +1929,12 @@ void TLatex::PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, c
          size = size/h;
       SetTextFont(10*(saveFont/10) + 2);
    }
-   if (gVirtualPS) gVirtualPS->SetBit(kLatex);
 
    fError = 0 ;
    if (CheckLatexSyntax(newText)) {
       std::cout<<"\n*ERROR<TLatex>: "<<fError<<std::endl;
       std::cout<<"==> "<<text1<<std::endl;
+      if (saveps) gVirtualPS = saveps;
       return ;
    }
    fError = 0 ;
@@ -1973,8 +1991,7 @@ void TLatex::PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, c
    SetLineWidth(lineW);
    SetLineColor(lineC);
    delete[] fTabSize;
-
-   if (gVirtualPS) gVirtualPS->ResetBit(kLatex);
+   if (saveps) gVirtualPS = saveps;
 }
 
 
diff --git a/graf2d/graf/src/TLegend.cxx b/graf2d/graf/src/TLegend.cxx
index 7d1e7be..6fdcf25 100644
--- a/graf2d/graf/src/TLegend.cxx
+++ b/graf2d/graf/src/TLegend.cxx
@@ -97,6 +97,25 @@ Begin_Macro(source)
 End_Macro
 Begin_Html
 <br>
+<tt>TLegend</tt> inherits from <tt>TAttText</tt> therefore changing any
+text attributes (text alignmemt, font, color...) on a legend will changed the
+text attributes on each line.
+<br>
+In particular it can be interessting to change the text alignement that way. In
+order to have a base-line vertical alignment instead of a centered one simply do:
+<pre>
+   leg->SetTextAlign(13);
+</pre
+or
+<pre>
+   leg->SetTextAlign(11);
+</pre
+Text attributes can be also changed individually on each legend entry:
+<pre>
+   TLegendEntry *le = leg->AddEntry(h1,"Histogram filled with random numbers","f");
+   le->SetTextColor(kBlue);;
+</pre>
+<br>
 Note that the <tt>TPad</tt> class has a method to build automatically a legend
 for all objects in the pad. It is called <tt>TPad::BuildLegend()</tt>.
 <p>
@@ -122,10 +141,10 @@ Begin_Macro(source)
    TLegend* leg = new TLegend(0.2, 0.2, .8, .8);
    TH1* h = new TH1F("", "", 1, 0, 1);
 
-   leg->AddEntry(h, "Histogram \"h\"", "l"); 
-   leg->AddEntry((TObject*)0, "", "");  
+   leg->AddEntry(h, "Histogram \"h\"", "l");
+   leg->AddEntry((TObject*)0, "", "");
    leg->AddEntry((TObject*)0, "Some text", "");
-   leg->AddEntry((TObject*)0, "", "");  
+   leg->AddEntry((TObject*)0, "", "");
    leg->AddEntry(h, "Histogram \"h\" again", "l");
 
    leg->Draw();
@@ -141,17 +160,17 @@ End_Html
 Begin_Macro(source)
 {
    TCanvas *c3 = new TCanvas("c2","c2",500,300);
- 
+
    TLegend* leg = new TLegend(0.2, 0.2, .8, .8);
    TH1* h = new TH1F("", "", 1, 0, 1);
- 
+
    leg-> SetNColumns(2);
- 
+
    leg->AddEntry(h, "Column 1 line 1", "l");
    leg->AddEntry(h, "Column 2 line 1", "l");
    leg->AddEntry(h, "Column 1 line 2", "l");
    leg->AddEntry(h, "Column 2 line 2", "l");
- 
+
    leg->Draw();
    return c3;
 }
@@ -453,13 +472,13 @@ TLegendEntry *TLegend::GetEntry() const
       Error("GetEntry", "need to create a canvas first");
       return 0;
    }
-   
+
    Int_t nRows = GetNRows();
    if ( nRows == 0 ) return 0;
 
    Double_t ymouse = gPad->AbsPixeltoY(gPad->GetEventY())-fY1;
    Double_t yspace = (fY2 - fY1)/nRows;
-   
+
    Int_t nColumns = GetNColumns();
    Double_t xmouse = gPad->AbsPixeltoX(gPad->GetEventX())-fX1;
    Double_t xspace = 0.;
@@ -469,11 +488,11 @@ TLegendEntry *TLegend::GetEntry() const
    if (xspace > 0.) ix = (Int_t)(xmouse/xspace)+1;
    if (ix > nColumns) ix = nColumns;
    if (ix < 1)        ix = 1;
-   
+
    Int_t iy = nRows-(Int_t)(ymouse/yspace);
    if (iy > nRows) iy = nRows;
    if (iy < 1)     iy = 1;
-   
+
    Int_t nloops = TMath::Min(ix+(nColumns*(iy-1)), fPrimitives->GetSize());
 
    TIter next(fPrimitives);
@@ -516,7 +535,7 @@ void TLegend::InsertEntry( const char* objectName, const char* label, Option_t*
       Error("InsertEntry", "need to create a canvas first");
       return;
    }
-   
+
    TLegendEntry* beforeEntry = GetEntry();   // get entry pointed by the mouse
    TObject *obj = gPad->FindObject( objectName );
 
@@ -608,11 +627,13 @@ void TLegend::PaintPrimitives()
    Double_t boxw = boxwidth*0.35;
    Double_t yspace = (y2-y1)/nRows;
    Double_t textsize = GetTextSize();
+   Bool_t autosize = kFALSE;
    Double_t save_textsize = textsize;
    Double_t* columnWidths = new Double_t[fNColumns];
    memset(columnWidths, 0, fNColumns*sizeof(Double_t));
 
    if ( textsize == 0 ) {
+      autosize = kTRUE;
       textsize = ( 1. - fEntrySeparation ) * yspace;
 
       // find the max width and height (in pad coords) of one latex entry label
@@ -625,6 +646,7 @@ void TLegend::PaintPrimitives()
          entrytex.SetNDC();
          Style_t tfont = entrysize->GetTextFont();
          if (tfont == 0) tfont = GetTextFont();
+         if (tfont%10 == 3) --tfont;
          entrytex.SetTextFont(tfont);
          entrytex.SetTextSize(textsize);
          if ( entrytex.GetYsize() > maxentryheight ) {
@@ -669,6 +691,7 @@ void TLegend::PaintPrimitives()
          entrytex.SetNDC();
          Style_t tfont = entry->GetTextFont();
          if (tfont == 0) tfont = GetTextFont();
+         if (autosize && tfont%10 == 3) --tfont;
          entrytex.SetTextFont(tfont);
          if(entry->GetTextSize() == 0) entrytex.SetTextSize(textsize);
          TString opt = entry->GetOption();
@@ -710,7 +733,11 @@ void TLegend::PaintPrimitives()
       if (talign == 0) entry->SetTextAlign(GetTextAlign());
       if (tangle == 0) entry->SetTextAngle(GetTextAngle());
       if (tcolor == 0) entry->SetTextColor(GetTextColor());
-      if (tfont  == 0) entry->SetTextFont(GetTextFont());
+      if (tfont  == 0) {
+         tfont = GetTextFont();
+         if (autosize && tfont%10 == 3) --tfont;
+         entry->SetTextFont(tfont);
+      }
       if (tsize  == 0) entry->SetTextSize(GetTextSize());
       // set x,y according to the requested alignment
       Double_t x=0,y=0;
@@ -732,10 +759,15 @@ void TLegend::PaintPrimitives()
       if (halign == 2) x = 0.5*( (x1+entrymargin) + x2 );
       if (halign == 3) x = x2 - entrymargin/10.;
       Int_t valign = entry->GetTextAlign()%10;
+
+      // The vertical alignment "centered" is treated in a special to
+      // ensure a better spacing between lines.
+      if (valign == 2) entry->SetTextAlign(10*halign+1);
+
       if (valign == 1) y = ytext - (1. - fEntrySeparation)* yspace/2.;
-      if (valign == 2) y = ytext;
+      if (valign == 2) y = ytext - (1. - fEntrySeparation)* yspace/4.;
       if (valign == 3) y = ytext + (1. - fEntrySeparation)* yspace/2.;
-      //
+
       TLatex entrytex( x, y, entry->GetLabel() );
       entrytex.SetNDC();
       entry->TAttText::Copy(entrytex);
@@ -909,7 +941,7 @@ void TLegend::SetEntryLabel( const char* label )
    /* Begin_Html
    Edit the label of the entry pointed to by the mouse.
    End_Html */
-   
+
    TLegendEntry* entry = GetEntry();   // get entry pointed by the mouse
    if ( entry ) entry->SetLabel( label );
 }
diff --git a/graf2d/graf/src/TMathText.cxx b/graf2d/graf/src/TMathText.cxx
index a5c9819..9c17b2a 100644
--- a/graf2d/graf/src/TMathText.cxx
+++ b/graf2d/graf/src/TMathText.cxx
@@ -46,9 +46,7 @@ Begin_Html
 End_Html
 */
 
-
 const Double_t kPI      = TMath::Pi();
-const Int_t kLatex      = BIT(10);
 
 class TMathTextRenderer : public TText, public TAttFill,
                           public mathtext::math_text_renderer_t {
@@ -269,6 +267,7 @@ public:
    bounding_box(const std::wstring string,
              const unsigned int family = FAMILY_PLAIN)
    {
+      if (TTF::fgCurFontIdx<0) return mathtext::bounding_box_t(0, 0, 0, 0, 0, 0);
       if (string.empty() || TTF::fgFace[TTF::fgCurFontIdx] == NULL ||
          TTF::fgFace[TTF::fgCurFontIdx]->units_per_EM == 0) {
          return mathtext::bounding_box_t(0, 0, 0, 0, 0, 0);
@@ -623,7 +622,6 @@ void TMathText::PaintMathText(Double_t x, Double_t y, Double_t angle,
       size = size / std::min(w, h);
       SetTextFont(10 * (saveFont / 10) + 2);
    }
-   if (gVirtualPS) gVirtualPS->SetBit(kLatex);
 
    const TString newText = text1;
 
@@ -640,8 +638,6 @@ void TMathText::PaintMathText(Double_t x, Double_t y, Double_t angle,
    SetTextSize(saveSize);
    SetTextFont(saveFont);
    SetTextAlign(saveAlign);
-
-   if (gVirtualPS) gVirtualPS->ResetBit(kLatex);
 }
 
 
diff --git a/graf2d/gviz/doc/index.txt b/graf2d/gviz/doc/index.txt
new file mode 100644
index 0000000..cc83ff7
--- /dev/null
+++ b/graf2d/gviz/doc/index.txt
@@ -0,0 +1,5 @@
+BEGIN_HTML
+<ul>
+<li><a href="http://root.cern.ch/root/html/tutorials/graphs/graphstruct.C.html">An example of how the graphviz interface classes are used.</a></li>
+</ul>
+END_HTML
diff --git a/graf2d/mathtext/src/mathrenderstyle.cxx b/graf2d/mathtext/src/mathrenderstyle.cxx
index c220321..6dac545 100644
--- a/graf2d/mathtext/src/mathrenderstyle.cxx
+++ b/graf2d/mathtext/src/mathrenderstyle.cxx
@@ -455,11 +455,13 @@ namespace mathtext {
 								  size);
 			const float remaining_height =
 				height - bounding_box_sum.height();
-			const unsigned long repeat_ratio =
+         unsigned long repeat_ratio = 0;
+         if (bounding_box_repeatable.height() !=0) {
+		      repeat_ratio =
 				(unsigned long)ceil(
 					remaining_height /
 					bounding_box_repeatable.height());
-
+         }
 			nrepeat = glyph[GLYPH_MIDDLE] == L'\0' ?
 				repeat_ratio : ((repeat_ratio + 1UL) >> 1);
 		}
diff --git a/graf2d/postscript/inc/LinkDef.h b/graf2d/postscript/inc/LinkDef.h
index c0e3720..6c3b934 100644
--- a/graf2d/postscript/inc/LinkDef.h
+++ b/graf2d/postscript/inc/LinkDef.h
@@ -18,5 +18,6 @@
 #pragma link C++ class TSVG+;
 #pragma link C++ class TPDF+;
 #pragma link C++ class TImageDump+;
+#pragma link C++ class TTeXDump+;
 
 #endif
diff --git a/graf2d/postscript/inc/TPDF.h b/graf2d/postscript/inc/TPDF.h
index 79578de..497677c 100644
--- a/graf2d/postscript/inc/TPDF.h
+++ b/graf2d/postscript/inc/TPDF.h
@@ -101,7 +101,7 @@ public:
    void     TextNDC(Double_t u, Double_t v, const char *string);
    void     TextNDC(Double_t, Double_t, const wchar_t *){}
    void     WriteCompressedBuffer();
-   virtual  void  WriteReal(Float_t r);
+   virtual  void WriteReal(Float_t r, Bool_t space=kTRUE);
    Double_t UtoPDF(Double_t u);
    Double_t VtoPDF(Double_t v);
    Double_t XtoPDF(Double_t x);
diff --git a/graf2d/postscript/inc/TTeXDump.h b/graf2d/postscript/inc/TTeXDump.h
new file mode 100644
index 0000000..98225a0
--- /dev/null
+++ b/graf2d/postscript/inc/TTeXDump.h
@@ -0,0 +1,90 @@
+// @(#)root/postscript:$Id$
+// Author: Olivier Couet
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TTeXDump
+#define ROOT_TTeXDump
+
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TTeXDump                                                             //
+//                                                                      //
+// Tex driver.                                                          //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_TVirtualPS
+#include "TVirtualPS.h"
+#endif
+
+class TPoints;
+
+class TTeXDump : public TVirtualPS {
+
+protected:
+   Float_t      fXsize;           //Page size along X
+   Float_t      fYsize;           //Page size along Y
+   Int_t        fType;            //Workstation type used to know if the Tex is open
+   Bool_t       fBoundingBox;     //True when the Tex header is printed
+   Bool_t       fRange;           //True when a range has been defined
+   Float_t      fCurrentRed;      //Current Red component
+   Float_t      fCurrentGreen;    //Current Green component
+   Float_t      fCurrentBlue;     //Current Blue component
+
+
+public:
+   TTeXDump();
+   TTeXDump(const char *filename, Int_t type=-113);
+   virtual ~TTeXDump();
+
+   void    CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2);
+   void    CellArrayFill(Int_t r, Int_t g, Int_t b);
+   void    CellArrayEnd();
+   void    Close(Option_t *opt="");
+   Int_t   CMtoTeX(Double_t u) {return Int_t(0.5 + 72*u/2.54);}
+   void    DefineMarkers();
+   void    DrawBox(Double_t x1, Double_t y1,Double_t x2, Double_t  y2);
+   void    DrawFrame(Double_t xl, Double_t yl, Double_t xt, Double_t  yt,
+                     Int_t mode, Int_t border, Int_t dark, Int_t light);
+   void    DrawPolyLine(Int_t n, TPoints *xy);
+   void    DrawPolyLineNDC(Int_t n, TPoints *uv);
+   void    DrawPolyMarker(Int_t n, Float_t *x, Float_t *y);
+   void    DrawPolyMarker(Int_t n, Double_t *x, Double_t *y);
+   void    DrawPS(Int_t n, Float_t *xw, Float_t *yw);
+   void    DrawPS(Int_t n, Double_t *xw, Double_t *yw);
+   void    NewPage();
+   void    Off();
+   void    On();
+   void    Open(const char *filename, Int_t type=-111);
+   void    Range(Float_t xrange, Float_t yrange);
+   void    SetColor(Int_t color = 1);
+   void    SetColor(Float_t r, Float_t g, Float_t b);
+   void    SetFillColor( Color_t cindex=1);
+   void    SetLineColor( Color_t cindex=1);
+   void    SetLineStyle(Style_t linestyle = 1);
+   void    SetLineWidth(Width_t linewidth = 1);
+   void    SetLineScale(Float_t =3) { }
+   void    SetMarkerSize( Size_t msize=1);
+   void    SetMarkerColor( Color_t cindex=1);
+   void    SetTextColor( Color_t cindex=1);
+   void    Text(Double_t x, Double_t y, const char *string);
+   void    Text(Double_t, Double_t, const wchar_t *){}
+   void    TextNDC(Double_t u, Double_t v, const char *string);
+   void    TextNDC(Double_t, Double_t, const wchar_t *){}
+   Float_t UtoTeX(Double_t u);
+   Float_t VtoTeX(Double_t v);
+   Float_t XtoTeX(Double_t x);
+   Float_t YtoTeX(Double_t y);
+
+   ClassDef(TTeXDump,0)  //Tex driver
+};
+
+#endif
diff --git a/graf2d/postscript/src/TPDF.cxx b/graf2d/postscript/src/TPDF.cxx
index 4b9ba3a..1ccdcc8 100644
--- a/graf2d/postscript/src/TPDF.cxx
+++ b/graf2d/postscript/src/TPDF.cxx
@@ -2471,7 +2471,7 @@ void TPDF::WriteCompressedBuffer()
 }
 
 //______________________________________________________________________________
-void TPDF::WriteReal(Float_t z)
+void TPDF::WriteReal(Float_t z, Bool_t space)
 {
    // Write a Real number to the file.
    // This method overwrites TVirtualPS::WriteReal. Some PDF reader like
@@ -2480,7 +2480,12 @@ void TPDF::WriteReal(Float_t z)
    // format "%g" when writing it with "%g" generates a number with exponent.
 
    char str[15];
-   snprintf(str,15," %g", z);
-   if (strstr(str,"e") || strstr(str,"E")) snprintf(str,15," %10.8f", z);
+   if (space) {
+      snprintf(str,15," %g", z);
+      if (strstr(str,"e") || strstr(str,"E")) snprintf(str,15," %10.8f", z);
+   } else {
+      snprintf(str,15,"%g", z);
+      if (strstr(str,"e") || strstr(str,"E")) snprintf(str,15,"%10.8f", z);
+   }
    PrintStr(str);
-}
+}
\ No newline at end of file
diff --git a/graf2d/postscript/src/TPostScript.cxx b/graf2d/postscript/src/TPostScript.cxx
index 4c9e202..5e4b6e0 100644
--- a/graf2d/postscript/src/TPostScript.cxx
+++ b/graf2d/postscript/src/TPostScript.cxx
@@ -396,7 +396,7 @@ void TPostScript::Open(const char *fname, Int_t wtype)
       fXsize = xrange; fYsize = yrange;
    }
 
-   // open OS file
+   // Open OS file
    fFileName = fname;
    fStream = new std::ofstream(fFileName.Data(),std::ios::out);
    if (fStream == 0 || gSystem->AccessPathName(fFileName.Data(),kWritePermission)) {
diff --git a/graf2d/postscript/src/TSVG.cxx b/graf2d/postscript/src/TSVG.cxx
index cc0ef75..790f009 100644
--- a/graf2d/postscript/src/TSVG.cxx
+++ b/graf2d/postscript/src/TSVG.cxx
@@ -132,7 +132,7 @@ void TSVG::Open(const char *fname, Int_t wtype)
    }
 
    // Open OS file
-   fStream   = new ofstream(fname,ios::out);
+   fStream   = new std::ofstream(fname,ios::out);
    if (fStream == 0 || !fStream->good()) {
       printf("ERROR in TSVG::Open: Cannot open file:%s\n",fname);
       if (fStream == 0) return;
diff --git a/graf2d/postscript/src/TTeXDump.cxx b/graf2d/postscript/src/TTeXDump.cxx
new file mode 100644
index 0000000..4ddc82d
--- /dev/null
+++ b/graf2d/postscript/src/TTeXDump.cxx
@@ -0,0 +1,923 @@
+// @(#)root/postscript:$Id$
+// Author: Olivier Couet
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifdef WIN32
+#pragma optimize("",off)
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "Riostream.h"
+#include "TROOT.h"
+#include "TColor.h"
+#include "TVirtualPad.h"
+#include "TPoints.h"
+#include "TTeXDump.h"
+#include "TStyle.h"
+#include "TMath.h"
+#include "TObjString.h"
+#include "TObjArray.h"
+#include "TClass.h"
+
+ClassImp(TTeXDump)
+
+
+//______________________________________________________________________________
+/*Begin_Html
+<center><h2>TTeXDump: Graphics interface to TeX</h2></center>
+This class allow to generate <b>PGF/TikZ</b> vector graphics output
+which can be included in TeX and LaTeX documents.
+<p>
+PGF is a TeX macro package for generating graphics. It is platform
+and format-independent and works together with the most important TeX
+backend drivers, including pdftex and dvips. It comes with a
+user-friendly syntax layer called TikZ.
+<p>
+To generate a such file it is enough to do:
+<pre>
+   gStyle->SetPaperSize(10.,10.);
+   hpx->Draw();
+   gPad->Print("hpx.tex");
+</pre>
+
+<p>Then, the generated file (<tt>hpx.tex</tt>) can be included in a
+LaTeX document (<tt>simple.tex</tt>) in the following way:
+<pre>
+\documentclass{article}
+\usepackage{tikz}
+\usetikzlibrary{patterns}
+\usetikzlibrary{plotmarks}
+\title{A simple LaTeX example}
+\date{July 2013}
+\begin{document}
+\maketitle
+The following image as been generated using the TTeXDump class:
+\par
+\input{hpx.tex}
+\end{document}
+</pre>
+
+Note the three directives needed at the top of the LaTeX file:
+<pre>
+\usepackage{tikz}
+\usetikzlibrary{patterns}
+\usetikzlibrary{plotmarks}
+</pre>
+
+Then including the picture in the document is done with the
+<tt>\input<\tt> directive.
+
+<p> The command <tt>pdflatex simple.tex</tt> will generate the
+corresponding pdf file <tt>simple.pdf</tt>.
+
+End_Html */
+
+
+//______________________________________________________________________________
+TTeXDump::TTeXDump() : TVirtualPS()
+{
+   // Default TeX constructor
+
+   fStream       = 0;
+   fType         = 0;
+   gVirtualPS    = this;
+   fBoundingBox  = kFALSE;
+   fRange        = kFALSE;
+   fXsize        = 0.;
+   fYsize        = 0.;
+   fCurrentRed   = 0.;
+   fCurrentGreen = 0.;
+   fCurrentBlue  = 0.;
+}
+
+
+//______________________________________________________________________________
+TTeXDump::TTeXDump(const char *fname, Int_t wtype) : TVirtualPS(fname, wtype)
+{
+   // Initialize the TeX interface
+   //
+   //  fname : TeX file name
+   //  wtype : TeX workstation type. Not used in the TeX driver. But as TTeXDump
+   //          inherits from TVirtualPS it should be kept. Anyway it is not
+   //          necessary to specify this parameter at creation time because it
+   //          has a default value (which is ignore in the TeX case).
+
+   fStream       = 0;
+   fType         = 0;
+   gVirtualPS    = this;
+   fBoundingBox  = kFALSE;
+   fRange        = kFALSE;
+   fXsize        = 0.;
+   fYsize        = 0.;
+   fCurrentRed   = 0.;
+   fCurrentGreen = 0.;
+   fCurrentBlue  = 0.;
+
+   Open(fname, wtype);
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::Open(const char *fname, Int_t wtype)
+{
+   // Open a TeX file
+
+   if (fStream) {
+      Warning("Open", "TeX file already open");
+      return;
+   }
+
+   fLenBuffer = 0;
+   fType      = abs(wtype);
+
+   gStyle->GetPaperSize(fXsize, fYsize);
+
+   Float_t xrange, yrange;
+   if (gPad) {
+      Double_t ww = gPad->GetWw();
+      Double_t wh = gPad->GetWh();
+      ww *= gPad->GetWNDC();
+      wh *= gPad->GetHNDC();
+      Double_t ratio = wh/ww;
+      xrange = fXsize;
+      yrange = fXsize*ratio;
+      if (yrange > fYsize) { yrange = fYsize; xrange = yrange/ratio;}
+      fXsize = xrange; fYsize = yrange;
+   }
+
+   // Open OS file
+   fStream   = new std::ofstream(fname,std::ios::out);
+   if (fStream == 0 || !fStream->good()) {
+      printf("ERROR in TTeXDump::Open: Cannot open file:%s\n",fname);
+      if (fStream == 0) return;
+   }
+
+   gVirtualPS = this;
+
+   for (Int_t i=0;i<fSizBuffer;i++) fBuffer[i] = ' ';
+
+   fBoundingBox = kFALSE;
+   fRange       = kFALSE;
+
+   // Set a default range
+   Range(fXsize, fYsize);
+
+   NewPage();
+}
+
+
+//______________________________________________________________________________
+TTeXDump::~TTeXDump()
+{
+   // Default TeX destructor
+
+   Close();
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::Close(Option_t *)
+{
+   // Close a TeX file
+
+   if (!gVirtualPS) return;
+   if (!fStream) return;
+   if (gPad) gPad->Update();
+   PrintStr("@");
+   PrintStr("\\end{tikzpicture}@");
+
+   // Close file stream
+   if (fStream) { fStream->close(); delete fStream; fStream = 0;}
+
+   gVirtualPS = 0;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::On()
+{
+   // Activate an already open TeX file
+
+   // fType is used to know if the TeX file is open. Unlike TPostScript, TTeXDump
+   // has no "workstation type". In fact there is only one TeX type.
+
+   if (!fType) {
+      Error("On", "no TeX file open");
+      Off();
+      return;
+   }
+   gVirtualPS = this;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::Off()
+{
+   // Deactivate an already open TeX file
+
+   gVirtualPS = 0;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
+{
+   // Draw a Box
+
+   Float_t x1c = XtoTeX(x1);
+   Float_t y1c = YtoTeX(y1);
+   Float_t x2c = XtoTeX(x2);
+   Float_t y2c = YtoTeX(y2);
+
+   Int_t fillis = fFillStyle/1000;
+   Int_t fillsi = fFillStyle%1000;
+
+   if (fillis==1) {
+      SetColor(fFillColor);
+      PrintStr("@");
+      PrintStr("\\draw [color=c, fill=c] (");
+      WriteReal(x1c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y1c, kFALSE);
+      PrintStr(") rectangle (");
+      WriteReal(x2c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y2c, kFALSE);
+      PrintStr(");");
+   } else if (fillis>1) {
+      SetColor(fFillColor);
+      PrintStr("@");
+      PrintStr("\\draw [pattern=");
+      if (fillsi==1)  PrintStr("crosshatch dots");
+      if (fillsi==2)  PrintStr("dots");
+      if (fillsi==4)  PrintStr("north east lines");
+      if (fillsi==5)  PrintStr("north west lines");
+      if (fillsi==6)  PrintStr("vertical lines");
+      if (fillsi==7)  PrintStr("horizontal lines");
+      if (fillsi==10) PrintStr("bricks");
+      if (fillsi==13) PrintStr("crosshatch");
+      PrintStr(", pattern color=c] (");
+      WriteReal(x1c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y1c, kFALSE);
+      PrintStr(") rectangle (");
+      WriteReal(x2c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y2c, kFALSE);
+      PrintStr(");");
+   } else {
+      SetColor(fLineColor);
+      PrintStr("@");
+      PrintStr("\\draw [c] (");
+      WriteReal(x1c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y1c, kFALSE);
+      PrintStr(") -- (");
+      WriteReal(x1c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y2c, kFALSE);
+      PrintStr(") -- (");
+      WriteReal(x2c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y2c, kFALSE);
+      PrintStr(") -- (");
+      WriteReal(x2c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y1c, kFALSE);
+      PrintStr(") -- (");
+      WriteReal(x1c, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y1c, kFALSE);
+      PrintStr(");");
+   }
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawFrame(Double_t, Double_t, Double_t, Double_t,
+                         Int_t, Int_t, Int_t, Int_t)
+{
+   // Draw a Frame around a box
+   //
+   // mode = -1  the box looks as it is behind the screen
+   // mode =  1  the box looks as it is in front of the screen
+   // border is the border size in already pre-computed TeX units dark is the
+   // color for the dark part of the frame light is the color for the light
+   // part of the frame
+
+   Warning("DrawFrame", "not yet implemented");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawPolyLine(Int_t, TPoints *)
+{
+   // Draw a PolyLine
+   //
+   //  Draw a polyline through  the points  xy.
+   //  If NN=1 moves only to point x,y.
+   //  If NN=0 the x,y are  written in the TeX file
+   //     according to the current transformation.
+   //  If NN>0 the line is clipped as a line.
+   //  If NN<0 the line is clipped as a fill area.
+
+   Warning("DrawPolyLine", "not yet implemented");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawPolyLineNDC(Int_t, TPoints *)
+{
+   // Draw a PolyLine in NDC space
+   //
+   //  Draw a polyline through  the points  xy.
+   //  If NN=1 moves only to point x,y.
+   //  If NN=0 the x,y are  written in the TeX file
+   //     according to the current transformation.
+   //  If NN>0 the line is clipped as a line.
+   //  If NN<0 the line is clipped as a fill area.
+
+   Warning("DrawPolyLineNDC", "not yet implemented");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawPolyMarker(Int_t, Float_t *, Float_t *)
+{
+   // Paint PolyMarker
+
+   Warning("DrawPolyMarker", "not yet implemented");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawPolyMarker(Int_t n, Double_t *xw, Double_t *yw)
+{
+   // Paint PolyMarker
+
+   Float_t x, y;
+
+   SetColor(fMarkerColor);
+
+   PrintStr("@");
+   PrintStr("\\foreach \\P in {");
+
+   x = XtoTeX(xw[0]);
+   y = YtoTeX(yw[0]);
+
+   PrintStr("(");
+   WriteReal(x, kFALSE);
+   PrintFast(1,",");
+   WriteReal(y, kFALSE);
+   PrintStr(")");
+
+   for (Int_t i=1;i<n;i++) {
+      x = XtoTeX(xw[i]);
+      y = YtoTeX(yw[i]);
+      PrintFast(2,",(");
+      WriteReal(x, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y, kFALSE);
+      PrintFast(1,")");
+   }
+
+   PrintStr("}{\\draw[mark options={color=c,fill=c},mark size=");
+   PrintStr(Form("%fpt,mark=",8./3.33*fMarkerSize));
+   switch (fMarkerStyle) {
+   case 1 :
+      PrintStr("*");
+      PrintStr(",mark size=1pt");
+      break;
+   case 2 :
+      PrintStr("+");
+      break;
+   case 3 :
+      PrintStr("asterisk");
+      break;
+   case 4 :
+      PrintStr("o");
+      break;
+   case 5 :
+      PrintStr("x");
+      break;
+   case 20 :
+      PrintStr("*");
+      break;
+   case 21 :
+      PrintStr("square*");
+      break;
+   case 22 :
+      PrintStr("triangle*");
+      break;
+   case 23 :
+      PrintStr("triangle*");
+      PrintStr(",mark options={rotate=180}");
+      break;
+   case 24 :
+      PrintStr("o");
+      break;
+   case 25 :
+      PrintStr("square");
+      break;
+   case 26 :
+      PrintStr("triangle");
+      break;
+   case 27 :
+      PrintStr("diamond");
+      break;
+   case 28 :
+      PrintStr("cross");
+      break;
+   case 29 :
+      PrintStr("newstar*");
+      break;
+   case 30 :
+      PrintStr("newstar");
+      break;
+   case 31 :
+      PrintStr("10-pointed star");
+      break;
+   case 32 :
+      PrintStr("triangle");
+      PrintStr(",mark options={rotate=180}");
+      break;
+   case 33 :
+      PrintStr("diamond*");
+      break;
+   case 34 :
+      PrintStr("cross*");
+      break;
+   }
+   PrintStr("] plot coordinates {\\P};}");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawPS(Int_t nn, Double_t *xw, Double_t *yw)
+{
+   // This function defines a path with xw and yw and draw it according the
+   // value of nn:
+   //
+   //  If nn>0 a line is drawn.
+   //  If nn<0 a closed polygon is drawn.
+
+   Int_t  n = TMath::Abs(nn);;
+   Float_t x, y;
+
+   if( n <= 1) {
+      Error("DrawPS", "Two points are needed");
+      return;
+   }
+
+   x = XtoTeX(xw[0]);
+   y = YtoTeX(yw[0]);
+
+   Int_t fillis = fFillStyle/1000;
+   Int_t fillsi = fFillStyle%1000;
+
+   if (nn>0) {
+      SetColor(fLineColor);
+      PrintStr("@");
+      PrintStr("\\draw [c");
+      switch(fLineStyle) {
+      case 1:
+         break;
+      case 2:
+         PrintStr(",dashed");
+         break;
+      case 3:
+         PrintStr(",dotted");
+         break;
+      case 4:
+         PrintStr(",dash pattern=on 2.4pt off 3.2pt on 0.8pt off 3.2pt");
+         break;
+      case 5:
+         PrintStr(",dash pattern=on 4pt off 2.4pt on 0.8pt off 2.4pt");
+         break;
+      case 6:
+         PrintStr(",dash pattern=on 4pt off 2.4pt on 0.8pt off 2.4pt on 0.8pt off 2.4pt on 0.8pt off 2.4pt");
+         break;
+      case 7:
+         PrintStr(",dash pattern=on 4pt off 4pt");
+         break;
+      case 8:
+         PrintStr(",dash pattern=on 4pt off 2.4pt on 0.8pt off 2.4pt on 0.8pt off 2.4pt");
+         break;
+      case 9:
+         PrintStr(",dash pattern=on 16pt off 4pt");
+         break;
+      case 10:
+         PrintStr(",dash pattern=on 16pt off 8pt on 0.8pt off 8pt");
+         break;
+      }
+      if (fLineWidth>1) {
+         PrintStr(",line width=");
+         WriteReal(fLineWidth*0.2, kFALSE);
+      }
+   } else {
+      SetColor(fFillColor);
+      if (fillis==1) {
+         PrintStr("@");
+         PrintStr("\\draw [c, fill=c");
+      } else {
+         PrintStr("\\draw [pattern=");
+         if (fillsi==1)  PrintStr("crosshatch dots");
+         if (fillsi==2)  PrintStr("dots");
+         if (fillsi==4)  PrintStr("north east lines");
+         if (fillsi==5)  PrintStr("north west lines");
+         if (fillsi==6)  PrintStr("vertical lines");
+         if (fillsi==7)  PrintStr("horizontal lines");
+         if (fillsi==10) PrintStr("bricks");
+         if (fillsi==13) PrintStr("crosshatch");
+         PrintStr(", pattern color=c");
+      }
+   }
+
+   PrintStr("] (");
+   WriteReal(x, kFALSE);
+   PrintFast(1,",");
+   WriteReal(y, kFALSE);
+   PrintStr(") -- ");
+
+   for (Int_t i=1;i<n;i++) {
+      x = XtoTeX(xw[i]);
+      y = YtoTeX(yw[i]);
+      PrintFast(1,"(");
+      WriteReal(x, kFALSE);
+      PrintFast(1,",");
+      WriteReal(y, kFALSE);
+      PrintFast(1,")");
+      if (i<n-1) PrintStr(" -- ");
+      else PrintStr(";@");
+   }
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::NewPage()
+{
+   // Start the TeX page. This function starts the tikzpicture environment
+
+   // Compute pad conversion coefficients
+   if (gPad) {
+      Double_t ww   = gPad->GetWw();
+      Double_t wh   = gPad->GetWh();
+      fYsize        = fXsize*wh/ww;
+   } else {
+      fYsize = 27;
+   }
+
+   if(!fBoundingBox) {
+      DefineMarkers();
+      PrintStr("\\begin{tikzpicture}@");
+      /*
+      PrintStr("\\draw[help lines] (0,0) grid (");
+      WriteReal(fXsize, kFALSE);
+      PrintStr(",");
+      WriteReal(fYsize, kFALSE);
+      PrintStr(");@");
+      */
+      fBoundingBox = kTRUE;
+   }
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::Range(Float_t xsize, Float_t ysize)
+{
+   // Set the range for the paper in centimetres
+
+   fXsize = xsize;
+   fYsize = ysize;
+
+   fRange = kTRUE;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetFillColor( Color_t cindex )
+{
+   // Set color index for fill areas
+
+   fFillColor = cindex;
+   if (gStyle->GetFillColor() <= 0) cindex = 0;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetLineColor( Color_t cindex )
+{
+   // Set color index for lines
+
+   fLineColor = cindex;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetLineStyle(Style_t linestyle)
+{
+   // Change the line style
+   //
+   // linestyle = 2 dashed
+   //           = 3 dotted
+   //           = 4 dash-dotted
+   //           = else solid (1 in is used most of the time)
+
+   fLineStyle = linestyle;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetLineWidth(Width_t linewidth)
+{
+   // Set the lines width.
+
+   fLineWidth = linewidth;
+}
+
+//______________________________________________________________________________
+void TTeXDump::SetMarkerSize( Size_t msize)
+{
+   // Set size for markers.
+
+   fMarkerSize = msize;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetMarkerColor( Color_t cindex)
+{
+   // Set color index for markers.
+
+   fMarkerColor = cindex;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetColor(Int_t color)
+{
+   // Set color with its color index
+
+   if (color < 0) color = 0;
+
+   TColor *col = gROOT->GetColor(color);
+   if (col) SetColor(col->GetRed(), col->GetGreen(), col->GetBlue());
+   else     SetColor(1., 1., 1.);
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetColor(Float_t r, Float_t g, Float_t b)
+{
+   // Set color with its R G B components
+   //
+   //  r: % of red in [0,1]
+   //  g: % of green in [0,1]
+   //  b: % of blue in [0,1]
+
+   if (fCurrentRed == r && fCurrentGreen == g && fCurrentBlue == b) return;
+
+   fCurrentRed   = r;
+   fCurrentGreen = g;
+   fCurrentBlue  = b;
+   PrintStr("@");
+   PrintStr("\\definecolor{c}{rgb}{");
+   WriteReal(r, kFALSE);
+   PrintFast(1,",");
+   WriteReal(g, kFALSE);
+   PrintFast(1,",");
+   WriteReal(b, kFALSE);
+   PrintFast(2,"};");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::SetTextColor( Color_t cindex )
+{
+   // Set color index for text
+
+   fTextColor = cindex;
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::Text(Double_t x, Double_t y, const char *chars)
+{
+   // Draw text
+   //
+   // xx: x position of the text
+   // yy: y position of the text
+   // chars: text to be drawn
+
+   Float_t ftsize;
+   if (fXsize < fYsize) {
+      ftsize = fTextSize*fXsize;
+   } else {
+      ftsize = fTextSize*fYsize;
+   }
+   ftsize *= 2.22097;
+
+   TString t(chars);
+   t.ReplaceAll("&","\\&");
+   t.ReplaceAll("<","$<$");
+   t.ReplaceAll(">","$>$");
+
+   Int_t txalh = fTextAlign/10;
+   if (txalh <1) txalh = 1; if (txalh > 3) txalh = 3;
+   Int_t txalv = fTextAlign%10;
+   if (txalv <1) txalv = 1; if (txalv > 3) txalv = 3;
+
+   PrintStr("@");
+   PrintStr("\\draw");
+   if (txalh!=2 || txalv!=2) {
+      PrintStr(" [anchor=");
+      if (txalv==1) PrintStr("base");
+      if (txalv==3) PrintStr("north");
+      if (txalh==1) PrintStr(" west");
+      if (txalh==3) PrintStr(" east");
+      PrintFast(1,"]");
+   }
+   PrintFast(2," (");
+   WriteReal(XtoTeX(x), kFALSE);
+   PrintFast(1,",");
+   WriteReal(YtoTeX(y), kFALSE);
+   PrintStr(") node[scale=");
+   WriteReal(ftsize, kFALSE);
+   PrintStr(", rotate=");
+   WriteReal(fTextAngle, kFALSE);
+   PrintFast(2,"]{");
+   PrintStr(t.Data());
+   PrintFast(2,"};");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::TextNDC(Double_t u, Double_t v, const char *chars)
+{
+   // Write a string of characters in NDC
+
+   Double_t x = gPad->GetX1() + u*(gPad->GetX2() - gPad->GetX1());
+   Double_t y = gPad->GetY1() + v*(gPad->GetY2() - gPad->GetY1());
+   Text(x, y, chars);
+}
+
+
+//______________________________________________________________________________
+Float_t TTeXDump::UtoTeX(Double_t u)
+{
+   // Convert U from NDC coordinate to TeX
+
+   Double_t cm = fXsize*(gPad->GetAbsXlowNDC() + u*gPad->GetAbsWNDC());
+   return cm;
+}
+
+
+//______________________________________________________________________________
+Float_t TTeXDump::VtoTeX(Double_t v)
+{
+   // Convert V from NDC coordinate to TeX
+
+   Double_t cm = fYsize*(gPad->GetAbsYlowNDC() + v*gPad->GetAbsHNDC());
+   return cm;
+}
+
+
+//______________________________________________________________________________
+Float_t TTeXDump::XtoTeX(Double_t x)
+{
+   // Convert X from world coordinate to TeX
+
+   Double_t u = (x - gPad->GetX1())/(gPad->GetX2() - gPad->GetX1());
+   return  UtoTeX(u);
+}
+
+
+//______________________________________________________________________________
+Float_t TTeXDump::YtoTeX(Double_t y)
+{
+   // Convert Y from world coordinate to TeX
+
+   Double_t v = (y - gPad->GetY1())/(gPad->GetY2() - gPad->GetY1());
+   return  VtoTeX(v);
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::CellArrayBegin(Int_t, Int_t, Double_t, Double_t, Double_t,
+                          Double_t)
+{
+   // Begin the Cell Array painting
+
+   Warning("CellArrayBegin", "not yet implemented");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::CellArrayFill(Int_t, Int_t, Int_t)
+{
+   // Paint the Cell Array
+
+   Warning("CellArrayFill", "not yet implemented");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::CellArrayEnd()
+{
+   // End the Cell Array painting
+
+   Warning("CellArrayEnd", "not yet implemented");
+}
+
+
+//______________________________________________________________________________
+void TTeXDump::DrawPS(Int_t, Float_t *, Float_t *)
+{
+   // Not needed in TeX case
+
+   Warning("DrawPS", "not yet implemented");
+}
+
+//______________________________________________________________________________
+void TTeXDump::DefineMarkers()
+{
+   // add additional pgfplotmarks
+
+  // open cross
+  PrintStr("\\pgfdeclareplotmark{cross} {@");
+  PrintStr("\\pgfpathmoveto{\\pgfpoint{-0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathclose@");
+  PrintStr("\\pgfusepathqstroke@");
+  PrintStr("}@");
+
+  // filled cross
+  PrintStr("\\pgfdeclareplotmark{cross*} {@");
+  PrintStr("\\pgfpathmoveto{\\pgfpoint{-0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+1\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{+0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-1.\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{-0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-1.\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfpoint{-0.3\\pgfplotmarksize}{0.3\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathclose@");
+  PrintStr("\\pgfusepathqfillstroke@");
+  PrintStr("}@");
+
+  // open star
+  PrintStr("\\pgfdeclareplotmark{newstar} {@");
+  PrintStr("\\pgfpathmoveto{\\pgfqpoint{0pt}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{44}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{18}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-20}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-54}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-90}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{234}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{198}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{162}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{134}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathclose@");
+  PrintStr("\\pgfusepathqstroke@");
+  PrintStr("}@");
+
+  // filled star
+  PrintStr("\\pgfdeclareplotmark{newstar*} {@");
+  PrintStr("\\pgfpathmoveto{\\pgfqpoint{0pt}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{44}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{18}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-20}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-54}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{-90}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{234}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{198}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{162}{\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathlineto{\\pgfqpointpolar{134}{0.5\\pgfplotmarksize}}@");
+  PrintStr("\\pgfpathclose@");
+  PrintStr("\\pgfusepathqfillstroke@");
+  PrintStr("}@");
+}
\ No newline at end of file
diff --git a/graf2d/qt/src/TQtTimer.cxx b/graf2d/qt/src/TQtTimer.cxx
index 17d1fc1..35a22bd 100644
--- a/graf2d/qt/src/TQtTimer.cxx
+++ b/graf2d/qt/src/TQtTimer.cxx
@@ -27,7 +27,7 @@ TQtTimer *TQtTimer::fgQTimer=0;
 void TQtTimer::AwakeRootEvent(){
      // proceess the ROOT events inside of Qt event loop
      gSystem->DispatchOneEvent(kFALSE);
-     start(300);
+     start(5);
 }
 //______________________________________________________________________________
 TQtTimer * TQtTimer::Create(QObject *parent)
diff --git a/graf3d/eve/inc/TEveBrowser.h b/graf3d/eve/inc/TEveBrowser.h
index 1a0a72e..723398c 100644
--- a/graf3d/eve/inc/TEveBrowser.h
+++ b/graf3d/eve/inc/TEveBrowser.h
@@ -149,8 +149,9 @@ public:
 
    void InitPlugins(Option_t *opt="FI");
 
-   TGFileBrowser* MakeFileBrowser();
-   TGFileBrowser* GetFileBrowser() const { return fFileBrowser; }
+   TGFileBrowser* MakeFileBrowser(Bool_t make_default=kFALSE);
+   TGFileBrowser* GetFileBrowser() const;
+   void           SetFileBrowser(TGFileBrowser* b);
 
    void EveMenu(Int_t id);
 
diff --git a/graf3d/eve/src/TEveBrowser.cxx b/graf3d/eve/src/TEveBrowser.cxx
index 6b6feab..6ba57a8 100644
--- a/graf3d/eve/src/TEveBrowser.cxx
+++ b/graf3d/eve/src/TEveBrowser.cxx
@@ -762,10 +762,12 @@ void TEveBrowser::InitPlugins(Option_t *opt)
 }
 
 //______________________________________________________________________________
-TGFileBrowser* TEveBrowser::MakeFileBrowser()
+TGFileBrowser* TEveBrowser::MakeFileBrowser(Bool_t make_default)
 {
-   // Create a file-browser. Caller should provide
-   // Start/StopEmbedding() calls and populate the new browser.
+   // Create a file-browser. Caller should provide Start/StopEmbedding() calls
+   // and populate the new browser.
+   // If flag make_default is kTRUE, the default file-browser is set to the
+   // newly created browser.
 
    TBrowserImp    imp;
    TBrowser      *tb = new TBrowser("Pipi", "Strel", &imp);
@@ -777,10 +779,30 @@ TGFileBrowser* TEveBrowser::MakeFileBrowser()
    // This guy is never used and stays in list-of-cleanups after destruction.
    // So let's just delete it now.
    delete tb->GetContextMenu();
+
+   if (make_default)
+      fFileBrowser = fb;
+
    return fb;
 }
 
 //______________________________________________________________________________
+TGFileBrowser* TEveBrowser::GetFileBrowser() const
+{
+  // Returns the default file-browser.
+
+  return fFileBrowser;
+}
+
+//______________________________________________________________________________
+void TEveBrowser::SetFileBrowser(TGFileBrowser* b)
+{
+  // Set the default file browser.
+
+  fFileBrowser = b;
+}
+
+//______________________________________________________________________________
 void TEveBrowser::ReallyDelete()
 {
    // Override from TRootBrowser. We need to be more brutal as fBrowser is
diff --git a/graf3d/eve/src/TEveTrackPropagator.cxx b/graf3d/eve/src/TEveTrackPropagator.cxx
index 8a03279..bf31399 100644
--- a/graf3d/eve/src/TEveTrackPropagator.cxx
+++ b/graf3d/eve/src/TEveTrackPropagator.cxx
@@ -905,15 +905,14 @@ Bool_t TEveTrackPropagator::LineIntersectPlane(const TEveVectorD& p,
    // the line.
 
    TEveVectorD pos(fV.fX, fV.fY, fV.fZ);
-   TEveVectorD delta = pos - point;
+   TEveVectorD delta = point - pos;
 
-   Double_t d = delta.Dot(normal);
-   if (d == 0) {
-      itsect = pos;
-      return kTRUE;
+   Double_t pn = p.Dot(normal);
+   if (pn == 0)
+   {
+     return kFALSE;
    }
-
-   Double_t t = (p.Dot(normal)) / d;
+   Double_t t = delta.Dot(normal) / pn;
    if (t < 0) {
       return kFALSE;
    } else {
diff --git a/gui/gui/src/HelpText.cxx b/gui/gui/src/HelpText.cxx
index 8634c56..5485254 100644
--- a/gui/gui/src/HelpText.cxx
+++ b/gui/gui/src/HelpText.cxx
@@ -254,6 +254,7 @@ Each canvas has a menu bar with the following items:\n\
         <name.eps >   makes a Postscript encapsulated file\n\
         <name.pdf >   makes a PDF file\n\
         <name.svg >   makes a SVG file\n\
+        <name.tex >   makes a TeX file\n\
         <name.gif >   makes a GIF file\n\
         <name.C   >   generates a C++ macro to reproduce the canvas\n\
         <name.root>   saves canvas objects in a Root file\n\
diff --git a/gui/gui/src/TGFontDialog.cxx b/gui/gui/src/TGFontDialog.cxx
index a86e8a4..df21f9d 100644
--- a/gui/gui/src/TGFontDialog.cxx
+++ b/gui/gui/src/TGFontDialog.cxx
@@ -806,15 +806,11 @@ void TGFontDialog::GetFontName()
       if (!fLabelFont) {
          // should not happen
          fLName = oldFont;
-         goto out;
       }
-
-      if (fSample) {
+      else if (fSample) {
          fSample->SetTextFont(fLabelFont);
       }
    }
-
-out:
    Int_t oldAlign = fTextAlign;
 
    Int_t idx = fTextAligns->GetSelected();
diff --git a/gui/gui/src/TGListTree.cxx b/gui/gui/src/TGListTree.cxx
index 2897f2e..5d34d31 100644
--- a/gui/gui/src/TGListTree.cxx
+++ b/gui/gui/src/TGListTree.cxx
@@ -2338,7 +2338,6 @@ TGListTreeItem *TGListTree::FindItemByPathname(const char *path)
    TGListTreeItem *diritem = 0;
    TString fulldir;
 
-start:
    while (1) {
       while (*p && *p == '/') p++;
       if (!*p) break;
@@ -2361,7 +2360,7 @@ start:
             if (!s || !strlen(s)) return diritem;
             p = ++s;
             item = diritem;
-            goto start;
+            continue;
          }
       }
 
diff --git a/gui/gui/src/TRootBrowserLite.cxx b/gui/gui/src/TRootBrowserLite.cxx
index ed4b47e..b4febfa 100644
--- a/gui/gui/src/TRootBrowserLite.cxx
+++ b/gui/gui/src/TRootBrowserLite.cxx
@@ -661,7 +661,6 @@ void TRootIconBox::AddObjItem(const char *name, TObject *obj, TClass *cl)
 
       fi->SetUserData(obj);
       AddItem(fi);
-      fTotal++;
       return;
    }
 
diff --git a/gui/gui/src/TRootCanvas.cxx b/gui/gui/src/TRootCanvas.cxx
index 195b973..d32c7ad 100644
--- a/gui/gui/src/TRootCanvas.cxx
+++ b/gui/gui/src/TRootCanvas.cxx
@@ -163,6 +163,7 @@ static const char *gSaveAsTypes[] = { "PostScript",   "*.ps",
                                       "Encapsulated PostScript", "*.eps",
                                       "PDF",          "*.pdf",
                                       "SVG",          "*.svg",
+                                      "TeX",          "*.tex",
                                       "GIF",          "*.gif",
                                       "ROOT macros",  "*.C",
                                       "ROOT files",   "*.root",
@@ -841,6 +842,7 @@ again:
                             fn.EndsWith(".eps")  ||
                             fn.EndsWith(".pdf")  ||
                             fn.EndsWith(".svg")  ||
+                            fn.EndsWith(".tex")  ||
                             fn.EndsWith(".gif")  ||
                             fn.EndsWith(".xml")  ||
                             fn.EndsWith(".xpm")  ||
diff --git a/gui/gui/src/TRootContextMenu.cxx b/gui/gui/src/TRootContextMenu.cxx
index 229ea59..4419ee1 100644
--- a/gui/gui/src/TRootContextMenu.cxx
+++ b/gui/gui/src/TRootContextMenu.cxx
@@ -350,6 +350,7 @@ void TRootContextMenu::CreateMenu(TObject *object)
             break;
          case TClassMenuItem::kPopupUserFunction:
             {
+               const char* menuItemTitle = menuItem->GetTitle();
                if (menuItem->IsToggle()) {
                   TMethod* method =
                         object->IsA()->GetMethodWithPrototype(menuItem->GetFunctionName(),menuItem->GetArgs());
@@ -359,11 +360,11 @@ void TRootContextMenu::CreateMenu(TObject *object)
                      t->SetOnValue(1);
                      fTrash->Add(t);
 
-                     AddEntry(method->GetName(), toggle++, t);
+                     if (strlen(menuItemTitle)==0) menuItemTitle = method->GetName();
+                     AddEntry(menuItemTitle, toggle++, t);
                      if (t->GetState()) CheckEntry(toggle-1);
                   }
                } else {
-                  const char* menuItemTitle = menuItem->GetTitle();
                   if (strlen(menuItemTitle)==0) menuItemTitle = menuItem->GetFunctionName();
                   AddEntry(menuItemTitle,userfunction++,menuItem);
                }
diff --git a/gui/sessionviewer/inc/TProofProgressLog.h b/gui/sessionviewer/inc/TProofProgressLog.h
index c52dc6c..235104c 100644
--- a/gui/sessionviewer/inc/TProofProgressLog.h
+++ b/gui/sessionviewer/inc/TProofProgressLog.h
@@ -1,4 +1,4 @@
-// @(#)root/sessionviewer:$Id$
+// @(#)root/sessionviewer:$Id: c52dc6cb225c25e34d388329d41570a484d98ce0 $
 // Author: G Ganis, Aug 2005
 
 /*************************************************************************
@@ -39,7 +39,7 @@ class TGListBox;
 class TGSplitButton;
 class TGVerticalFrame;
 class TGCheckButton;
-
+class TGLabel;
 
 class TProofProgressLog : public TGTransientFrame {
 
@@ -68,6 +68,9 @@ private:
    TGCheckButton        *fRawLines;  // display raw lines button
    TGSplitButton        *fAllWorkers; // display all workers button
    TGVerticalFrame      *fVworkers;  // Vertical frame
+   TGLabel              *fGrepLabel;  // label indicating if grepping or piping
+   TGCheckButton        *fGrepCheckCmd;  // checkbox active if piping
+   TGCheckButton        *fGrepCheckInv;  // checkbox active if inverting
 
    Bool_t                fFullText;    // 0 - when grep was called
    Int_t                 fTextType;   // Type of retrieval
@@ -93,6 +96,7 @@ public:
    void   Popup();
    void   SaveToFile();
    void   NoLineEntry();
+   void   SetGrepView();
    void   Select(Int_t id, Bool_t all = kTRUE);
 
    void   SetUrl(const char *url) { fSessionUrl = url; }
diff --git a/gui/sessionviewer/src/TProofProgressLog.cxx b/gui/sessionviewer/src/TProofProgressLog.cxx
index c4b9140..fbac457 100644
--- a/gui/sessionviewer/src/TProofProgressLog.cxx
+++ b/gui/sessionviewer/src/TProofProgressLog.cxx
@@ -10,6 +10,7 @@
  *************************************************************************/
 
 #include "TError.h"
+#include "TPRegexp.h"
 #include "TGFrame.h"
 #include "TGTextView.h"
 #include "TGScrollBar.h"
@@ -154,7 +155,7 @@ void TProofProgressLog::Init(Int_t w, Int_t h)
    hflogbox->AddFrame(fSave, new TGLayoutHints(kLHintsCenterY | kLHintsRight, 4, 0, 0, 0));
    fFileName = new TGTextEntry(hflogbox);
    fFileName->SetText("<session-tag>.log");
-   hflogbox->AddFrame(fFileName, new TGLayoutHints(kLHintsCenterY | kLHintsRight));
+   hflogbox->AddFrame(fFileName, new TGLayoutHints(kLHintsCenterY | kLHintsRight | kLHintsExpandX));
    TGLabel *label10 = new TGLabel(hflogbox, "Save to a file:");
    hflogbox->AddFrame(label10, new TGLayoutHints(kLHintsCenterY | kLHintsRight, 50, 2, 2, 2));
 
@@ -193,20 +194,48 @@ void TProofProgressLog::Init(Int_t w, Int_t h)
    vlines->AddFrame(vlines_buttons, new TGLayoutHints(kLHintsCenterY));
    hflogbox->AddFrame(vlines, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 2, 2, 2, 2));
 
-   //Grep controls
-   TGLabel *label4 = new TGLabel(hflogbox, "Grep for:");
-   hflogbox->AddFrame(label4, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 5, 2, 2, 2));
-   fGrepText = new TGTextEntry(hflogbox);
-   hflogbox->AddFrame(fGrepText, new TGLayoutHints(kLHintsCenterY | kLHintsLeft));
+   //
+   // Lowest line, with filter (grep or cmd pipe) controls
+   //
 
-   fGrepButton = new TGTextButton(hflogbox, "Grep");
+   TGHorizontalFrame *hfgrepbox = new TGHorizontalFrame(vtextbox, 550, 20);
+
+   // Grep/pipe label, textbox and button
+   fGrepLabel = new TGLabel(hfgrepbox, "");
+   hfgrepbox->AddFrame(fGrepLabel, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 2, 2, 2, 2));
+   fGrepText = new TGTextEntry(hfgrepbox);
+   {
+      TGDimension dim = fGrepText->GetDefaultSize();
+      fGrepText->SetDefaultSize(400, dim.fHeight);
+   }
+   hfgrepbox->AddFrame(fGrepText, new TGLayoutHints( kLHintsCenterY | kLHintsLeft | kLHintsExpandX));
+   fGrepButton = new TGTextButton(hfgrepbox, "Filter");
    fGrepButton->Connect("Clicked()", "TProofProgressLog", this, "DoLog(=kTRUE)");
-   hflogbox->AddFrame(fGrepButton, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 4, 0, 0, 0));
+   hfgrepbox->AddFrame(fGrepButton, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 4, 10, 0, 0));  // l r t b
+
+   // Checkbox for inverting selection or giving a pipe command
+   fGrepCheckInv = new TGCheckButton(hfgrepbox, "invert match");
+   fGrepCheckInv->Connect("Clicked()", "TProofProgressLog", this, "SetGrepView()");
+   hfgrepbox->AddFrame(fGrepCheckInv, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 2, 2, 2, 2));
+
+   fGrepCheckCmd = new TGCheckButton(hfgrepbox, "is a pipe command");
+   fGrepCheckCmd->Connect("Clicked()", "TProofProgressLog", this, "SetGrepView()");
+   hfgrepbox->AddFrame(fGrepCheckCmd, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 2, 2, 2, 2));
 
-   vtextbox->AddFrame(hflogbox, new TGLayoutHints(kLHintsBottom | kLHintsLeft | kLHintsExpandX, 2, 2, 2, 2));
+   // fRawLines->SetToolTipText("Retrieve all type of lines, service messages included");
+   // fRawLines->SetState(kButtonUp);
+   // vlines_buttons->AddFrame(fRawLines, new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 2, 2, 2, 2));
+
+   //
+   // Add frames to the global picture
+   //
+
+   vtextbox->AddFrame(hflogbox, new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 2, 2, 2, 2));
+   vtextbox->AddFrame(hfgrepbox, new TGLayoutHints(kLHintsBottom | kLHintsLeft | kLHintsExpandX, 2, 2, 2, 2));
    htotal->AddFrame(vtextbox, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY | kLHintsRight, 3, 3, 3, 3));
    AddFrame(htotal, new TGLayoutHints(kLHintsExpandX |
                                         kLHintsExpandY, 3, 3, 3, 3));
+   SetGrepView();
    MapSubwindows();
    Resize();
    CenterOnParent();
@@ -356,7 +385,8 @@ void TProofProgressLog::BuildLogList(Bool_t create)
 //______________________________________________________________________________
 void TProofProgressLog::DoLog(Bool_t grep)
 {
-   // Display the logs
+   // Display logs. 'grep' is set to kTRUE if it is invoked by pressing the
+   // 'Filter' button.
 
    Clear();
 
@@ -366,6 +396,16 @@ void TProofProgressLog::DoLog(Bool_t grep)
    }
 
    TString greptext = fGrepText->GetText();
+   greptext.Remove(TString::kBoth, ' ');
+   if (greptext.IsNull()) {
+      grep = kFALSE;
+   }
+   else if (!fGrepCheckCmd->IsOn()) {
+      // Not a command: sanitize string
+      TPMERegexp san("(^|[^\\\\])([^a-zA-Z0-9_=\\\\/.-])");
+      while (san.Substitute(greptext, "$1\\$2") > 0) { }
+   }
+
    Int_t from, to;
    if (fAllLines->IsOn()){
       from = 0;
@@ -389,9 +429,18 @@ void TProofProgressLog::DoLog(Bool_t grep)
       }
    }
 
+   // Pipe command for filtering
+   TString pipeCommand;
+
+   // Filter out SvcMsg
+   if (!fRawLines->IsOn()) {
+      pipeCommand = "grep -v \"| SvcMsg\"";
+   }
+
    // Default is not retrieving
    Bool_t retrieve = kFALSE;
    if (!grep) {
+      // Not invoked via 'Filter' button
       if (!fFullText ||
           ((fTextType != kRaw && fRawLines->IsOn())   ||
            (fTextType != kStd && !fRawLines->IsOn())) ||
@@ -408,6 +457,21 @@ void TProofProgressLog::DoLog(Bool_t grep)
    } else {
       retrieve = kTRUE;
       fTextType = kGrep;
+
+      if (!pipeCommand.IsNull())
+         pipeCommand.Append('|');
+
+      if (fGrepCheckCmd->IsOn()) {
+         pipeCommand.Append(greptext);
+      }
+      else {
+         pipeCommand.Append("grep ");
+         if (fGrepCheckInv->IsOn())
+            pipeCommand.Append("-v ");
+         pipeCommand.Append("-- ");
+         pipeCommand.Append(greptext);  // sanitized
+      }
+
       if (fDialog && fDialog->fStatus != TProofProgressDialog::kRunning)
          fFullText = kTRUE;
    }
@@ -428,12 +492,17 @@ void TProofProgressLog::DoLog(Bool_t grep)
          Int_t is = ord.Index(" ");
          if (is != kNPOS) ord.Remove(is);
          if (retrieve || !selentry->TestBit(kLogElemFilled)) {
-            if (fTextType == kGrep) {
-               fProofLog->Retrieve(ord.Data(), TProofLog::kGrep, 0, greptext.Data());
-            } else if (fTextType == kRaw) {
-               fProofLog->Retrieve(ord.Data(), TProofLog::kTrailing, 0, 0);
-            } else {
-               fProofLog->Retrieve(ord.Data(), TProofLog::kGrep, 0, "-v \"| SvcMsg\"");
+            pipeCommand.Prepend('|');
+            if (fTextType == kRaw) {
+               if (gDebug >= 2)
+                  Info("DoLog", "Retrieving unfiltered log for %s", ord.Data());
+               fProofLog->Retrieve(ord.Data(), TProofLog::kTrailing, 0, 0);               
+            }
+            else {
+               if (gDebug >= 2)
+                  Info("DoLog", "Retrieving log for %s filtered with %s",
+                     ord.Data(), pipeCommand.Data());
+               fProofLog->Retrieve(ord.Data(), TProofLog::kGrep, 0, pipeCommand.Data());
             }
             selentry->SetBit(kLogElemFilled);
          }
@@ -497,6 +566,35 @@ void TProofProgressLog::SaveToFile()
 }
 
 //______________________________________________________________________________
+void TProofProgressLog::SetGrepView()
+{
+   // Sets the view of grep filters according to the value of checkboxes
+
+   if (fGrepCheckCmd->IsOn()) {
+      fGrepLabel->SetText("Pipe log through command:");
+      fGrepCheckInv->SetDisabledAndSelected(kFALSE);
+   }
+   else {
+      fGrepLabel->SetText("Grep:");
+      Bool_t u = fGrepCheckInv->IsOn();
+      fGrepCheckInv->SetEnabled(kTRUE);
+      if (u) {
+         fGrepLabel->SetText("Show lines not matching:");
+         fGrepCheckInv->SetState(kButtonDown);
+      }
+      else {
+         fGrepLabel->SetText("Show lines matching:");
+         fGrepCheckInv->SetState(kButtonUp);
+      }
+   }
+
+   // Ugly but necessary const_cast
+   TGFrame *frame = dynamic_cast<TGFrame *>( const_cast<TGWindow *>(fGrepLabel->GetParent()) );
+   if (frame) frame->Layout();
+
+}
+
+//______________________________________________________________________________
 void TProofProgressLog::NoLineEntry()
 {
    //Enable/disable the line number entry
diff --git a/hist/hist/inc/TGraph2D.h b/hist/hist/inc/TGraph2D.h
index ea81319..3234ec5 100644
--- a/hist/hist/inc/TGraph2D.h
+++ b/hist/hist/inc/TGraph2D.h
@@ -113,6 +113,8 @@ public:
    virtual Double_t      GetErrorY(Int_t bin) const;
    virtual Double_t      GetErrorZ(Int_t bin) const;
    Double_t              GetMargin() const {return fMargin;}
+   Double_t              GetMaximum() const {return fMaximum;};
+   Double_t              GetMinimum() const {return fMinimum;};
    TAxis                *GetXaxis() const ;
    TAxis                *GetYaxis() const ;
    TAxis                *GetZaxis() const ;
diff --git a/hist/hist/inc/TH2Poly.h b/hist/hist/inc/TH2Poly.h
index 7f19b2e..4f948c2 100644
--- a/hist/hist/inc/TH2Poly.h
+++ b/hist/hist/inc/TH2Poly.h
@@ -116,6 +116,7 @@ public:
    Double_t     Integral(Int_t, Int_t, const Option_t*) const{return 0;}                             //MayNotUse
    Double_t     Integral(Int_t, Int_t, Int_t, Int_t, const Option_t*) const{return 0;}               //MayNotUse
    Double_t     Integral(Int_t, Int_t, Int_t, Int_t, Int_t, Int_t, const Option_t*) const{return 0;} //MayNotUse
+   Long64_t     Merge(TCollection *);
    void         Reset(Option_t *option);
    void         SavePrimitive(ostream& out, Option_t* option = "");
    void         SetBinContent(Int_t bin, Double_t content);
diff --git a/hist/hist/inc/TMultiGraph.h b/hist/hist/inc/TMultiGraph.h
index 8fd2628..b0fe954 100644
--- a/hist/hist/inc/TMultiGraph.h
+++ b/hist/hist/inc/TMultiGraph.h
@@ -56,8 +56,8 @@ public:
    virtual void      Browse(TBrowser *b);
    virtual Int_t     DistancetoPrimitive(Int_t px, Int_t py);
    virtual void      Draw(Option_t *chopt="");
-   virtual TFitResultPtr Fit(const char *formula ,Option_t *option="" ,Option_t *goption="", Axis_t xmin=0, Axis_t xmax=0); 
-   virtual TFitResultPtr Fit(TF1 *f1 ,Option_t *option="" ,Option_t *goption="", Axis_t rxmin=0, Axis_t rxmax=0); 
+   virtual TFitResultPtr Fit(const char *formula ,Option_t *option="" ,Option_t *goption="", Axis_t xmin=0, Axis_t xmax=0);
+   virtual TFitResultPtr Fit(TF1 *f1 ,Option_t *option="" ,Option_t *goption="", Axis_t rxmin=0, Axis_t rxmax=0);
    virtual void      FitPanel(); // *MENU*
    virtual Option_t *GetGraphDrawOption(const TGraph *gr) const;
    virtual void      LeastSquareLinearFit(Int_t ndata, Double_t &a0, Double_t &a1, Int_t &ifail, Double_t xmin, Double_t xmax);
@@ -70,7 +70,7 @@ public:
    TF1              *GetFunction(const char *name) const;
    TList            *GetListOfGraphs() const { return fGraphs; }
    TList            *GetListOfFunctions();  // non const method (create list if empty)
-   const TList      *GetListOfFunctions() const { return fFunctions; } 
+   const TList      *GetListOfFunctions() const { return fFunctions; }
    TAxis            *GetXaxis() const;
    TAxis            *GetYaxis() const;
    virtual void      Paint(Option_t *chopt="");
@@ -80,7 +80,7 @@ public:
    virtual void      SavePrimitive(ostream &out, Option_t *option = "");
    virtual void      SetMaximum(Double_t maximum=-1111);
    virtual void      SetMinimum(Double_t minimum=-1111);
-  
+
    ClassDef(TMultiGraph,2)  //A collection of TGraph objects
 };
 
diff --git a/hist/hist/src/TAxis.cxx b/hist/hist/src/TAxis.cxx
index 6391a34..0e7b32a 100644
--- a/hist/hist/src/TAxis.cxx
+++ b/hist/hist/src/TAxis.cxx
@@ -623,7 +623,9 @@ void TAxis::SaveAttributes(std::ostream &out, const char *name, const char *subn
 
    char quote = '"';
    if (strlen(GetTitle())) {
-      out<<"   "<<name<<subname<<"->SetTitle("<<quote<<GetTitle()<<quote<<");"<<std::endl;
+      TString t(GetTitle());
+      t.ReplaceAll("\\","\\\\");
+      out<<"   "<<name<<subname<<"->SetTitle("<<quote<<t.Data()<<quote<<");"<<std::endl;
    }
    if (fTimeDisplay) {
       out<<"   "<<name<<subname<<"->SetTimeDisplay(1);"<<std::endl;
@@ -1076,7 +1078,7 @@ void TAxis::UnZoom()
 {
    // Reset first & last bin to the full range
 
-
+   if (!gPad) return;
    gPad->SetView();
 
    //unzoom object owning this axis
diff --git a/hist/hist/src/TFormula.cxx b/hist/hist/src/TFormula.cxx
index b11ffa7..57dd944 100644
--- a/hist/hist/src/TFormula.cxx
+++ b/hist/hist/src/TFormula.cxx
@@ -2909,24 +2909,16 @@ Double_t TFormula::EvalParOld(const Double_t *x, const Double_t *uparams)
             TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
 
             // Set the arguments
-            TString args;
+            method->ResetParam();
             if (nargs) {
                UInt_t argloc = pos-nargs;
                for(j=0;j<nargs;j++,argloc++,pos--) {
-                  if (TMath::IsNaN(tab[argloc])) {
-                     // TString would add 'nan' this is not what we want
-                     // so let's do somethign else
-                     args += "(double)(0x8000000000000)";
-                  } else {
-                     args += tab[argloc];
-                  }
-                  args += ',';
+                  method->SetParam(tab[argloc]);
                }
-               args.Remove(args.Length()-1);
             }
             pos++;
             Double_t ret;
-            method->Execute(args,ret);
+            method->Execute(ret);
             tab[pos-1] = ret; // check for the correct conversion!
 
             continue;
@@ -4373,24 +4365,16 @@ Double_t TFormula::EvalParFast(const Double_t *x, const Double_t *uparams)
             TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
 
             // Set the arguments
-            TString args;
+            method->ResetParam();
             if (nargs) {
                UInt_t argloc = pos-nargs;
                for(j=0;j<nargs;j++,argloc++,pos--) {
-                  if (TMath::IsNaN(tab[argloc])) {
-                     // TString would add 'nan' this is not what we want
-                     // so let's do somethign else
-                     args += "(double)(0x8000000000000)";
-                  } else {
-                     args += tab[argloc];
-                  }
-                  args += ',';
+                  method->SetParam(tab[argloc]);
                }
-               args.Remove(args.Length()-1);
             }
             pos++;
             Double_t ret;
-            method->Execute(args,ret);
+            method->Execute(ret);
             tab[pos-1] = ret; // check for the correct conversion!
 
             continue;
diff --git a/hist/hist/src/TGraph.cxx b/hist/hist/src/TGraph.cxx
index 5d57f6b..fbacf91 100644
--- a/hist/hist/src/TGraph.cxx
+++ b/hist/hist/src/TGraph.cxx
@@ -804,6 +804,15 @@ void TGraph::Draw(Option_t *option)
       if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
       if (opt.Contains("a")) gPad->Clear();
    }
+   // If no option is specified, it is defined as "alp" in case there
+   // no current pad or if the current pad as no axis defined.
+   if (!strlen(option)) {
+      if (gPad) {
+         if (!gPad->GetListOfPrimitives()->FindObject("TFrame")) opt = "alp";
+      } else {
+         opt = "alp";
+      }
+   }
    AppendPad(opt);
 }
 
diff --git a/hist/hist/src/TGraph2D.cxx b/hist/hist/src/TGraph2D.cxx
index 2f5964f..5b9e9a2 100644
--- a/hist/hist/src/TGraph2D.cxx
+++ b/hist/hist/src/TGraph2D.cxx
@@ -614,7 +614,7 @@ void TGraph2D::Clear(Option_t * /*option = "" */)
    delete [] fZ;
    fZ = 0;
    fSize = fNpoints = 0;
-   if (fHistogram) {
+   if (fHistogram && !fUserHisto) {
       delete fHistogram;
       fHistogram = 0;
    }
diff --git a/hist/hist/src/TGraphDelaunay.cxx b/hist/hist/src/TGraphDelaunay.cxx
index 8c867c9..3cc2a5c 100644
--- a/hist/hist/src/TGraphDelaunay.cxx
+++ b/hist/hist/src/TGraphDelaunay.cxx
@@ -252,7 +252,7 @@ L1:
    if (swap) goto L1;
 
    // expand the triangles storage if needed
-   if (fNdt> fTriedSize) {
+   if (fNdt>=fTriedSize) {
       Int_t newN   = 2*fTriedSize;
       Int_t *savep = new Int_t [newN];
       Int_t *saven = new Int_t [newN];
diff --git a/hist/hist/src/TH1.cxx b/hist/hist/src/TH1.cxx
index b1a3552..e72b0d4 100644
--- a/hist/hist/src/TH1.cxx
+++ b/hist/hist/src/TH1.cxx
@@ -6684,9 +6684,10 @@ void TH1::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
    }
    const char *hname = histName.Data();
 
-
+   TString t(GetTitle());
+   t.ReplaceAll("\\","\\\\");
    out << hname << " = new " << ClassName() << "(" << quote
-      << hname << quote << "," << quote<< GetTitle() << quote
+      << hname << quote << "," << quote<< t.Data() << quote
       << "," << GetXaxis()->GetNbins();
    if (nonEqiX)
       out << ", "<<sxaxis;
diff --git a/hist/hist/src/TH2Poly.cxx b/hist/hist/src/TH2Poly.cxx
index aa19bd2..aa3d135 100644
--- a/hist/hist/src/TH2Poly.cxx
+++ b/hist/hist/src/TH2Poly.cxx
@@ -1133,6 +1133,14 @@ Bool_t TH2Poly::IsIntersectingPolygon(Int_t bn, Double_t *x, Double_t *y,
 
 
 //______________________________________________________________________________
+Long64_t TH2Poly::Merge(TCollection *)
+{
+   Error("Merge","Cannot merge TH2Poly");
+   return 0;
+}
+
+
+//______________________________________________________________________________
 void TH2Poly::SavePrimitive(ostream &out, Option_t *option)
 {
    // Save primitive as a C++ statement(s) on output stream out
diff --git a/hist/hist/src/TH3.cxx b/hist/hist/src/TH3.cxx
index 247bffd..0c9f17a 100644
--- a/hist/hist/src/TH3.cxx
+++ b/hist/hist/src/TH3.cxx
@@ -1842,7 +1842,7 @@ TH1D *TH3::ProjectionZ(const char *name, Int_t ixmin, Int_t ixmax, Int_t iymin,
    //*-*      ====================================================
    //
    //   The projection is always of the type TH1D.
-   //   The projection is made from the cells along the X axis
+   //   The projection is made from the cells along the Z axis
    //   ranging from ixmin to ixmax and iymin to iymax included.
    //   By default, bins 1 to nx and 1 to ny  are included
    //   By setting ixmin=1 and/or ixmax=NbinsX the underflow and/or overflow in X will be excluded
diff --git a/hist/hist/src/TMultiGraph.cxx b/hist/hist/src/TMultiGraph.cxx
index e776af1..367f939 100644
--- a/hist/hist/src/TMultiGraph.cxx
+++ b/hist/hist/src/TMultiGraph.cxx
@@ -62,24 +62,24 @@ Example:
      mg->Add(gr2,"cp");
      mg->Draw("a");
 </pre>
-A special option <tt>3D</tt> allows to draw the graphs in a 3D space. See the 
+A special option <tt>3D</tt> allows to draw the graphs in a 3D space. See the
 following example:
 End_Html
 Begin_Macro(source)
 {
    c0 = new TCanvas("c1","multigraph L3",200,10,700,500);
    c0->SetFrameFillColor(30);
- 
+
    TMultiGraph *mg = new TMultiGraph();
- 
+
    TGraph *gr1 = new TGraph(); gr1->SetLineColor(kBlue);
    TGraph *gr2 = new TGraph(); gr2->SetLineColor(kRed);
    TGraph *gr3 = new TGraph(); gr3->SetLineColor(kGreen);
    TGraph *gr4 = new TGraph(); gr4->SetLineColor(kOrange);
- 
+
    Double_t dx = 6.28/100;
    Double_t x  = -3.14;
- 
+
    for (int i=0; i<=100; i++) {
       x = x+dx;
       gr1->SetPoint(i,x,2.*TMath::Sin(x));
@@ -87,12 +87,12 @@ Begin_Macro(source)
       gr3->SetPoint(i,x,TMath::Cos(x*x));
       gr4->SetPoint(i,x,TMath::Cos(x*x*x));
    }
- 
+
    mg->Add(gr4); gr4->SetTitle("Cos(x*x*x)"); gr4->SetLineWidth(3);
    mg->Add(gr3); gr3->SetTitle("Cos(x*x)")  ; gr3->SetLineWidth(3);
    mg->Add(gr2); gr2->SetTitle("Cos(x)")    ; gr2->SetLineWidth(3);
    mg->Add(gr1); gr1->SetTitle("2*Sin(x)")  ; gr1->SetLineWidth(3);
- 
+
    mg->Draw("a fb l3d");
    return c0;
 }
@@ -276,7 +276,7 @@ End_Html */
 //______________________________________________________________________________
 TMultiGraph::TMultiGraph(): TNamed()
 {
-   // TMultiGraph default constructor
+   // TMultiGraph default constructor.
 
    fGraphs    = 0;
    fFunctions = 0;
@@ -290,7 +290,7 @@ TMultiGraph::TMultiGraph(): TNamed()
 TMultiGraph::TMultiGraph(const char *name, const char *title)
        : TNamed(name,title)
 {
-   // Constructor with name and title
+   // Constructor with name and title.
 
    fGraphs    = 0;
    fFunctions = 0;
@@ -309,16 +309,16 @@ TMultiGraph::TMultiGraph(const TMultiGraph& mg) :
   fMaximum(mg.fMaximum),
   fMinimum(mg.fMinimum)
 {
-   // Copy constructor
+   // Copy constructor.
 }
 
 
 //______________________________________________________________________________
 TMultiGraph& TMultiGraph::operator=(const TMultiGraph& mg)
 {
-   // Assignement operator
-   
-   if(this!=&mg) {
+   // Assignement operator.
+
+   if (this!=&mg) {
       TNamed::operator=(mg);
       fGraphs=mg.fGraphs;
       fFunctions=mg.fFunctions;
@@ -333,7 +333,7 @@ TMultiGraph& TMultiGraph::operator=(const TMultiGraph& mg)
 //______________________________________________________________________________
 TMultiGraph::~TMultiGraph()
 {
-   // TMultiGraph destructor
+   // TMultiGraph destructor.
 
    if (!fGraphs) return;
    TGraph *g;
@@ -354,7 +354,7 @@ TMultiGraph::~TMultiGraph()
       //drawing modes
       TObject *obj;
       while ((obj  = fFunctions->First())) {
-         while(fFunctions->Remove(obj)) { }
+         while (fFunctions->Remove(obj)) { }
          delete obj;
       }
       delete fFunctions;
@@ -380,18 +380,24 @@ void TMultiGraph::Add(TGraph *graph, Option_t *chopt)
 void TMultiGraph::Add(TMultiGraph *multigraph, Option_t *chopt)
 {
    // Add all the graphs in "multigraph" to the list of graphs.
+   // If "chopt" is defined all the graphs in "multigraph" will be added with
+   // the "chopt" option.
+   // If "chopt" is undefined each graph will be added with the option it had
+   // in "multigraph".
 
    TList *graphlist = multigraph->GetListOfGraphs();
    if (!graphlist) return;
 
    if (!fGraphs) fGraphs = new TList();
 
-   TGraph *gr;
-   gr = (TGraph*)graphlist->First();
-   fGraphs->Add(gr,chopt);
-   for(Int_t i = 1; i < graphlist->GetSize(); i++){
-      gr = (TGraph*)graphlist->After(gr);
-      fGraphs->Add(gr,chopt);
+   TObjOptLink *lnk = (TObjOptLink*)graphlist->FirstLink();
+   TObject *obj = 0;
+
+   while (lnk) {
+      obj = lnk->GetObject();
+      if (!strlen(chopt)) fGraphs->Add(obj,lnk->GetOption());
+      else                fGraphs->Add(obj,chopt);
+      lnk = (TObjOptLink*)lnk->Next();
    }
 }
 
@@ -409,7 +415,7 @@ void TMultiGraph::Browse(TBrowser *)
 //______________________________________________________________________________
 Int_t TMultiGraph::DistancetoPrimitive(Int_t px, Int_t py)
 {
-   // Compute distance from point px,py to each graph
+   // Compute distance from point px,py to each graph.
 
    // Are we on the axis?
    const Int_t kMaxDiff = 10;
@@ -447,6 +453,13 @@ void TMultiGraph::Draw(Option_t *option)
    //  TMultiGraph::Draw. Use GetDrawOption to return the option specified
    //  when drawing the TMultiGraph.
 
+   TString opt = option;
+   opt.ToLower();
+
+   if (gPad) {
+      if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
+      if (opt.Contains("a")) gPad->Clear();
+   }
    AppendPad(option);
 }
 
@@ -627,7 +640,7 @@ TFitResultPtr TMultiGraph::Fit(TF1 *f1, Option_t *option, Option_t *goption, Axi
 //______________________________________________________________________________
 void TMultiGraph::FitPanel()
 {
-   // Display a panel with all histogram fit options
+   // Display a panel with all histogram fit options.
    // See class TFitPanel for example
 
    if (!gPad)
@@ -651,7 +664,7 @@ void TMultiGraph::FitPanel()
 //______________________________________________________________________________
 Option_t *TMultiGraph::GetGraphDrawOption(const TGraph *gr) const
 {
-   // Return the draw option for the TGraph gr in this TMultiGraph
+   // Return the draw option for the TGraph gr in this TMultiGraph.
    // The return option is the one specified when calling TMultiGraph::Add(gr,option).
 
    if (!fGraphs || !gr) return "";
@@ -684,7 +697,7 @@ void TMultiGraph::InitGaus(Double_t xmin, Double_t xmax)
       px=g->GetX();
       py=g->GetY();
       npp=g->GetN();
-      for (bin=0; bin<npp; bin++){
+      for (bin=0; bin<npp; bin++) {
          x=px[bin];
          if (x<xmin || x>xmax) continue;
          np++;
@@ -774,7 +787,7 @@ void TMultiGraph::LeastSquareFit(Int_t m, Double_t *a, Double_t xmin, Double_t x
    while ((g = (TGraph*) next())) {
       px=g->GetX();
       npp=g->GetN();
-      for (bin=0; bin<npp; bin++){
+      for (bin=0; bin<npp; bin++) {
          xk=px[bin];
          if (xk < xmin || xk > xmax) continue;
          n++;
@@ -837,7 +850,8 @@ void TMultiGraph::LeastSquareFit(Int_t m, Double_t *a, Double_t xmin, Double_t x
 
 
 //______________________________________________________________________________
-void TMultiGraph::LeastSquareLinearFit(Int_t ndata, Double_t &a0, Double_t &a1, Int_t &ifail, Double_t xmin, Double_t xmax)
+void TMultiGraph::LeastSquareLinearFit(Int_t ndata, Double_t &a0, Double_t &a1,
+                                       Int_t &ifail, Double_t xmin, Double_t xmax)
 {
    // Least square linear fit without weights.
    //
@@ -916,7 +930,7 @@ Int_t TMultiGraph::IsInside(Double_t x, Double_t y) const
 //______________________________________________________________________________
 TH1F *TMultiGraph::GetHistogram() const
 {
-   // Returns a pointer to the histogram used to draw the axis
+   // Returns a pointer to the histogram used to draw the axis.
    // Takes into account the two following cases.
    //    1- option 'A' was specified in TMultiGraph::Draw. Return fHistogram
    //    2- user had called TPad::DrawFrame. return pointer to hframe histogram
@@ -946,8 +960,8 @@ TF1 *TMultiGraph::GetFunction(const char *name) const
 //______________________________________________________________________________
 TList *TMultiGraph::GetListOfFunctions()
 {
-   // Return pointer to list of functions
-   // if pointer is null create the list
+   // Return pointer to list of functions.
+   // If pointer is null create the list
 
    if (!fFunctions) fFunctions = new TList();
    return fFunctions;
@@ -981,8 +995,8 @@ TAxis *TMultiGraph::GetYaxis() const
 //______________________________________________________________________________
 void TMultiGraph::Paint(Option_t *option)
 {
-   // Paint all the graphs of this multigraph
-   
+   // Paint all the graphs of this multigraph.
+
    const TPickerStackGuard pushGuard(this);
 
    if (!fGraphs) return;
@@ -1092,11 +1106,11 @@ void TMultiGraph::Paint(Option_t *option)
          //else                 uxmax = 0;
       }
       if (minimum < 0 && rwymin >= 0) {
-         if(gPad->GetLogy()) minimum = 0.9*rwymin;
+         if (gPad->GetLogy()) minimum = 0.9*rwymin;
          //else                minimum = 0;
       }
       if (maximum > 0 && rwymax <= 0) {
-         if(gPad->GetLogy()) maximum = 1.1*rwymax;
+         if (gPad->GetLogy()) maximum = 1.1*rwymax;
          //else                maximum = 0;
       }
       if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
@@ -1138,11 +1152,11 @@ void TMultiGraph::Paint(Option_t *option)
       TObject *obj = 0;
 
       while (lnk) {
-      
+
          obj = lnk->GetObject();
-         
+
          gPad->PushSelectableObject(obj);
-         
+
          if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected())) {
             if (strlen(lnk->GetOption()))
                obj->Paint(lnk->GetOption());
@@ -1177,7 +1191,7 @@ void TMultiGraph::Paint(Option_t *option)
 //______________________________________________________________________________
 void TMultiGraph::PaintPolyLine3D(Option_t *option)
 {
-   // Paint all the graphs of this multigraph as 3D lines
+   // Paint all the graphs of this multigraph as 3D lines.
 
    Int_t i, npt=0;
    char *l;
@@ -1202,7 +1216,7 @@ void TMultiGraph::PaintPolyLine3D(Option_t *option)
    }
 
    Int_t ndiv = fGraphs->GetSize();
-   TH2F* frame = new TH2F("frame","", ndiv, 0., (Double_t)(ndiv), 
+   TH2F* frame = new TH2F("frame","", ndiv, 0., (Double_t)(ndiv),
                                       10, rwxmin, rwxmax);
 
    TAxis *Xaxis = frame->GetXaxis();
@@ -1216,15 +1230,15 @@ void TMultiGraph::PaintPolyLine3D(Option_t *option)
    frame->SetStats(kFALSE);
    frame->SetMinimum(rwymin);
    frame->SetMaximum(rwymax);
-   
+
    l = (char*)strstr(option,"A");
    if (l) frame->Paint("lego0,fb,bb");
    l = (char*)strstr(option,"BB");
    if (!l) frame->Paint("lego0,fb,a,same");
-   
+
    Double_t *x, *y;
    Double_t xyz1[3], xyz2[3];
-   
+
    next.Reset();
    Int_t j = ndiv;
    while ((g = (TGraph*) next())) {
@@ -1246,7 +1260,7 @@ void TMultiGraph::PaintPolyLine3D(Option_t *option)
       }
       j--;
    }
-   
+
    l = (char*)strstr(option,"FB");
    if (!l) frame->Paint("lego0,bb,a,same");
    delete frame;
@@ -1256,7 +1270,7 @@ void TMultiGraph::PaintPolyLine3D(Option_t *option)
 //______________________________________________________________________________
 void TMultiGraph::Print(Option_t *option) const
 {
-   // Print the list of graphs
+   // Print the list of graphs.
 
    TGraph *g;
    if (fGraphs) {
@@ -1272,7 +1286,7 @@ void TMultiGraph::Print(Option_t *option) const
 void TMultiGraph::RecursiveRemove(TObject *obj)
 {
    // Recursively remove this object from a list. Typically implemented
-   // by classes that can contain mulitple references to a same object.
+   // by classes that can contain multiple references to a same object.
 
    if (!fGraphs) return;
    TObject *objr = fGraphs->Remove(obj);
@@ -1285,7 +1299,7 @@ void TMultiGraph::RecursiveRemove(TObject *obj)
 //______________________________________________________________________________
 void TMultiGraph::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
 {
-   // Save primitive as a C++ statement(s) on output stream out
+   // Save primitive as a C++ statement(s) on output stream out.
 
    char quote = '"';
    out<<"   "<<endl;
@@ -1339,4 +1353,4 @@ void TMultiGraph::SetMinimum(Double_t minimum)
 
    fMinimum = minimum;
    if (fHistogram) fHistogram->SetMinimum(minimum);
-}
+}
\ No newline at end of file
diff --git a/hist/histpainter/inc/TPainter3dAlgorithms.h b/hist/histpainter/inc/TPainter3dAlgorithms.h
index 0a1dce4..ae088a4 100644
--- a/hist/histpainter/inc/TPainter3dAlgorithms.h
+++ b/hist/histpainter/inc/TPainter3dAlgorithms.h
@@ -72,6 +72,10 @@ private:
    Int_t       *fColorDark;        //
    Int_t        fColorTop;         //
    Int_t        fColorBottom;      //
+   Int_t       *fEdgeColor;        //
+   Int_t       *fEdgeStyle;        //
+   Int_t       *fEdgeWidth;        //
+   Int_t        fEdgeIdx;          //
    Int_t        fMesh;             //(=1 if mesh to draw, o otherwise)
    Int_t        fNlines;           //
    Int_t        fLevelLine[200];   //
@@ -168,6 +172,7 @@ public:
    void    SetSurfaceFunction(SurfaceFunc_t pointer);
    void    SetColorDark(Color_t color, Int_t n=0);
    void    SetColorMain(Color_t color, Int_t n=0);
+   void    SetEdgeAtt(Color_t color=1, Style_t style=1, Width_t width=1, Int_t n=0);
    void    SideVisibilityDecode(Double_t val, Int_t &iv1, Int_t &iv2, Int_t &iv3, Int_t &iv4, Int_t &iv5, Int_t &iv6, Int_t &ir);
    void    SideVisibilityEncode(Int_t iopt, Double_t phi1, Double_t phi2, Double_t &val);
    void    Spectrum(Int_t nl, Double_t fmin, Double_t fmax, Int_t ic, Int_t idc, Int_t &irep);
diff --git a/hist/histpainter/src/TGraph2DPainter.cxx b/hist/histpainter/src/TGraph2DPainter.cxx
index 04bbd4c..e683acf 100644
--- a/hist/histpainter/src/TGraph2DPainter.cxx
+++ b/hist/histpainter/src/TGraph2DPainter.cxx
@@ -589,8 +589,12 @@ void TGraph2DPainter::PaintLevels(Int_t *t,Double_t *x, Double_t *y,
    Double_t x0 = x[0]  , x2 = x[0];
    Double_t y0 = y[0]  , y2 = y[0];
    Double_t z0 = fZ[p0], z2 = fZ[p0];
-   Double_t zmin = fZmin;
-   Double_t zmax = fZmax;
+   Double_t zmin = fGraph2D->GetMinimum();
+   Double_t zmax = fGraph2D->GetMaximum();
+   if (zmin==-1111 && zmax==-1111) {
+      zmin = fZmin;
+      zmax = fZmax;
+   }
 
    // Order along Z axis the points (xi,yi,zi) where "i" belongs to {0,1,2}
    // After this z0 < z1 < z2
@@ -773,7 +777,7 @@ void TGraph2DPainter::PaintPolyMarker(Option_t *option)
    Bool_t colors   = opt.Contains("pcol");
    Int_t  ncolors  = gStyle->GetNumberOfColors();
    Int_t  it, theColor;
-   
+
    // Initialize the levels on the Z axis
    if (colors) {
       Int_t ndiv   = gCurrentHist->GetContour();
@@ -783,7 +787,7 @@ void TGraph2DPainter::PaintPolyMarker(Option_t *option)
       }
       if (gCurrentHist->TestBit(TH1::kUserContour) == 0) gCurrentHist->SetContour(ndiv);
    }
-   
+
    Double_t *xm = new Double_t[fNpoints];
    Double_t *ym = new Double_t[fNpoints];
    Double_t hzmin = gCurrentHist->GetMinimum();
diff --git a/hist/histpainter/src/THistPainter.cxx b/hist/histpainter/src/THistPainter.cxx
index ac86576..5398160 100644
--- a/hist/histpainter/src/THistPainter.cxx
+++ b/hist/histpainter/src/THistPainter.cxx
@@ -23,6 +23,7 @@
 #include "TH2Poly.h"
 #include "TH3.h"
 #include "TProfile.h"
+#include "TProfile2D.h"
 #include "THStack.h"
 #include "TF2.h"
 #include "TF3.h"
@@ -258,6 +259,16 @@ Draw a lego plot using colors to show the cell contents When the option "0" is
 used with any LEGO option, the empty bins are not drawn.
 </td></tr>
 
+<tr><th valign=top>"LEGO3"</th><td>
+Draw a lego plot with hidden surface removal, like LEGO1 but the border lines
+of each lego-bar are not drawn.
+</td></tr>
+
+<tr><th valign=top>"LEGO4"</th><td>
+Draw a lego plot with hidden surface removal, like LEGO1 but without the
+shadow effect on each lego-bar.
+</td></tr>
+
 <tr><th valign=top>"TEXT"</th><td>
 Draw bin contents as text (format set via <tt>gStyle->SetPaintTextFormat</tt>).
 </td></tr>
@@ -404,6 +415,10 @@ value. A sunken button is drawn for negative values a raised one for positive.
 A box is drawn for each cell with a color scale varying with contents. All the
 none empty bins are painted. Empty bins are not painted unless some bins have
 a negative content because in that case the null bins might be not empty.
+<tt>TProfile2D</tt> histograms are handled differently because, for this type of 2D
+histograms, it is possible to know if an empty bin has been filled or not. So even
+if all the bins' contents are positive some empty bins might be painted. And vice versa,
+if some bins have a negative content some empty bins might be not painted.
 </td></tr>
 
 <tr><th valign=top>"COLZ"</th><td>
@@ -698,6 +713,7 @@ The "<tt>mode</tt>" has up to nine digits that can be set to on(1 or 2), off(0).
       s = 1;  skewness printed
       s = 2;  skewness and skewness error printed
       i = 1;  integral of bins printed
+      i = 2;  integral of bins with option "width" printed
       o = 1;  number of overflows printed
       u = 1;  number of underflows printed
       r = 1;  rms printed
@@ -744,13 +760,14 @@ To print only the name of the histogram do:
 of underflow/overflows and not just one single number.
 
 <p>The parameter mode can be any combination of the letters
-<tt>kKsSiourRmMen</tt>
+<tt>kKsSiIourRmMen</tt>
 <pre>
       k :  kurtosis printed
       K :  kurtosis and kurtosis error printed
       s :  skewness printed
       S :  skewness and skewness error printed
       i :  integral of bins printed
+      I :  integral of bins with option "width" printed
       o :  number of overflows printed
       u :  number of underflows printed
       r :  rms printed
@@ -823,6 +840,12 @@ and activate it again with:
       h->SetStats(1).
 </pre>
 
+<p>Labels used in the statistics box ("Mean", "RMS", ...) can be changed from
+<a href="http://root.cern.ch/download/doc/primer/ROOTPrimer.html#configure-root-at-start-up">$ROOTSYS/etc/system.rootrc</a> or
+<a href="http://root.cern.ch/download/doc/primer/ROOTPrimer.html#configure-root-at-start-up">.rootrc</a>
+(look for the string <tt>"Hist.Stats."</tt>).
+</p>
+
 
 <a name="HP08"></a><h3>Fit Statistics</h3>
 
@@ -1162,10 +1185,10 @@ Begin_Macro(source)
    for (Int_t i=0;i<1000;i++) {
       double x,y;
       gRandom->Rannor(x,y);
-      if(x>0 && y>0) hb1->Fill(x,y,4);
-      if(x<0 && y<0) hb2->Fill(x,y,3);
-      if(x>0 && y<0) hb3->Fill(x,y,2);
-      if(x<0 && y>0) hb4->Fill(x,y,1);
+      if (x>0 && y>0) hb1->Fill(x,y,4);
+      if (x<0 && y<0) hb2->Fill(x,y,3);
+      if (x>0 && y<0) hb3->Fill(x,y,2);
+      if (x<0 && y>0) hb4->Fill(x,y,1);
    }
    hb1->SetFillColor(1);
    hb2->SetFillColor(2);
@@ -1205,6 +1228,11 @@ is the color change between cells.
 some bins have a negative content because in that case the null bins
 might be not empty.
 
+<p><tt>TProfile2D</tt> histograms are handled differently because, for this type of 2D
+histograms, it is possible to know if an empty bin has been filled or not. So even
+if all the bins' contents are positive some empty bins might be painted. And vice versa,
+if some bins have a negative content some empty bins might be not painted.
+
 <p>Combined with the option <tt>"COL"</tt>, the option <tt>"Z"</tt> allows to
 display the color palette defined by <tt>gStyle->SetPalette()</tt>.
 
@@ -1573,6 +1601,16 @@ Draw a lego plot using the hidden surface removal technique.
 Draw a lego plot using colors to show the cell contents.
 </td></tr>
 
+<tr><th valign=top>"LEGO3"</th><td>
+Draw a lego plot with hidden surface removal, like LEGO1 but the border lines
+of each lego-bar are not drawn.
+</td></tr>
+
+<tr><th valign=top>"LEGO4"</th><td>
+Draw a lego plot with hidden surface removal, like LEGO1 but without the
+shadow effect on each lego-bar.
+</td></tr>
+
 <tr><th valign=top>"0"</th><td>
 When used with any LEGO option, the empty bins are not drawn.
 </td></tr>
@@ -1580,6 +1618,8 @@ When used with any LEGO option, the empty bins are not drawn.
 </table>
 See the limitations with <a href="#HP060a">the option "SAME"</a>.
 
+<p>Line attributes can be used in lego plots to change the edges' style.
+
 <p>The following example shows a 2D histogram plotted with the option
 <tt>"LEGO"</tt>. The option <tt>"LEGO"</tt> draws a lego plot using the hidden
 lines removal technique.
@@ -1617,7 +1657,6 @@ Begin_Macro(source)
       hlego1->Fill(px-1,5*py);
       hlego1->Fill(2+0.5*px,2*py-10.,0.1);
    }
-   gStyle->SetPalette(1);
    hlego1->SetFillColor(kYellow);
    hlego1->Draw("LEGO1 0");
    return c2;
@@ -1626,6 +1665,30 @@ End_Macro
 Begin_Html
 
 <p>The following example shows a 2D histogram plotted with the option
+<tt>"LEGO3"</tt>. Like the option <tt>"LEGO1"</tt>, the option <tt>"LEGO3"</tt>
+draws a lego plot using the hidden surface removal technique but doesn't draw
+the border lines of each individual lego-bar. This is very useful for histograms
+having many bins. With such histograms the option <tt>"LEGO1"</tt> gives a black
+image because of the border lines. This option also works with stacked legos.
+End_Html
+Begin_Macro(source)
+{
+   TCanvas *c2 = new TCanvas("c2","c2",600,400);
+   TH2F *hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
+   Float_t px, py;
+   for (Int_t i = 0; i < 25000; i++) {
+      gRandom->Rannor(px,py);
+      hlego3->Fill(px-1,5*py);
+      hlego3->Fill(2+0.5*px,2*py-10.,0.1);
+   }
+   hlego3->SetFillColor(kRed);
+   hlego3->Draw("LEGO3");
+   return c2;
+ }
+End_Macro
+Begin_Html
+
+<p>The following example shows a 2D histogram plotted with the option
 <tt>"LEGO2"</tt>. The option <tt>"LEGO2"</tt> draws a lego plot using colors to
 show the cell contents.  Combined with the option <tt>"LEGO2"</tt>, the option
 <tt>"Z"</tt> allows to display the color palette defined by
@@ -1929,12 +1992,12 @@ Begin_Macro(source)
       hlcc->Fill(2+0.5*px,2*py-10.,0.1);
    }
    hlcc->SetFillColor(kYellow);
-   c3->cd(1) ; hlcc->Draw("LEGO1 CYL");
-   c3->cd(2) ; TH2F *hlpc = hlcc->DrawClone("LEGO1 POL");
+   c3->cd(1); hlcc->Draw("LEGO1 CYL");
+   c3->cd(2); TH2F *hlpc = hlcc->DrawClone("LEGO1 POL");
    hlpc->SetTitle("Polar coordinates");
-   c3->cd(3) ; TH2F *hlsc = hlcc->DrawClone("LEGO1 SPH");
+   c3->cd(3); TH2F *hlsc = hlcc->DrawClone("LEGO1 SPH");
    hlsc->SetTitle("Spherical coordinates");
-   c3->cd(4) ; TH2F *hlprpc = hlcc->DrawClone("LEGO1 PSR");
+   c3->cd(4); TH2F *hlprpc = hlcc->DrawClone("LEGO1 PSR");
    hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
    return c3;
 }
@@ -1957,12 +2020,12 @@ Begin_Macro(source)
       hscc->Fill(2+0.5*px,2*py-10.,0.1);
    }
    gStyle->SetPalette(1);
-   c4->cd(1) ; hscc->Draw("SURF1 CYL");
-   c4->cd(2) ; TH2F *hspc = hscc->DrawClone("SURF1 POL");
+   c4->cd(1); hscc->Draw("SURF1 CYL");
+   c4->cd(2); TH2F *hspc = hscc->DrawClone("SURF1 POL");
    hspc->SetTitle("Polar coordinates");
-   c4->cd(3) ; TH2F *hssc = hscc->DrawClone("SURF1 SPH");
+   c4->cd(3); TH2F *hssc = hscc->DrawClone("SURF1 SPH");
    hssc->SetTitle("Spherical coordinates");
-   c4->cd(4) ; TH2F *hsprpc = hscc->DrawClone("SURF1 PSR");
+   c4->cd(4); TH2F *hsprpc = hscc->DrawClone("SURF1 PSR");
    hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
    return c4;
 }
@@ -2746,6 +2809,7 @@ static TString gStringRMSZ;
 static TString gStringUnderflow;
 static TString gStringOverflow;
 static TString gStringIntegral;
+static TString gStringIntegralBinWidth;
 static TString gStringSkewness;
 static TString gStringSkewnessX;
 static TString gStringSkewnessY;
@@ -2784,26 +2848,27 @@ THistPainter::THistPainter()
       fCutsOpt[i] = 0;
    }
 
-   gStringEntries   = gEnv->GetValue("Hist.Stats.Entries",   "Entries");
-   gStringMean      = gEnv->GetValue("Hist.Stats.Mean",      "Mean");
-   gStringMeanX     = gEnv->GetValue("Hist.Stats.MeanX",     "Mean x");
-   gStringMeanY     = gEnv->GetValue("Hist.Stats.MeanY",     "Mean y");
-   gStringMeanZ     = gEnv->GetValue("Hist.Stats.MeanZ",     "Mean z");
-   gStringRMS       = gEnv->GetValue("Hist.Stats.RMS",       "RMS");
-   gStringRMSX      = gEnv->GetValue("Hist.Stats.RMSX",      "RMS x");
-   gStringRMSY      = gEnv->GetValue("Hist.Stats.RMSY",      "RMS y");
-   gStringRMSZ      = gEnv->GetValue("Hist.Stats.RMSZ",      "RMS z");
-   gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
-   gStringOverflow  = gEnv->GetValue("Hist.Stats.Overflow",  "Overflow");
-   gStringIntegral  = gEnv->GetValue("Hist.Stats.Integral",  "Integral");
-   gStringSkewness  = gEnv->GetValue("Hist.Stats.Skewness",  "Skewness");
-   gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
-   gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
-   gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
-   gStringKurtosis  = gEnv->GetValue("Hist.Stats.Kurtosis",  "Kurtosis");
-   gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
-   gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
-   gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
+   gStringEntries          = gEnv->GetValue("Hist.Stats.Entries",          "Entries");
+   gStringMean             = gEnv->GetValue("Hist.Stats.Mean",             "Mean");
+   gStringMeanX            = gEnv->GetValue("Hist.Stats.MeanX",            "Mean x");
+   gStringMeanY            = gEnv->GetValue("Hist.Stats.MeanY",            "Mean y");
+   gStringMeanZ            = gEnv->GetValue("Hist.Stats.MeanZ",            "Mean z");
+   gStringRMS              = gEnv->GetValue("Hist.Stats.RMS",              "RMS");
+   gStringRMSX             = gEnv->GetValue("Hist.Stats.RMSX",             "RMS x");
+   gStringRMSY             = gEnv->GetValue("Hist.Stats.RMSY",             "RMS y");
+   gStringRMSZ             = gEnv->GetValue("Hist.Stats.RMSZ",             "RMS z");
+   gStringUnderflow        = gEnv->GetValue("Hist.Stats.Underflow",        "Underflow");
+   gStringOverflow         = gEnv->GetValue("Hist.Stats.Overflow",         "Overflow");
+   gStringIntegral         = gEnv->GetValue("Hist.Stats.Integral",         "Integral");
+   gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
+   gStringSkewness         = gEnv->GetValue("Hist.Stats.Skewness",         "Skewness");
+   gStringSkewnessX        = gEnv->GetValue("Hist.Stats.SkewnessX",        "Skewness x");
+   gStringSkewnessY        = gEnv->GetValue("Hist.Stats.SkewnessY",        "Skewness y");
+   gStringSkewnessZ        = gEnv->GetValue("Hist.Stats.SkewnessZ",        "Skewness z");
+   gStringKurtosis         = gEnv->GetValue("Hist.Stats.Kurtosis",         "Kurtosis");
+   gStringKurtosisX        = gEnv->GetValue("Hist.Stats.KurtosisX",        "Kurtosis x");
+   gStringKurtosisY        = gEnv->GetValue("Hist.Stats.KurtosisY",        "Kurtosis y");
+   gStringKurtosisZ        = gEnv->GetValue("Hist.Stats.KurtosisZ",        "Kurtosis z");
 }
 
 
@@ -3133,6 +3198,7 @@ void THistPainter::ExecuteEvent(Int_t event, Int_t px, Int_t py)
    }
 }
 
+
 //______________________________________________________________________________
 TList *THistPainter::GetContourList(Double_t contour) const
 {
@@ -3164,7 +3230,7 @@ char *THistPainter::GetObjectInfo(Int_t px, Int_t py) const
    End_html */
 
    if (!gPad) return (char*)"";
-   static char info[100];
+   static char info[200];
    Double_t x  = gPad->PadtoX(gPad->AbsPixeltoX(px));
    Double_t y  = gPad->PadtoY(gPad->AbsPixeltoY(py));
    Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
@@ -3224,18 +3290,42 @@ char *THistPainter::GetObjectInfo(Int_t px, Int_t py) const
       }
    }
    if (fH->GetDimension() == 1) {
-      Double_t integ = 0;
-      for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
-      snprintf(info,100,"(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",x,y,binx,fH->GetBinContent(binx),integ);
-   } else {
+      if (fH->InheritsFrom(TProfile::Class())) {
+         TProfile *tp = (TProfile*)fH;
+         snprintf(info,200,"(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
+                  x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
+                  (Int_t) tp->GetBinEntries(binx));
+      }
+      else {
+         Double_t integ = 0;
+         for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
+         snprintf(info,200,"(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
+                  x,y,binx,fH->GetBinContent(binx),integ);
+      }
+   } else if (fH->GetDimension() == 2) {
       if (fH->InheritsFrom(TH2Poly::Class())) {
          TH2Poly *th2 = (TH2Poly*)fH;
          biny = th2->FindBin(x,y);
-         snprintf(info,100,"%s (x=%g, y=%g, bin=%d, binc=%g)",th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
+         snprintf(info,200,"%s (x=%g, y=%g, bin=%d, binc=%g)",
+                  th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
+      }
+      else if (fH->InheritsFrom(TProfile2D::Class())) {
+         TProfile2D *tp = (TProfile2D*)fH;
+         biny = fYaxis->FindFixBin(y);
+         Int_t bin = fH->GetBin(binx,biny);
+         snprintf(info,200,"(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
+                  x, y, binx, biny, fH->GetBinContent(bin),
+                  fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
       } else {
          biny = fYaxis->FindFixBin(y);
-         snprintf(info,100,"(x=%g, y=%g, binx=%d, biny=%d, binc=%g)",x,y,binx,biny,fH->GetCellContent(binx,biny));
+         snprintf(info,200,"(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
+                  x,y,binx,biny,fH->GetBinContent(binx,biny),
+                  fH->GetBinError(binx,biny));
       }
+   } else {
+      // 3d case: retrieving the x,y,z bin is not yet implemented
+      // print just the x,y info
+      snprintf(info,200,"(x=%g, y=%g)",x,y);
    }
    return info;
 }
@@ -3290,6 +3380,7 @@ Int_t THistPainter::MakeChopt(Option_t *choptin)
    char chopt[128];
    Int_t nch = strlen(choptin);
    strlcpy(chopt,choptin,128);
+   Int_t hdim = fH->GetDimension();
 
    Hoption.Axis = Hoption.Bar    = Hoption.Curve   = Hoption.Error = 0;
    Hoption.Hist = Hoption.Line   = Hoption.Mark    = Hoption.Fill  = 0;
@@ -3315,10 +3406,10 @@ Int_t THistPainter::MakeChopt(Option_t *choptin)
    MakeCuts(chopt);
 
    for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
-   if (fH->GetDimension() > 1) Hoption.Scat = 1;
+   if (hdim > 1) Hoption.Scat = 1;
    if (!nch) Hoption.Hist = 1;
    if (fFunctions->First()) Hoption.Func = 2;
-   if (fH->GetSumw2N() && fH->GetDimension() == 1) Hoption.Error = 2;
+   if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
 
    l = strstr(chopt,"SPEC");
    if (l) {
@@ -3354,8 +3445,8 @@ Int_t THistPainter::MakeChopt(Option_t *choptin)
       Hoption.AxisPos += 1;
       strncpy(l,"  ",2);
    }
-   if((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
-   if(Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
+   if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
+   if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
 
    l = strstr(chopt,"SAMES");
    if (l) {
@@ -3382,6 +3473,8 @@ Int_t THistPainter::MakeChopt(Option_t *choptin)
       Hoption.Lego = 1; strncpy(l,"    ",4);
       if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
       if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
+      if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
+      if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
       l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; strncpy(l,"  ",2); }
       l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0;  strncpy(l,"  ",2); }
       l = strstr(chopt,"0");  if (l) { Hoption.Zero = 1;  strncpy(l," ",1); }
@@ -3418,13 +3511,18 @@ Int_t THistPainter::MakeChopt(Option_t *choptin)
 
    l = strstr(chopt,"CONT");
    if (l) {
-      Hoption.Scat = 0;
-      Hoption.Contour = 1; strncpy(l,"    ",4);
-      if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
-      if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
-      if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
-      if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
-      if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
+      strncpy(l,"    ",4);
+      if (hdim>1) {
+         Hoption.Scat = 0;
+         Hoption.Contour = 1;
+         if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
+         if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
+         if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
+         if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
+         if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
+      } else {
+         Hoption.Hist = 1;
+      }
    }
    l = strstr(chopt,"HBAR");
    if (l) {
@@ -3445,15 +3543,48 @@ Int_t THistPainter::MakeChopt(Option_t *choptin)
       if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
    }
 
-   l = strstr(chopt,"ARR" ); if (l) { Hoption.Arrow  = 1; strncpy(l,"   ", 3); Hoption.Scat = 0; }
+   l = strstr(chopt,"ARR" );
+   if (l) {
+      strncpy(l,"   ", 3);
+      if (hdim>1) {
+         Hoption.Arrow  = 1;
+         Hoption.Scat = 0;
+      } else {
+         Hoption.Hist = 1;
+      }
+   }
    l = strstr(chopt,"BOX" );
    if (l) {
-      Hoption.Scat = 0;
-      Hoption.Box  = 1; strncpy(l,"   ", 3);
-      if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
+      strncpy(l,"   ", 3);
+      if (hdim>1) {
+         Hoption.Scat = 0;
+         Hoption.Box  = 1;
+         if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
+      } else {
+         Hoption.Hist = 1;
+      }
+   }
+   l = strstr(chopt,"COLZ");
+   if (l) {
+      strncpy(l,"    ",4);
+      if (hdim>1) {
+         Hoption.Color  = 2;
+         Hoption.Scat   = 0;
+         Hoption.Zscale = 1;
+      } else {
+         Hoption.Hist = 1;
+      }
+   }
+   l = strstr(chopt,"COL" );
+   if (l) {
+      strncpy(l,"   ", 3);
+      if (hdim>1) {
+         Hoption.Color = 1;
+         Hoption.Scat  = 0;
+      } else {
+         Hoption.Hist = 1;
+      }
    }
-   l = strstr(chopt,"COLZ"); if (l) { Hoption.Color  = 2; strncpy(l,"    ",4); Hoption.Scat = 0; Hoption.Zscale = 1;}
-   l = strstr(chopt,"COL" ); if (l) { Hoption.Color  = 1; strncpy(l,"   ", 3); Hoption.Scat = 0; }
    l = strstr(chopt,"CHAR"); if (l) { Hoption.Char   = 1; strncpy(l,"    ",4); Hoption.Scat = 0; }
    l = strstr(chopt,"FUNC"); if (l) { Hoption.Func   = 2; strncpy(l,"    ",4); Hoption.Hist = 0; }
    l = strstr(chopt,"HIST"); if (l) { Hoption.Hist   = 2; strncpy(l,"    ",4); Hoption.Func = 0; Hoption.Error = 0;}
@@ -3529,7 +3660,7 @@ Int_t THistPainter::MakeChopt(Option_t *choptin)
    }
 
    if (strstr(chopt,"E")) {
-      if (fH->GetDimension() == 1) {
+      if (hdim == 1) {
          Hoption.Error = 1;
          if (strstr(chopt,"E0"))  Hoption.Error = 10;
          if (strstr(chopt,"E1"))  Hoption.Error = 11;
@@ -3596,7 +3727,7 @@ Int_t THistPainter::MakeCuts(char *choptin)
    *right = 0;
    char *comma, *minus;
    Int_t i;
-   while(1) {
+   while (1) {
       comma = strchr(cuts,',');
       if (comma) *comma = 0;
       minus = strchr(cuts,'-');
@@ -3847,18 +3978,18 @@ void THistPainter::PaintArrows(Option_t *)
             xstep = fXaxis->GetBinWidth(i);
             if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
             if (i == Hparam.xfirst) {
-               dx = fH->GetCellContent(i+1, j) - fH->GetCellContent(i, j);
+               dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
             } else if (i == Hparam.xlast) {
-               dx = fH->GetCellContent(i, j) - fH->GetCellContent(i-1, j);
+               dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
             } else {
-               dx = 0.5*(fH->GetCellContent(i+1, j) - fH->GetCellContent(i-1, j));
+               dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
             }
             if (j == Hparam.yfirst) {
-               dy = fH->GetCellContent(i, j+1) - fH->GetCellContent(i, j);
+               dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
             } else if (j == Hparam.ylast) {
-               dy = fH->GetCellContent(i, j) - fH->GetCellContent(i, j-1);
+               dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
             } else {
-               dy = 0.5*(fH->GetCellContent(i, j+1) - fH->GetCellContent(i, j-1));
+               dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
             }
             if (id == 1) {
                dn = TMath::Max(dn, TMath::Abs(dx));
@@ -4552,6 +4683,7 @@ void THistPainter::PaintColorLevels(Option_t *)
    Double_t scale = ndivz/dz;
 
    Int_t color;
+   TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
    for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
       yk    = fYaxis->GetBinLowEdge(j);
       ystep = fYaxis->GetBinWidth(j);
@@ -4562,7 +4694,17 @@ void THistPainter::PaintColorLevels(Option_t *)
          if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
          if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
          z     = fH->GetBinContent(bin);
-         if (z == 0 && (zmin >= 0 || Hoption.Logz)) continue; // don't draw the empty bins for histograms with positive content
+         // if fH is a profile histogram do not draw empty bins
+         if (prof2d) {
+            const Double_t binEntries = prof2d->GetBinEntries(bin);
+            if (binEntries == 0)
+               continue;
+         } else {
+            // don't draw the empty bins for non-profile histograms
+            // with positive content
+            if (z == 0 && (zmin >= 0 || Hoption.Logz)) continue;
+         }
+
          if (Hoption.Logz) {
             if (z > 0) z = TMath::Log10(z);
             else       z = zmin;
@@ -5236,7 +5378,7 @@ void THistPainter::PaintErrors(Option_t *)
          if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
          if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
          // don't duplicate the horizontal line
-         if (Hoption.Hist != 2){
+         if (Hoption.Hist != 2) {
             if (yi1<ymax && yi1>ymin) {
               if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
               if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
@@ -5247,7 +5389,7 @@ void THistPainter::PaintErrors(Option_t *)
          if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
          if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
          // don't duplicate the horizontal line
-         if (Hoption.Hist != 2){
+         if (Hoption.Hist != 2) {
             if (yi1<ymax && yi1>ymin) {
                if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
                if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
@@ -5296,7 +5438,7 @@ L30:
       // 2*npoints. In such cases the array xline and yline must be arranged
       // before being plotted. The next loop does that.
       if (if2 > npoints) {
-         for(i=1; i<if1 ;i++) {
+         for (i=1; i<if1; i++) {
             xline[if1-2+i] = xline[if2-1+i];
             yline[if1-2+i] = yline[if2-1+i];
          }
@@ -5367,7 +5509,7 @@ void THistPainter::Paint2DErrors(Option_t *)
    Double_t temp1[3],temp2[3];
    Double_t xyerror;
    if (Hoption.Error == 110) {
-      xyerror = 0 ;
+      xyerror = 0;
    } else {
       xyerror = gStyle->GetErrorX();
    }
@@ -5595,7 +5737,7 @@ void THistPainter::PaintHist(Option_t *)
          if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
          else              yb = c1;
       }
-      if(!Hoption.Line){
+      if (!Hoption.Line) {
          yb = TMath::Max(yb, ymin);
          yb = TMath::Min(yb, ymax);
       }
@@ -5776,6 +5918,7 @@ Int_t THistPainter::PaintInit()
 
    if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
 
+   Int_t i;
    static const char *where = "PaintInit";
    Double_t yMARGIN = gStyle->GetHistTopMargin();
    Int_t maximum = 0;
@@ -5796,18 +5939,28 @@ Int_t THistPainter::PaintInit()
 
    //       if log scale in X, replace xmin,max by the log
    if (Hoption.Logx) {
+      if (Hparam.xmax<=0) {
+         Error(where, "cannot set X axis to log scale");
+         return 0;
+      }
       if (Hparam.xlowedge <=0 ) {
          if (Hoption.Same) {
             Hparam.xlowedge = TMath::Power(10, gPad->GetUxmin());
          } else {
-            Hparam.xlowedge = 0.1*Hparam.xbinsize;
+            for (i=first; i<=last; i++) {
+               Double_t binLow = fXaxis->GetBinLowEdge(i);
+               if (binLow>0) {
+                  Hparam.xlowedge = binLow;
+                  break;
+               }
+            }
+            if (Hparam.xlowedge<=0) {
+               Error(where, "cannot set X axis to log scale");
+               return 0;
+            }
          }
          Hparam.xmin  = Hparam.xlowedge;
       }
-      if (Hparam.xmin <=0 || Hparam.xmax <=0) {
-         Error(where, "cannot set X axis to log scale");
-         return 0;
-      }
       Hparam.xfirst= fXaxis->FindFixBin(Hparam.xmin);
       Hparam.xlast = fXaxis->FindFixBin(Hparam.xmax);
       Hparam.xmin  = TMath::Log10(Hparam.xmin);
@@ -5823,7 +5976,6 @@ Int_t THistPainter::PaintInit()
    Double_t c1, e1;
    Double_t xv[1];
    Double_t fval;
-   Int_t i;
    TObject *f;
    TF1 *f1;
    Double_t allchan = 0;
@@ -5921,7 +6073,7 @@ Int_t THistPainter::PaintInit()
    }
 
    // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
-   if(TMath::AreEqualRel(ymin,ymax,1E-15)) {
+   if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
       ymin = ymin*(1-1E-14);
       ymax = ymax*(1+1E-14);
    }
@@ -6190,9 +6342,9 @@ void THistPainter::PaintH3Iso()
    Double_t *y = new Double_t[ny];
    Double_t *z = new Double_t[nz];
 
-   for ( i=0 ; i<nx ; i++) x[i] = xaxis->GetBinCenter(i+1);
-   for ( i=0 ; i<ny ; i++) y[i] = yaxis->GetBinCenter(i+1);
-   for ( i=0 ; i<nz ; i++) z[i] = zaxis->GetBinCenter(i+1);
+   for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
+   for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
+   for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
 
    fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
    fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
@@ -6342,6 +6494,22 @@ void THistPainter::PaintLego(Option_t *)
 
    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf, Hoption.System);
 
+   Int_t nids = -1;
+   TH1 * hid = NULL;
+   Color_t colormain = -1, colordark = -1;
+   Bool_t drawShadowsInLego1 = kTRUE;
+
+   // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
+   if (Hoption.Lego == 13) {
+      Hoption.Lego = 11;
+      fLego->SetMesh(0);
+   }
+   // LEGO4 is like LEGO1 except no shadows are drawn.
+   if (Hoption.Lego == 14) {
+      Hoption.Lego = 11;
+      drawShadowsInLego1 = kFALSE;
+   }
+
    //          Create axis object
 
    TGaxis *axis = new TGaxis();
@@ -6355,23 +6523,29 @@ void THistPainter::PaintLego(Option_t *)
    Int_t ndivz  = TMath::Abs(ndiv);
    if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
 
-   //     Initialize colors for the lighting model (option Lego1 only)
-   if (Hoption.Lego == 1) {
-         Color_t colormain = fH->GetLineColor();
-         fLego->SetColorMain(colormain,0);
+   //     Initialize colors
+   if (!fStack) {
+      fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
+   } else {
+      for (Int_t id=0;id<=fStack->GetSize();id++) {
+         hid = (TH1*)fStack->At((id==0)?id:id-1);
+         fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
+      }
    }
+
    if (Hoption.Lego == 11) {
-      Int_t nids = 1;
+      nids = 1;
       if (fStack) nids = fStack->GetSize();
-      TH1 *hid = fH;
+      hid = fH;
       for (Int_t id=0;id<=nids;id++) {
          if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
-         Color_t colormain = hid->GetFillColor();
+         colormain = hid->GetFillColor();
          if (colormain == 1) colormain = 17; //avoid drawing with black
-         Color_t colordark = TColor::GetColorDark(colormain);
+         if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
+         else                    colordark = colormain;
          fLego->SetColorMain(colormain,id);
          fLego->SetColorDark(colordark,id);
-         if (id == 0)    fLego->SetColorMain(colormain,-1);  // Set Bottom color
+         if (id <= 1)    fLego->SetColorMain(colormain,-1);  // Set Bottom color
          if (id == nids) fLego->SetColorMain(colormain,99);  // Set Top color
       }
    }
@@ -6390,7 +6564,7 @@ void THistPainter::PaintLego(Option_t *)
    Double_t psideg = view->GetPsi();
    view->SetView(phideg, thedeg, psideg, irep);
 
-   fLego->SetLineColor(fH->GetLineColor());
+   fLego->SetLineColor(kBlack);  /// zgrid color for lego1 & lego2
    fLego->SetFillStyle(fH->GetFillStyle());
 
    //     Set color/style for back box
@@ -6449,7 +6623,6 @@ void THistPainter::PaintLego(Option_t *)
    }
 
    if (Hoption.Lego == 1 || Hoption.Lego == 11) {
-      fLego->SetLineColor(1);
       if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
          fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
          fLego->BackBox(90);
@@ -6503,10 +6676,10 @@ void THistPainter::PaintLegoAxis(TGaxis *axis, Double_t ang)
       r[2] = 0;
       view->WCtoNDC(r, x2);
       gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
-      return ;
+      return;
    }
 
-   if (Hoption.System != kCARTESIAN) return ;
+   if (Hoption.System != kCARTESIAN) return;
 
    rad = TMath::ATan(1.) * 4. /180.;
    cosa = TMath::Cos(ang*rad);
@@ -6656,7 +6829,7 @@ void THistPainter::PaintLegoAxis(TGaxis *axis, Double_t ang)
       axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
    }
 
-   fH->SetLineStyle(1);
+   //fH->SetLineStyle(1);  /// otherwise fEdgeStyle[i] gets overwritten!
 }
 
 
@@ -6791,11 +6964,11 @@ void THistPainter::PaintScatterPlot(Option_t *option)
                }
                fXbuf[marker] = (random.Rndm(loop)*xstep) + xk;
                fYbuf[marker] = (random.Rndm(loop)*ystep) + yk;
-               if (Hoption.Logx){
+               if (Hoption.Logx) {
                   if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
                   else                   break;
                }
-               if (Hoption.Logy){
+               if (Hoption.Logy) {
                   if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
                   else                  break;
                }
@@ -6987,7 +7160,7 @@ void THistPainter::PaintStat(Int_t dostat, TF1 *fit)
          snprintf(t,100,textstats,fH->GetRMS(1),fH->GetRMSError(1));
       }
       stats->AddText(t);
-      if(fH->InheritsFrom(TProfile::Class())) {
+      if (fH->InheritsFrom(TProfile::Class())) {
          if (print_rms == 1) {
             snprintf(textstats,50,"%s = %s%s",gStringRMSY.Data(),"%",stats->GetStatFormat());
             snprintf(t,100,textstats,fH->GetRMS(2));
@@ -7010,8 +7183,13 @@ void THistPainter::PaintStat(Int_t dostat, TF1 *fit)
       stats->AddText(t);
    }
    if (print_integral) {
-      snprintf(textstats,50,"%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
-      snprintf(t,100,textstats,fH->Integral());
+      if (print_integral == 1) {
+         snprintf(textstats,50,"%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
+         snprintf(t,100,textstats,fH->Integral());
+      } else {
+         snprintf(textstats,50,"%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
+         snprintf(t,100,textstats,fH->Integral("width"));
+      }
       stats->AddText(t);
    }
    if (print_skew) {
@@ -7059,9 +7237,9 @@ void THistPainter::PaintStat(Int_t dostat, TF1 *fit)
             if (a>50) a = 50;
             if (print_ferrors) {
                snprintf(textstats,50,"= %s%s #pm %s ", "%",stats->GetFitFormat(),
-                        GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
+                       GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
                snprintf(&t[a],100,textstats,(Float_t)fit->GetParameter(ipar)
-                        ,(Float_t)fit->GetParError(ipar));
+                               ,(Float_t)fit->GetParError(ipar));
             } else {
                snprintf(textstats,50,"= %s%s ","%",stats->GetFitFormat());
                snprintf(&t[a],100,textstats,(Float_t)fit->GetParameter(ipar));
@@ -7250,15 +7428,22 @@ void THistPainter::PaintStat2(Int_t dostat, TF1 *fit)
       //get 3*3 under/overflows for 2d hist
       Double_t unov[9];
 
-      unov[0] = h2->Integral(0,h2->GetXaxis()->GetFirst()-1,h2->GetYaxis()->GetLast()+1,h2->GetYaxis()->GetNbins()+1);
-      unov[1] = h2->Integral(h2->GetXaxis()->GetFirst(),h2->GetXaxis()->GetLast(),h2->GetYaxis()->GetLast()+1,h2->GetYaxis()->GetNbins()+1);
-      unov[2] = h2->Integral(h2->GetXaxis()->GetLast()+1,h2->GetXaxis()->GetNbins()+1,h2->GetYaxis()->GetLast()+1,h2->GetYaxis()->GetNbins()+1);
-      unov[3] = h2->Integral(0,h2->GetXaxis()->GetFirst()-1,h2->GetYaxis()->GetFirst(),h2->GetYaxis()->GetLast());
-      unov[4] = h2->Integral(h2->GetXaxis()->GetFirst(),h2->GetXaxis()->GetLast(),h2->GetYaxis()->GetFirst(),h2->GetYaxis()->GetLast());
-      unov[5] = h2->Integral(h2->GetXaxis()->GetLast()+1,h2->GetXaxis()->GetNbins()+1,h2->GetYaxis()->GetFirst(),h2->GetYaxis()->GetLast());
-      unov[6] = h2->Integral(0,h2->GetXaxis()->GetFirst()-1,0,h2->GetYaxis()->GetFirst()-1);
-      unov[7] = h2->Integral(h2->GetXaxis()->GetFirst(),h2->GetXaxis()->GetLast(),0,h2->GetYaxis()->GetFirst()-1);
-      unov[8] = h2->Integral(h2->GetXaxis()->GetLast()+1,h2->GetXaxis()->GetNbins()+1,0,h2->GetYaxis()->GetFirst()-1);
+      Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
+      Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
+      Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
+      Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
+      Int_t lastX  = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
+      Int_t lastY  = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
+
+      unov[0] = h2->Integral(      0, firstX-1, lastY+1, cellsY  );
+      unov[1] = h2->Integral(firstX , lastX   , lastY+1, cellsY  );
+      unov[2] = h2->Integral(lastX+1, cellsX  , lastY+1, cellsY  );
+      unov[3] = h2->Integral(      0, firstX-1, firstY , lastY   );
+      unov[4] = h2->Integral(firstX , lastX   , firstY , lastY   );
+      unov[5] = h2->Integral(lastX+1, cellsX  , firstY , lastY   );
+      unov[6] = h2->Integral(      0, firstX-1,       0, firstY-1);
+      unov[7] = h2->Integral(firstX, lastX,           0, firstY-1);
+      unov[8] = h2->Integral(lastX+1, cellsX  ,       0, firstY-1);
 
       snprintf(t, 100," %7d|%7d|%7d\n", (Int_t)unov[0], (Int_t)unov[1], (Int_t)unov[2]);
       stats->AddText(t);
@@ -7280,7 +7465,7 @@ void THistPainter::PaintStat2(Int_t dostat, TF1 *fit)
          snprintf(t,100,"%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
                                    ,(Float_t)fit->GetParameter(ipar)
                                    ,(Float_t)fit->GetParError(ipar));
-         t[32] = 0;
+         t[63] = 0;
          stats->AddText(t);
       }
    }
@@ -7602,7 +7787,7 @@ void THistPainter::PaintSurface(Option_t *)
    }
 
    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf, Hoption.System);
-   fLego->SetLineColor(fH->GetLineColor());
+   fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
    fLego->SetFillColor(fH->GetFillColor());
 
    //          Create axis object
@@ -7679,7 +7864,6 @@ void THistPainter::PaintSurface(Option_t *)
 
    if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
       fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
-      fLego->SetLineColor(1);
       if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
          fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
          fLego->BackBox(90);
@@ -7764,7 +7948,6 @@ void THistPainter::PaintSurface(Option_t *)
 
    if ((!Hoption.Same) &&
        (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
-      fLego->SetLineColor(1);
       if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
          fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
          fLego->BackBox(90);
@@ -8875,10 +9058,10 @@ Int_t THistPainter::TableInit()
    Double_t allchan = 0;
    for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
       for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
-         c1 = fH->GetCellContent(i,j);
+         c1 = fH->GetBinContent(i,j);
          zmax = TMath::Max(zmax,c1);
          if (Hoption.Error) {
-            e1 = fH->GetCellError(i,j);
+            e1 = fH->GetBinError(i,j);
             zmax = TMath::Max(zmax,c1+e1);
          }
          zmin = TMath::Min(zmin,c1);
@@ -9151,7 +9334,7 @@ void THistPainter::ShowProjectionY(Int_t px, Int_t /*py*/)
    TVirtualPad *padsav = gPad;
    TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
                                                                               (ULong_t)fH, fShowProjection));
-   if(c) {
+   if (c) {
       c->Clear();
    } else {
       fShowProjection = 0;
@@ -9234,7 +9417,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
    TVirtualPad *padsav = gPad;
    TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
                                                                               (ULong_t)fH, fShowProjection));
-   if(!c) {
+   if (!c) {
       fShowProjection = 0;
       return;
    }
@@ -9251,7 +9434,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t lastZ  = zaxis->GetLast();
             Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
             zaxis->SetRange(binz,binz+nbins-1);
-            if(line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
+            if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
             if (nbins>1 && line1[0].GetX()) {
                gVirtualX->DrawPolyLine(2,line2);
                gVirtualX->DrawPolyLine(2,line3);
@@ -9358,7 +9541,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t lastZ  = zaxis->GetLast();
             Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
             zaxis->SetRange(binz,binz+nbins-1);
-            if(line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
+            if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
             if (nbins>1 && line1[0].GetX()) {
                gVirtualX->DrawPolyLine(2,line2);
                gVirtualX->DrawPolyLine(2,line3);
@@ -9465,7 +9648,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t lastY  = yaxis->GetLast();
             Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
             yaxis->SetRange(biny,biny+nbins-1);
-            if(line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
+            if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
             if (nbins>1 && line1[0].GetX()) {
                gVirtualX->DrawPolyLine(2,line2);
                gVirtualX->DrawPolyLine(2,line3);
@@ -9568,8 +9751,8 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t last  = zaxis->GetLast();
             Int_t binz  = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
             zaxis->SetRange(binz,binz+nbins-1);
-            if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
-            if(nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
+            if (rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
+            if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
             xx[0] = xaxis->GetXmin();
             xx[1] = yaxis->GetXmax();
             xx[2] = zaxis->GetBinCenter(binz);
@@ -9623,7 +9806,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             zaxis->SetRange(first,last);
             if (hp) {
                hp->SetFillColor(38);
-               if(nbins==1)hp->SetTitle(Form("ProjectionXY of binz=%d (%.1f)", binz,value1));
+               if (nbins==1)hp->SetTitle(Form("ProjectionXY of binz=%d (%.1f)", binz,value1));
                else        hp->SetTitle(Form("ProjectionXY, binz range=%d-%d (%.1f-%.1f)", binz,binz+nbins-1,value1,value2));
                hp->SetXTitle(fH->GetYaxis()->GetTitle());
                hp->SetYTitle(fH->GetXaxis()->GetTitle());
@@ -9640,8 +9823,8 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t last  = zaxis->GetLast();
             Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
             zaxis->SetRange(binz,binz+nbins-1);
-            if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
-            if(nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
+            if (rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
+            if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
             xx[0] = xaxis->GetXmin();
             xx[1] = yaxis->GetXmax();
             xx[2] = zaxis->GetBinCenter(binz);
@@ -9694,7 +9877,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             zaxis->SetRange(first,last);
             if (hp) {
                hp->SetFillColor(38);
-               if(nbins==1)hp->SetTitle(Form("ProjectionYX of binz=%d (%.1f)", binz,value1));
+               if (nbins==1)hp->SetTitle(Form("ProjectionYX of binz=%d (%.1f)", binz,value1));
                else        hp->SetTitle(Form("ProjectionXY, binz range=%d-%d (%.1f-%.1f)", binz,binz+nbins-1,value1,value2));
                hp->SetXTitle(fH->GetXaxis()->GetTitle());
                hp->SetYTitle(fH->GetYaxis()->GetTitle());
@@ -9711,8 +9894,8 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t last  = yaxis->GetLast();
             Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
             yaxis->SetRange(biny,biny+nbins-1);
-            if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
-            if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
+            if (rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
+            if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
             xx[0] = xaxis->GetXmin();
             xx[2] = zaxis->GetXmax();
             xx[1] = yaxis->GetBinCenter(biny);
@@ -9765,7 +9948,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             yaxis->SetRange(first,last);
             if (hp) {
                hp->SetFillColor(38);
-               if(nbins==1)hp->SetTitle(Form("ProjectionXZ of biny=%d (%.1f)", biny,value1));
+               if (nbins==1)hp->SetTitle(Form("ProjectionXZ of biny=%d (%.1f)", biny,value1));
                else        hp->SetTitle(Form("ProjectionXZ, biny range=%d-%d (%.1f-%.1f)", biny,biny+nbins-1,value1,value2));
                hp->SetXTitle(fH->GetZaxis()->GetTitle());
                hp->SetYTitle(fH->GetXaxis()->GetTitle());
@@ -9782,8 +9965,8 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t last  = yaxis->GetLast();
             Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
             yaxis->SetRange(biny,biny+nbins-1);
-            if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
-            if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
+            if (rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
+            if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
             xx[0] = xaxis->GetXmin();
             xx[2] = zaxis->GetXmax();
             xx[1] = yaxis->GetBinCenter(biny);
@@ -9836,7 +10019,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             yaxis->SetRange(first,last);
             if (hp) {
                hp->SetFillColor(38);
-               if(nbins==1)hp->SetTitle(Form("ProjectionZX of biny=%d (%.1f)", biny,value1));
+               if (nbins==1)hp->SetTitle(Form("ProjectionZX of biny=%d (%.1f)", biny,value1));
                else        hp->SetTitle(Form("ProjectionZX, binY range=%d-%d (%.1f-%.1f)", biny,biny+nbins-1,value1,value2));
                hp->SetXTitle(fH->GetXaxis()->GetTitle());
                hp->SetYTitle(fH->GetZaxis()->GetTitle());
@@ -9853,8 +10036,8 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t last  = xaxis->GetLast();
             Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
             xaxis->SetRange(binx,binx+nbins-1);
-            if(rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
-            if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
+            if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
+            if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
             xx[2] = zaxis->GetXmin();
             xx[1] = yaxis->GetXmax();
             xx[0] = xaxis->GetBinCenter(binx);
@@ -9907,7 +10090,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             xaxis->SetRange(first,last);
             if (hp) {
                hp->SetFillColor(38);
-               if(nbins==1)hp->SetTitle(Form("ProjectionYZ of binx=%d (%.1f)", binx,value1));
+               if (nbins==1)hp->SetTitle(Form("ProjectionYZ of binx=%d (%.1f)", binx,value1));
                else        hp->SetTitle(Form("ProjectionYZ, binx range=%d-%d (%.1f-%.1f)", binx,binx+nbins-1,value1,value2));
                hp->SetXTitle(fH->GetZaxis()->GetTitle());
                hp->SetYTitle(fH->GetYaxis()->GetTitle());
@@ -9924,8 +10107,8 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             Int_t last  = xaxis->GetLast();
             Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
             xaxis->SetRange(binx,binx+nbins-1);
-            if(rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
-            if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
+            if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
+            if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
             xx[2] = zaxis->GetXmin();
             xx[1] = yaxis->GetXmax();
             xx[0] = xaxis->GetBinCenter(binx);
@@ -9978,7 +10161,7 @@ void THistPainter::ShowProjection3(Int_t px, Int_t py)
             xaxis->SetRange(first,last);
             if (hp) {
                hp->SetFillColor(38);
-               if(nbins==1)hp->SetTitle(Form("ProjectionZY of binx=%d (%.1f)", binx,value1));
+               if (nbins==1)hp->SetTitle(Form("ProjectionZY of binx=%d (%.1f)", binx,value1));
                else        hp->SetTitle(Form("ProjectionZY, binx range=%d-%d (%.1f-%.1f)", binx,binx+nbins-1,value1,value2));
                hp->SetXTitle(fH->GetYaxis()->GetTitle());
                hp->SetYTitle(fH->GetZaxis()->GetTitle());
diff --git a/hist/histpainter/src/TPainter3dAlgorithms.cxx b/hist/histpainter/src/TPainter3dAlgorithms.cxx
index a6764de..038caee 100644
--- a/hist/histpainter/src/TPainter3dAlgorithms.cxx
+++ b/hist/histpainter/src/TPainter3dAlgorithms.cxx
@@ -40,17 +40,13 @@ End_Html */
 #include "THLimitsFinder.h"
 #include "TColor.h"
 
-#ifdef R__SUNCCBUG
-const Double_t kRad = 1.74532925199432955e-02;
-#else
-const Double_t kRad = TMath::ATan(1)*Double_t(4)/Double_t(180);
-#endif
+const Double_t kRad  = TMath::ATan(1)*Double_t(4)/Double_t(180);
 const Double_t kFdel = 0.;
-const Double_t kDel = 0.0001;
-const Int_t kNiso = 4;
+const Double_t kDel  = 0.0001;
+const Int_t kNiso  = 4;
 const Int_t kNmaxp = kNiso*13;
 const Int_t kNmaxt = kNiso*12;
-const Int_t kLmax = 12;
+const Int_t kLmax  = 12;
 const Int_t kF3FillColor1 = 201;
 const Int_t kF3FillColor2 = 202;
 const Int_t kF3LineColor  = 203;
@@ -67,6 +63,9 @@ static Double_t gV[kVSizeMax];
 static Double_t gTT[4*kVSizeMax];
 static Int_t gColorMain[kVSizeMax+1];
 static Int_t gColorDark[kVSizeMax+1];
+static Int_t gEdgeColor[kVSizeMax+1];
+static Int_t gEdgeStyle[kVSizeMax+1];
+static Int_t gEdgeWidth[kVSizeMax+1];
 
 extern TH1  *gCurrentHist; //these 3 globals should be replaced by class members
 extern Hoption_t Hoption;
@@ -86,13 +85,13 @@ TPainter3dAlgorithms::TPainter3dAlgorithms(): TObject(), TAttLine(1,1,1), TAttFi
    fRaster          = 0;
    fColorTop        = 1;
    fColorBottom     = 1;
+   fEdgeIdx         = -1;
    fNlevel          = 0;
    fSystem          = kCARTESIAN;
    fDrawFace        = 0;
    fLegoFunction    = 0;
    fSurfaceFunction = 0;
 
-
    TList *stack = 0;
    if (gCurrentHist) stack = gCurrentHist->GetPainter()->GetStack();
    fNStack = 0;
@@ -100,13 +99,19 @@ TPainter3dAlgorithms::TPainter3dAlgorithms(): TObject(), TAttLine(1,1,1), TAttFi
    if (fNStack > kVSizeMax) {
       fColorMain  = new Int_t[fNStack+1];
       fColorDark  = new Int_t[fNStack+1];
+      fEdgeColor  = new Int_t[fNStack+1];
+      fEdgeStyle  = new Int_t[fNStack+1];
+      fEdgeWidth  = new Int_t[fNStack+1];
    } else {
       fColorMain = &gColorMain[0];
       fColorDark = &gColorDark[0];
+      fEdgeColor = &gEdgeColor[0];
+      fEdgeStyle = &gEdgeStyle[0];
+      fEdgeWidth = &gEdgeWidth[0];
    }
 
-   for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; }
-   for (i=0;i<3;i++)       { fRmin[i] = 0, fRmax[i] = 1; }
+   for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; fEdgeColor[i] = 1; fEdgeStyle[i] = 1; fEdgeWidth[i] = 1; }
+   for (i=0;i<3;i++)       { fRmin[i] = 0; fRmax[i] = 1; }
    for (i=0;i<4;i++)       { fYls[i] = 0; }
 
    for (i=0;i<30;i++)      { fJmask[i] = 0; }
@@ -163,6 +168,7 @@ TPainter3dAlgorithms::TPainter3dAlgorithms(Double_t *rmin, Double_t *rmax, Int_t
    fRaster       = 0;
    fColorTop     = 1;
    fColorBottom  = 1;
+   fEdgeIdx      = -1;
    fNlevel       = 0;
    fSystem       = system;
    if (system == kCARTESIAN || system == kPOLAR) psi =  0;
@@ -177,13 +183,19 @@ TPainter3dAlgorithms::TPainter3dAlgorithms(Double_t *rmin, Double_t *rmax, Int_t
    if (fNStack > kVSizeMax) {
       fColorMain  = new Int_t[fNStack+1];
       fColorDark  = new Int_t[fNStack+1];
+      fEdgeColor  = new Int_t[fNStack+1];
+      fEdgeStyle  = new Int_t[fNStack+1];
+      fEdgeWidth  = new Int_t[fNStack+1];
    } else {
       fColorMain = &gColorMain[0];
       fColorDark = &gColorDark[0];
+      fEdgeColor = &gEdgeColor[0];
+      fEdgeStyle = &gEdgeStyle[0];
+      fEdgeWidth = &gEdgeWidth[0];
    }
 
-   for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; }
-   for (i=0;i<3;i++)       { fRmin[i] = rmin[i], fRmax[i] = rmax[i]; }
+   for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; fEdgeColor[i] = 1; fEdgeStyle[i] = 1; fEdgeWidth[i] = 1; }
+   for (i=0;i<3;i++)       { fRmin[i] = rmin[i]; fRmax[i] = rmax[i]; }
    for (i=0;i<4;i++)       { fYls[i] = 0; }
 
    for (i=0;i<30;i++)      { fJmask[i] = 0; }
@@ -240,6 +252,9 @@ TPainter3dAlgorithms::~TPainter3dAlgorithms()
    if (fNStack > kVSizeMax) {
       delete [] fColorMain;
       delete [] fColorDark;
+      delete [] fEdgeColor;
+      delete [] fEdgeStyle;
+      delete [] fEdgeWidth;
    }
 }
 
@@ -525,10 +540,17 @@ void TPainter3dAlgorithms::DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np,
    //          D R A W   F A C E   &   B O R D E R
    FillPolygon(np, p3, &t[1]);
    if (fMesh == 1) {
-      SetFillColor(1);
-      SetFillStyle(0);
-      TAttFill::Modify();
-      gPad->PaintFillArea(np, x, y);
+      if (Hoption.Lego!=0 && Hoption.Surf==0) {  // i.e. PaintFillArea for lego, not for surf
+         SetFillColor(fEdgeColor[fEdgeIdx]);
+         SetFillStyle(0);
+         TAttFill::Modify();
+         gPad->PaintFillArea(np, x, y);
+      }
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineStyle(fEdgeStyle[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+      TAttLine::Modify();
+      gPad->PaintPolyLine(np, x, y);
    }
 }
 
@@ -588,9 +610,14 @@ void TPainter3dAlgorithms::DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np,
    gPad->PaintFillArea(np, x, y);
    if (fMesh) {
       SetFillStyle(0);
-      SetFillColor(1);
+      SetFillColor(fEdgeColor[fEdgeIdx]);
       TAttFill::Modify();
       gPad->PaintFillArea(np, x, y);
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineStyle(fEdgeStyle[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+      TAttLine::Modify();
+      gPad->PaintPolyLine(np, x, y);
    }
 }
 
@@ -644,6 +671,13 @@ void TPainter3dAlgorithms::DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np,
 
    //          D R A W   L E V E L   L I N E S
    SetLineStyle(3);
+   if (icodes[3]==0) {  // front & back boxes
+      SetLineColor(1);
+      SetLineWidth(1);
+   } else {
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+   }
    TAttLine::Modify();
    for (il = 1; il <= fNlines; ++il) {
       FindVisibleDraw(&fPlines[(2*il + 1)*3 - 9], &fPlines[(2*il + 2)*3 - 9]);
@@ -661,7 +695,15 @@ void TPainter3dAlgorithms::DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np,
    }
 
    //          D R A W   F A C E
-   SetLineStyle(1);
+   if (icodes[3]==0) {  // front & back boxes
+      SetLineColor(1);
+      SetLineStyle(1);
+      SetLineWidth(1);
+   } else {
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineStyle(fEdgeStyle[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+   }
    TAttLine::Modify();
    for (i = 1; i <= np; ++i) {
       i1 = i;
@@ -739,6 +781,15 @@ void TPainter3dAlgorithms::DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np,
    FindLevelLines(np, p3, &tt[1]);
 
    // Draw level lines
+   if (icodes[3]==0) {  // front and back boxes
+      SetLineColor(1);
+      SetLineStyle(1);
+      SetLineWidth(1);
+   } else {
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineStyle(fEdgeStyle[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+   }
    TAttLine::Modify();
    for (il = 1; il <= fNlines; ++il) {
       FindVisibleDraw(&fPlines[(2*il + 1)*3 - 9], &fPlines[(2*il + 2)*3 - 9]);
@@ -787,7 +838,7 @@ void TPainter3dAlgorithms::DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np,
    //                       (not used in this routine)
 
    Double_t xdel, ydel;
-   Int_t i, k, icol, i1, i2, it;
+   Int_t i, k, i1, i2, it;
    Double_t x[2], y[2];
    Double_t p1[3], p2[3], p3[36]        /* was [3][12] */;
    TView *view = 0;
@@ -810,9 +861,15 @@ void TPainter3dAlgorithms::DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np,
    }
 
    //          D R A W   F A C E
-   icol = icodes[3];
-   if (icol) SetLineColor(fColorMain[icol - 1]);
-   else      SetLineColor(1);
+   if (icodes[3]==0) {  // front & back boxes
+      SetLineColor(1);
+      SetLineStyle(1);
+      SetLineWidth(1);
+   } else {
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineStyle(fEdgeStyle[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+   }
    TAttLine::Modify();
    for (i = 1; i <= np; ++i) {
       i1 = i;
@@ -893,6 +950,13 @@ void TPainter3dAlgorithms::DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t n
 
    //          D R A W   L E V E L   L I N E S
    SetLineStyle(3);
+   if (icodes[3]==0) {  // front & back boxes
+      SetLineColor(1);
+      SetLineWidth(1);
+   } else {
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+   }
    TAttLine::Modify();
    for (il = 1; il <= fNlines; ++il) {
       view->WCtoNDC(&fPlines[(2*il + 1)*3 - 9], p1);
@@ -910,7 +974,15 @@ void TPainter3dAlgorithms::DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t n
    }
 
    //          D R A W   F A C E
-   SetLineStyle(1);
+   if (icodes[3]==0) {  // front & back boxes
+      SetLineColor(1);
+      SetLineStyle(1);
+      SetLineWidth(1);
+   } else {
+      SetLineColor(fEdgeColor[fEdgeIdx]);
+      SetLineStyle(fEdgeStyle[fEdgeIdx]);
+      SetLineWidth(fEdgeWidth[fEdgeIdx]);
+   }
    TAttLine::Modify();
    for (i = 1; i <= np; ++i) {
       if (iface[i] < 0) continue;
@@ -955,7 +1027,7 @@ void TPainter3dAlgorithms::DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t n
    //                       (not used in this routine)
 
    Double_t xdel, ydel;
-   Int_t i, k, icol, i1, i2, it;
+   Int_t i, k, i1, i2, it;
    Double_t p[3], x[2], y[2];
    Double_t pp[24]        /* was [2][12] */;
    TView *view = 0;
@@ -979,9 +1051,9 @@ void TPainter3dAlgorithms::DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t n
    }
 
    //          D R A W   F A C E
-   icol = icodes[3];
-   if (icol) SetLineColor(fColorMain[icol - 1]);
-   else      SetLineColor(1);
+   SetLineColor(fEdgeColor[fEdgeIdx]);
+   SetLineStyle(fEdgeStyle[fEdgeIdx]);
+   SetLineWidth(fEdgeWidth[fEdgeIdx]);
    TAttLine::Modify();
    for (i = 1; i <= np; ++i) {
       if (iface[i] < 0) continue;
@@ -2228,7 +2300,7 @@ void TPainter3dAlgorithms::LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t
    //              Get the content of the table, and loop on the
    //              stack if necessary.
    vv[1] = Hparam.zmin;
-   vv[2] = Hparam.factor*gCurrentHist->GetCellContent(ixt, iyt);
+   vv[2] = Hparam.factor*gCurrentHist->GetBinContent(ixt, iyt);
 
    // In linear scale, 3D boxes all start from 0.
    if (Hparam.zmin<0 && !Hoption.Logz && gStyle->GetHistMinimumZero()) {
@@ -2246,7 +2318,7 @@ void TPainter3dAlgorithms::LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t
    if (nids) {
       for (i = 2; i <= nids + 1; ++i) {
          TH1 *hid = (TH1*)stack->At(i-2);
-         vv[i + 1] = Hparam.factor*hid->GetCellContent(ixt, iyt) + vv[i];
+         vv[i + 1] = Hparam.factor*hid->GetBinContent(ixt, iyt) + vv[i];
          vv[i + 1] = TMath::Max(Hparam.zmin, vv[i + 1]);
          //vv[i + 1] = TMath::Min(Hparam.zmax, vv[i + 1]);
       }
@@ -2341,6 +2413,7 @@ void TPainter3dAlgorithms::LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const
    Double_t xyz[24];   // was [3][8]
    Double_t *tn = 0;
    TView *view = 0;
+   Int_t firstStackNumberDrawn=-1 ;  // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
 
    sina = TMath::Sin(ang*kRad);
    cosa = TMath::Cos(ang*kRad);
@@ -2422,6 +2495,7 @@ void TPainter3dAlgorithms::LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const
             xyz[(i + 4)*3 - 2] = xyz[i*3 - 2];
          }
    //         D R A W   S T A C K
+         firstStackNumberDrawn = -1;
          for (iv = 1; iv < nv; ++iv) {
             for (i = 1; i <= 4; ++i) {
                xyz[i*3 - 1] = v[iv - 1];
@@ -2443,8 +2517,10 @@ void TPainter3dAlgorithms::LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const
                tface[1] = tt[k2 + (iv << 2) - 5];
                tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
                tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
+               fEdgeIdx = iv-1;
                (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
             }
+            if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
          }
    //         D R A W   B O T T O M   F A C E
          view->FindNormal(0, 0, 1, zn);
@@ -2456,6 +2532,11 @@ void TPainter3dAlgorithms::LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const
                iface[i - 1] = 5 - i;
                tface[i - 1] = tt[5 - i - 1];
             }
+            if (!Hoption.Zero) fEdgeIdx = 0;
+            else {
+               fEdgeIdx = firstStackNumberDrawn;
+               fColorBottom = fColorMain[fEdgeIdx];
+            }
             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
          }
    //         D R A W   T O P   F A C E
@@ -2467,9 +2548,15 @@ void TPainter3dAlgorithms::LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const
                tface[i - 1] = tt[i + (nv << 2) - 5];
             }
             Int_t cs = fColorTop;
-            if ( nv > 2 && (v[nv-1] == v[nv-2])) {
-               for (iv = nv-1; iv>2; iv--) {
-                  if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
+            if ( nv <= 3 ) fEdgeIdx = 0 ;  // no stack or stack with only one histo
+            else {
+               if ( nv > 2 && (v[nv-1] == v[nv-2])) {
+                  for (iv = nv-1; iv>2; iv--) {
+                     if (v[nv-1] == v[iv-1]) {
+                        fColorTop = fColorMain[iv-2];
+                        fEdgeIdx  = iv-2;
+                     }
+                  }
                }
             }
             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
@@ -2530,6 +2617,7 @@ void TPainter3dAlgorithms::LegoPolar(Int_t iordr, Int_t na, Int_t nb, const char
    Double_t xyz[24];     // was [3][8]
    ia = ib = 0;
    TView *view = 0;
+   Int_t firstStackNumberDrawn=-1 ;  // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
 
    if (gPad) view = gPad->GetView();
    if (!view) {
@@ -2626,6 +2714,7 @@ L100:
          xyz[(j + 4)*3 - 2] = xyz[j*3 - 2];
       }
    //      D R A W   S T A C K
+      firstStackNumberDrawn = -1;
       for (iv = 1; iv < nv; ++iv) {
          for (i = 1; i <= 4; ++i) {
             xyz[i*3 - 1] = v[iv - 1];
@@ -2649,8 +2738,10 @@ L100:
             tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
             tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
             icodes[3] = i;
+            fEdgeIdx  = iv-1;
             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
          }
+         if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
       }
    //         D R A W   B O T T O M   F A C E
       if (ivis[4] != 0) {
@@ -2661,6 +2752,11 @@ L100:
             iface[i - 1] = 5 - i;
             tface[i - 1] = tt[5 - i - 1];
          }
+         if (!Hoption.Zero) fEdgeIdx = 0;
+         else {
+            fEdgeIdx = firstStackNumberDrawn;
+            fColorBottom = fColorMain[fEdgeIdx];
+         }
          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
       }
    //         D R A W   T O P   F A C E
@@ -2672,9 +2768,15 @@ L100:
             tface[i - 1] = tt[i + (nv << 2) - 5];
          }
          Int_t cs = fColorTop;
-         if ( nv > 2 && (v[nv-1] == v[nv-2])) {
-            for (iv = nv-1; iv>2; iv--) {
-               if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
+         if ( nv <= 3 ) fEdgeIdx = 0 ;  // no stack or stack with only one histo
+         else {
+            if ( nv > 2 && (v[nv-1] == v[nv-2])) {
+               for (iv = nv-1; iv>2; iv--) {
+                  if (v[nv-1] == v[iv-1]) {
+                     fColorTop = fColorMain[iv-2];
+                     fEdgeIdx = iv-2;
+                  }
+               }
             }
          }
          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
@@ -2752,6 +2854,7 @@ void TPainter3dAlgorithms::LegoCylindrical(Int_t iordr, Int_t na, Int_t nb, cons
    Double_t xyz[24];     // was [3][8]
    ia = ib = 0;
    TView *view = 0;
+   Int_t firstStackNumberDrawn=-1 ;  // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
 
    if (gPad) view = gPad->GetView();
    if (!view) {
@@ -2849,6 +2952,7 @@ L100:
          xyz[(j + 4)*3 - 1] = ab[jz + 2*i - 3];
       }
    //      D R A W   S T A C K
+      firstStackNumberDrawn = -1;
       for (iv = 1; iv < nv; ++iv) {
          for (i = 1; i <= 4; ++i) {
             xyz[i*3 - 3] = v[iv - 1]*cosphi[i - 1];
@@ -2872,8 +2976,10 @@ L100:
             tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
             tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
             icodes[3] = i;
+            fEdgeIdx = iv-1;
             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
          }
+         if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
       }
    //       D R A W   B O T T O M   F A C E
       if (ivis[4] != 0 && v[0] > 0) {
@@ -2885,6 +2991,11 @@ L100:
             iface[i - 1] = i;
             tface[i - 1] = tt[i - 1];
          }
+         if (!Hoption.Zero) fEdgeIdx = 0;
+         else {
+            fEdgeIdx = firstStackNumberDrawn;
+            fColorBottom = fColorMain[fEdgeIdx];
+         }
          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
       }
    //      D R A W   T O P   F A C E
@@ -2896,9 +3007,15 @@ L100:
             tface[i - 1] = tt[5 - i + (nv << 2) - 5];
          }
          Int_t cs = fColorTop;
-         if ( nv > 2 && (v[nv-1] == v[nv-2])) {
-            for (iv = nv-1; iv>2; iv--) {
-               if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
+         if ( nv <= 3 ) fEdgeIdx = 0 ;  // no stack or stack with only one histo
+         else {
+            if ( nv > 2 && (v[nv-1] == v[nv-2])) {
+               for (iv = nv-1; iv>2; iv--) {
+                  if (v[nv-1] == v[iv-1]) {
+                     fColorTop = fColorMain[iv-2];
+                     fEdgeIdx = iv-2;
+                  }
+               }
             }
          }
          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
@@ -2974,6 +3091,7 @@ void TPainter3dAlgorithms::LegoSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int
    Double_t phi1, phi2;
    ia = ib = 0;
    TView *view = 0;
+   Int_t firstStackNumberDrawn=-1 ;  // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
 
    if (gPad) view = gPad->GetView();
    if (!view) {
@@ -3102,6 +3220,7 @@ L200:
       cosphi[j - 1] = TMath::Cos(kRad*ab[jphi + 2*i - 3]);
       sinphi[j - 1] = TMath::Sin(kRad*ab[jphi + 2*i - 3]);
    }
+   firstStackNumberDrawn = -1;
    for (iv = 1; iv < nv; ++iv) {
       if (ipsdr == 1) {
          for (i = 1; i <= 4; ++i) {
@@ -3138,8 +3257,10 @@ L200:
          tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
          tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
          icodes[3] = i;
+         fEdgeIdx = iv-1;
          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
       }
+      if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
    }
    //      D R A W   B O T T O M   F A C E
    if (ivis[4] != 0 && v[0] > 0) {
@@ -3158,6 +3279,11 @@ L200:
          iface[i - 1] = 5 - i;
          tface[i - 1] = tt[5 - i - 1];
       }
+      if (!Hoption.Zero) fEdgeIdx = 0;
+      else {
+         fEdgeIdx = firstStackNumberDrawn;
+         fColorBottom = fColorMain[fEdgeIdx];
+      }
       (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
    }
    //      D R A W   T O P   F A C E
@@ -3169,9 +3295,15 @@ L200:
          tface[i - 1] = tt[i + 4 + 2*nv - 5];
       }
       Int_t cs = fColorTop;
-      if ( nv > 2 && (v[nv-1] == v[nv-2])) {
-         for (iv = nv-1; iv>2; iv--) {
-            if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
+      if ( nv <= 3 ) fEdgeIdx = 0 ;  // no stack or stack with only one histo
+      else {
+         if ( nv > 2 && (v[nv-1] == v[nv-2])) {
+            for (iv = nv-1; iv>2; iv--) {
+               if (v[nv-1] == v[iv-1]) {
+                  fColorTop = fColorMain[iv-2];
+                  fEdgeIdx  = iv-2;
+               }
+            }
          }
       }
       (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
@@ -3500,6 +3632,18 @@ void TPainter3dAlgorithms::SetColorMain(Color_t color, Int_t n)
 
 
 //______________________________________________________________________________
+void TPainter3dAlgorithms::SetEdgeAtt(Color_t color, Style_t style, Width_t width, Int_t n)
+{
+
+   // Store edge attributes
+
+   fEdgeColor[n] = color;
+   fEdgeStyle[n] = style;
+   fEdgeWidth[n] = width;
+}
+
+
+//______________________________________________________________________________
 void TPainter3dAlgorithms::SideVisibilityDecode(Double_t val, Int_t &iv1, Int_t &iv2, Int_t &iv3, Int_t &iv4, Int_t &iv5, Int_t &iv6, Int_t &ir)
 {
    // Decode side visibilities and order along R for sector
@@ -3666,7 +3810,7 @@ void TPainter3dAlgorithms::SurfaceCartesian(Double_t ang, Int_t nx, Int_t ny, co
    Double_t cosa, sina, f[12]        /* was [3][4] */;
    Int_t i, incrx, incry, i1, ix, iy;
    Double_t tt[4];
-   Int_t icodes[2], ix1, iy1, ix2, iy2;
+   Int_t icodes[3], ix1, iy1, ix2, iy2;  // was icode[2]. One element more to differentiate front & back boxes from data
    Double_t xyz[12]        /* was [3][4] */;
    Double_t *tn;
 
@@ -3702,6 +3846,8 @@ void TPainter3dAlgorithms::SurfaceCartesian(Double_t ang, Int_t nx, Int_t ny, co
    iy2 = ny - iy1 + 1;
 
    //          D R A W   S U R F A C E
+   icodes[2] = -1;   // -1 for data, 0 for front a back boxes
+   fEdgeIdx = 0;   // constant since stacks are not (yet?) handled for surfaces
    THistPainter *painter = (THistPainter*)gCurrentHist->GetPainter();
    for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
       for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
@@ -3822,7 +3968,7 @@ void TPainter3dAlgorithms::SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Doub
    //          first channel should be used. */
       icx = ixt + ixa;
       if (icx > Hparam.xlast) icx = 1;
-      f[i*3+3] = Hparam.factor*gCurrentHist->GetCellContent(icx, iyt + iya);
+      f[i*3+3] = Hparam.factor*gCurrentHist->GetBinContent(icx, iyt + iya);
       if (Hoption.Logz) {
          if (f[i*3+3] > 0) f[i*3+3] = TMath::Log10(f[i*3+3]);
          else              f[i*3+3] = Hparam.zmin;
@@ -3834,7 +3980,7 @@ void TPainter3dAlgorithms::SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Doub
       }
 
    // The colors on the surface can represent the content or the errors.
-   // if (fSumw2.fN) t[i] = gCurrentHist->GetCellError(icx, iyt + iya);
+   // if (fSumw2.fN) t[i] = gCurrentHist->GetBinError(icx, iyt + iya);
    // else           t[i] = f[i * 3 + 3];
       t[i] = f[i * 3 + 3];
    }
@@ -3897,7 +4043,7 @@ void TPainter3dAlgorithms::SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const c
    Double_t f[12]        /* was [3][4] */;
    Int_t i, j, incrr, ir1, ir2;
    Double_t z;
-   Int_t ia, ib, ir, jr, nr, icodes[2];
+   Int_t ia, ib, ir, jr, nr, icodes[3];  // was icode[2]. One element more to differentiate front & back boxes from data
    Double_t tt[4];
    Double_t phi, ttt[4], xyz[12]        /* was [3][4] */;
    ia = ib = 0;
@@ -3936,6 +4082,8 @@ void TPainter3dAlgorithms::SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const c
    view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
 
    //       D R A W   S U R F A C E
+   icodes[2] = -1;   // -1 for data, 0 for front a back boxes
+   fEdgeIdx = 0;   // constant since stacks are not (yet?) handled for surfaces
    incr = 1;
    iphi = iphi1;
 L100:
@@ -4032,7 +4180,7 @@ void TPainter3dAlgorithms::SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, c
 
    Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
    Int_t i, j, incrz, nz, iz1, iz2;
-   Int_t ia, ib, iz, jz, icodes[2];
+   Int_t ia, ib, iz, jz, icodes[3];  // was icode[2]. One element more to differentiate front & back boxes from data
    Double_t f[12]        /* was [3][4] */;
    Double_t z;
    Double_t tt[4];
@@ -4090,6 +4238,8 @@ void TPainter3dAlgorithms::SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, c
    iz2 = nz - iz1 + 1;
 
    //       D R A W   S U R F A C E
+   icodes[2] = -1;   // -1 for data, 0 for front a back boxes
+   fEdgeIdx = 0;   // constant since stacks are not (yet?) handled for surfaces
    incr = 1;
    iphi = iphi1;
 L100:
@@ -4164,7 +4314,7 @@ void TPainter3dAlgorithms::SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na,
 
    Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
    Int_t i, j, incrth, ith, jth, kth, nth, mth, ith1, ith2;
-   Int_t ia, ib, icodes[2];
+   Int_t ia, ib, icodes[3];  // was icode[2]. One element more to differentiate front & back boxes from data
    Double_t f[12]        /* was [3][4] */;
    Double_t tt[4];
    Double_t phi;
@@ -4231,6 +4381,8 @@ void TPainter3dAlgorithms::SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na,
    }
 
    //       D R A W   S U R F A C E
+   icodes[2] = -1;   // -1 for data, 0 for front a back boxes
+   fEdgeIdx = 0;   // constant since stacks are not (yet?) handled for surfaces
    kth  = nth;
    incr = 1;
    iphi = iphi1;
@@ -5073,7 +5225,6 @@ L300:
    MarchingCubeSurfacePenetration(fF8[3], fF8[2], fF8[6], fF8[7],
                                   fF8[0], fF8[1], fF8[5], fF8[4], irep);
    if (irep != 2) goto L400;
-///   IHMCTT(NTRIA,IT8,ITRIA)
    ntria = 9;
    icase = 9;
 
diff --git a/io/io/src/TDirectoryFile.cxx b/io/io/src/TDirectoryFile.cxx
index 55e4a2a..0010288 100644
--- a/io/io/src/TDirectoryFile.cxx
+++ b/io/io/src/TDirectoryFile.cxx
@@ -1788,7 +1788,7 @@ Int_t TDirectoryFile::WriteTObject(const TObject *obj, const char *name, Option_
    // Remove trailing blanks in object name
    Int_t nch = strlen(oname);
    char *newName = 0;
-   if (oname[nch-1] == ' ') {
+   if (nch && oname[nch-1] == ' ') {
       newName = new char[nch+1];
       strlcpy(newName,oname,nch+1);
       for (Int_t i=0;i<nch;i++) {
@@ -1912,7 +1912,7 @@ Int_t TDirectoryFile::WriteObjectAny(const void *obj, const TClass *cl, const ch
    // Remove trailing blanks in object name
    Int_t nch = strlen(oname);
    char *newName = 0;
-   if (oname[nch-1] == ' ') {
+   if (nch && oname[nch-1] == ' ') {
       newName = new char[nch+1];
       strlcpy(newName,oname,nch+1);
       for (Int_t i=0;i<nch;i++) {
diff --git a/io/io/src/TGenCollectionProxy.cxx b/io/io/src/TGenCollectionProxy.cxx
index 75db28c..4c2a9fa 100644
--- a/io/io/src/TGenCollectionProxy.cxx
+++ b/io/io/src/TGenCollectionProxy.cxx
@@ -862,7 +862,7 @@ Int_t TGenCollectionProxy::GetCollectionType() const
 {
    // Return the type of collection see TClassEdit::ESTLType
 
-   if (!fClass) {
+   if (!fValue) {
       Initialize(kFALSE);
    }
    return fSTL_type;
diff --git a/io/io/src/TStreamerInfo.cxx b/io/io/src/TStreamerInfo.cxx
index 944e4be..28d7860 100644
--- a/io/io/src/TStreamerInfo.cxx
+++ b/io/io/src/TStreamerInfo.cxx
@@ -90,7 +90,6 @@ static void R__TObjArray_InsertAt(TObjArray *arr, TObject *obj, Int_t at)
    arr->AddAt( obj, at);
 }
 
-#if 0
 static void R__TObjArray_InsertAfter(TObjArray *arr, TObject *newobj, TObject *oldobj)
 {
    // Slide by one.
@@ -99,12 +98,9 @@ static void R__TObjArray_InsertAfter(TObjArray *arr, TObject *newobj, TObject *o
    while (at<last && arr->At(at) != oldobj) {
       ++at;
    }
-   if (at!=0) {
-      ++at; // we found the object, insert after it
-   }
+   ++at; // we found the object, insert after it
    R__TObjArray_InsertAt(arr, newobj, at);
 }
-#endif
 
 static void R__TObjArray_InsertBefore(TObjArray *arr, TObject *newobj, TObject *oldobj)
 {
@@ -218,8 +214,14 @@ void TStreamerInfo::Build()
    fIsBuilt = kTRUE;
 
    if (fClass->GetCollectionProxy()) {
-      //FIXME: What about arrays of STL containers?
-      TStreamerElement* element = new TStreamerSTL("This", "Used to call the proper TStreamerInfo case", 0, fClass->GetName(), fClass->GetName(), 0);
+      TVirtualCollectionProxy *proxy = fClass->GetCollectionProxy();
+      TString title;
+      if (proxy->GetValueClass()) {
+         title.Form("<%s%s> Used to call the proper TStreamerInfo case",proxy->GetValueClass()->GetName(),proxy->HasPointers() ? "*" : "");
+      } else {
+         title .Form("<%s%s> Used to call the proper TStreamerInfo case",TDataType::GetTypeName(proxy->GetType()),proxy->HasPointers() ? "*" : "");
+      }
+      TStreamerElement* element = new TStreamerSTL("This", title.Data(), 0, fClass->GetName(), *proxy, 0);
       fElements->Add(element);
       Compile();
       return;
@@ -256,7 +258,9 @@ void TStreamerInfo::Build()
       if (!strcmp(bname, "string")) {
          element = new TStreamerSTLstring(bname, btitle, offset, bname, kFALSE);
       } else if (base->IsSTLContainer()) {
-         element = new TStreamerSTL(bname, btitle, offset, bname, 0, kFALSE);
+         TVirtualCollectionProxy *proxy = base->GetClassPointer()->GetCollectionProxy();
+         if (proxy) element = new TStreamerSTL(bname, btitle, offset, bname, *proxy, kFALSE);
+         else       element = new TStreamerSTL(bname, btitle, offset, bname, 0, kFALSE);
          if (fClass->IsLoaded() && ((TStreamerSTL*)element)->GetSTLtype() != TClassEdit::kVector) {
             if (!element->GetClassPointer()->IsLoaded()) {
                Error("Build","The class \"%s\" is compiled and its base class \"%s\" is a collection and we do not have a dictionary for it, we will not be able to read or write this base class.",GetName(),bname);
@@ -389,7 +393,9 @@ void TStreamerInfo::Build()
          if (!strcmp(dmType, "string") || !strcmp(dmType, full_string_name)) {
             element = new TStreamerSTLstring(dmName, dmTitle, offset, dmFull, dmIsPtr);
          } else if (dm->IsSTLContainer()) {
-            element = new TStreamerSTL(dmName, dmTitle, offset, dmFull, dm->GetTrueTypeName(), dmIsPtr);
+            TVirtualCollectionProxy *proxy = TClass::GetClass(dm->GetTypeName() /* the underlying type */)->GetCollectionProxy();
+            if (proxy) element = new TStreamerSTL(dmName, dmTitle, offset, dmFull, *proxy, dmIsPtr);
+            else element = new TStreamerSTL(dmName, dmTitle, offset, dmFull, dm->GetTrueTypeName(), dmIsPtr);
             if (fClass->IsLoaded() && ((TStreamerSTL*)element)->GetSTLtype() != TClassEdit::kVector) {
                if (!element->GetClassPointer()->IsLoaded()) {
                   Error("Build","The class \"%s\" is compiled and for its the data member \"%s\", we do not have a dictionary for the collection \"%s\", we will not be able to read or write this data member.",GetName(),dmName,element->GetClassPointer()->GetName());
@@ -473,6 +479,15 @@ void TStreamerInfo::Build()
             cached = copy;
 
             // Warning("BuildOld","%s::%s is not set from the version %d of %s (You must add a rule for it)\n",GetName(), element->GetName(), GetClassVersion(), GetName() );
+         } else {
+            // If the element is just cached and not repeat, we need to inject an element
+            // to insure the writing.
+            TStreamerElement *writecopy = (TStreamerElement*)element->Clone();
+            fElements->Add(element);
+            writecopy->SetBit(TStreamerElement::kWrite);
+            writecopy->SetNewType( writecopy->GetType() );
+            // Put the write element after the read element (that does caching).
+            element = writecopy;
          }
          cached->SetBit(TStreamerElement::kCache);
          cached->SetNewType( cached->GetType() );
@@ -544,7 +559,45 @@ void TStreamerInfo::BuildCheck()
       fClass = new TClass(GetName(), fClassVersion, 0, 0, -1, -1);
       fClass->SetBit(TClass::kIsEmulation);
       array = fClass->GetStreamerInfos();
-   } else {
+     
+      // Case of a custom collection (the user provided a CollectionProxy
+      // for a class that is not an STL collection).
+      if (GetElements()->GetEntries() == 1) {
+         TObject *element = GetElements()->UncheckedAt(0);
+         Bool_t isstl = element && strcmp("This",element->GetName())==0;
+         if (isstl) {
+            if (element->GetTitle()[0] == '<') {
+               // We know the content.
+               TString content = element->GetTitle();
+               Int_t level = 1;
+               for(Int_t c = 1; c < content.Length(); ++c) {
+                  if (content[c] == '<') ++level;
+                  else if (content[c] == '>') --level;
+                  if (level == 0) {
+                     content.Remove(c+1);
+                     break;
+                  }
+               }
+               content.Prepend("vector");
+               TClass *clequiv = TClass::GetClass(content);
+               TVirtualCollectionProxy *proxy = clequiv->GetCollectionProxy();
+               if (gDebug > 1)
+                  Info("BuildCheck",
+                       "Update the collection proxy of the class \"%s\" \n"
+                       "\tto be similar to \"%s\".",
+                    GetName(),content.Data());
+               fClass->CopyCollectionProxy( *proxy );
+            } else {
+               Warning("BuildCheck", "\n\
+   The class %s had a collection proxy when written but it is not an STL\n \
+   collection and we did not record the type of the content of the collection.\n \
+   We will claim the content is a bool (i.e. no data will be read).",
+                       GetName());
+            }
+         }
+      }
+
+  } else {
       if (TClassEdit::IsSTLCont(fClass->GetName())) {
          SetBit(kCanDelete);
          return;
@@ -561,6 +614,45 @@ void TStreamerInfo::BuildCheck()
          ::Warning("TClass::TClass", "no dictionary for class %s is available", GetName());
       }
 
+      // Case of a custom collection (the user provided a CollectionProxy
+      // for a class that is not an STL collection).
+      if (GetElements()->GetEntries() == 1) {
+         TObject *element = GetElements()->UncheckedAt(0);
+         Bool_t isstl = element && strcmp("This",element->GetName())==0;
+         if (isstl && !fClass->GetCollectionProxy()) {
+            if (element->GetTitle()[0] == '<') {
+               // We know the content.
+               TString content = element->GetTitle();
+               Int_t level = 1;
+               for(Int_t c = 1; c < content.Length(); ++c) {
+                  if (content[c] == '<') ++level;
+                  else if (content[c] == '>') --level;
+                  if (level == 0) {
+                     content.Remove(c+1);
+                     break;
+                  }
+               }
+               content.Prepend("vector");
+               TClass *clequiv = TClass::GetClass(content);
+               TVirtualCollectionProxy *proxy = clequiv->GetCollectionProxy();
+               if (gDebug > 1)
+                  Info("BuildCheck",
+                       "Update the collection proxy of the class \"%s\" \n"
+                       "\tto be similar to \"%s\".",
+                    GetName(),content.Data());
+               fClass->CopyCollectionProxy( *proxy );
+            } else {
+               Warning("BuildCheck", "\n\
+   The class %s had a collection proxy when written but it is not an STL\n \
+   collection and we did not record the type of the content of the collection.\n \
+   We will claim the content is a bool (i.e. no data will be read).",
+                       GetName());
+            }
+            SetBit(kCanDelete);
+            return;         
+         }
+      }
+
       // If the user has not specified a class version (this _used to_
       // always be the case when the class is Foreign) or if the user
       // has specified a version to be explicitly 1. [We can not
@@ -1858,16 +1950,26 @@ void TStreamerInfo::BuildOld()
 
             // Now that we are caching the unconverted element, we do not assign it to the real type even if we could have!
             if (element->GetNewType()>0 /* intentionally not including base class for now */
-                && !rules->HasRuleWithTarget( element->GetName(), kTRUE ) )
-               {
-                  TStreamerElement *copy = (TStreamerElement*)element->Clone();
-                  R__TObjArray_InsertBefore( fElements, copy, element );
-                  next(); // move the cursor passed the insert object.
-                  copy->SetBit(TStreamerElement::kRepeat);
-                  element = copy;
-
-                  // Warning("BuildOld","%s::%s is not set from the version %d of %s (You must add a rule for it)\n",GetName(), element->GetName(), GetClassVersion(), GetName() );
-               }
+                && !rules->HasRuleWithTarget( element->GetName(), kTRUE ) ) {
+
+               TStreamerElement *copy = (TStreamerElement*)element->Clone();
+               R__TObjArray_InsertBefore( fElements, copy, element );
+               next(); // move the cursor passed the insert object.
+               copy->SetBit(TStreamerElement::kRepeat);
+               element = copy;
+               
+               // Warning("BuildOld","%s::%s is not set from the version %d of %s (You must add a rule for it)\n",GetName(), element->GetName(), GetClassVersion(), GetName() );
+            } else {
+               // If the element is just cached and not repeat, we need to inject an element
+               // to insure the writing.
+               TStreamerElement *writecopy = (TStreamerElement*)element->Clone();
+               R__TObjArray_InsertAfter( fElements, writecopy, element );
+               next(); // move the cursor passed the insert object.
+               writecopy->SetBit(TStreamerElement::kWrite);
+               writecopy->SetNewType( writecopy->GetType() );
+               writecopy->SetBit(TStreamerElement::kCache);
+               writecopy->SetOffset(infoalloc ? infoalloc->GetOffset(element->GetName()) : 0);
+            }
             element->SetBit(TStreamerElement::kCache);
             element->SetNewType( element->GetType() );
             element->SetOffset(infoalloc ? infoalloc->GetOffset(element->GetName()) : 0);
@@ -1875,6 +1977,23 @@ void TStreamerInfo::BuildOld()
             // The data member exist in the onfile StreamerInfo and there is a rule
             // that has the same member 'only' has a target ... so this means we are
             // asked to ignore the input data ...
+            if (element->GetType() == kCounter) {
+               // If the element is a counter, we will need its value to read
+               // other data member, so let's do so (by not disabling it) even
+               // if the value will be over-written by a rule.
+            } else {
+               element->SetOffset(kMissing);
+            }
+         }
+      } else if (rules && rules->HasRuleWithTarget( element->GetName(), kTRUE ) ) {
+         // The data member exist in the onfile StreamerInfo and there is a rule
+         // that has the same member 'only' has a target ... so this means we are
+         // asked to ignore the input data ...
+         if (element->GetType() == kCounter) {
+            // If the element is a counter, we will need its value to read
+            // other data member, so let's do so (by not disabling it) even
+            // if the value will be over-written by a rule.
+         } else {
             element->SetOffset(kMissing);
          }
       }
@@ -3615,26 +3734,15 @@ void TStreamerInfo::ls(Option_t *option) const
    }
    for (Int_t i=0;i < fNdata;i++) {
       TStreamerElement *element = (TStreamerElement*)fElem[i];
-      TString sequenceType = " [";
-      Bool_t first = kTRUE;
-      if (element->TestBit(TStreamerElement::kCache)) {
-         first = kFALSE;
-         sequenceType += "cached";
-      }
-      if (element->TestBit(TStreamerElement::kRepeat)) {
-         if (!first) sequenceType += ",";
-         first = kFALSE;
-         sequenceType += "repeat";
-      }
-      if (element->TestBit(TStreamerElement::kDoNotDelete)) {
-         if (!first) sequenceType += ",";
-         first = kFALSE;
-         sequenceType += "nodelete";
-      }
-      if (first) sequenceType.Clear();
-      else sequenceType += "]";
-
-      Printf("   i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",i,element->GetName(),fType[i],fOffset[i],fLength[i],fMethod[i],sequenceType.Data());
+      TString sequenceType;
+      element->GetSequenceType(sequenceType);
+      if (sequenceType.Length()) {
+         sequenceType.Prepend(" [");
+         sequenceType += "]";
+      }
+      Printf("   i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",
+             i,element->GetName(),fType[i],fOffset[i],fLength[i],fMethod[i],
+             sequenceType.Data());
    }
 }
 
@@ -4184,6 +4292,8 @@ void TStreamerInfo::Streamer(TBuffer &R__b)
             el = (TStreamerElement*)fElements->UncheckedAt(i);
             if( el != 0 && (el->IsA() == TStreamerArtificial::Class() || el->TestBit(TStreamerElement::kRepeat))) {
                fElements->RemoveAt( i );
+            } else if( el !=0 && (el->TestBit(TStreamerElement::kCache) && !el->TestBit(TStreamerElement::kWrite)) ) {
+               fElements->RemoveAt( i );
             }
          }
          fElements->Compress();
diff --git a/io/io/src/TStreamerInfoActions.cxx b/io/io/src/TStreamerInfoActions.cxx
index 2686ee9..f64f861 100644
--- a/io/io/src/TStreamerInfoActions.cxx
+++ b/io/io/src/TStreamerInfoActions.cxx
@@ -79,11 +79,13 @@ namespace TStreamerInfoActions
 
       TStreamerInfo *info = (TStreamerInfo*)fInfo;
       TStreamerElement *aElement = (TStreamerElement*)info->GetElems()[fElemId];
+      TString sequenceType;
+      aElement->GetSequenceType(sequenceType);
 
       printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
-             " %s, offset=%d\n",
+             " %s, offset=%d (%s)\n",
              info->GetClass()->GetName(), aElement->GetName(), fElemId, info->GetTypes()[fElemId],
-             aElement->ClassName(), fOffset);
+             aElement->ClassName(), fOffset, sequenceType.Data());
    }
 
    void TConfiguration::PrintDebug(TBuffer &buf, void *addr) const
@@ -94,11 +96,13 @@ namespace TStreamerInfoActions
          // Idea: We should print the name of the action function.
          TStreamerInfo *info = (TStreamerInfo*)fInfo;
          TStreamerElement *aElement = (TStreamerElement*)info->GetElems()[fElemId];
-
+         TString sequenceType;
+         aElement->GetSequenceType(sequenceType);
+      
          printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
-                " %s, bufpos=%d, arr=%p, offset=%d\n",
+                " %s, bufpos=%d, arr=%p, offset=%d (%s)\n",
                 info->GetClass()->GetName(), aElement->GetName(), fElemId, info->GetTypes()[fElemId],
-                aElement->ClassName(), buf.Length(), addr, fOffset);
+                aElement->ClassName(), buf.Length(), addr, fOffset, sequenceType.Data());
       }
    }
 
@@ -134,11 +138,13 @@ namespace TStreamerInfoActions
       void PrintDebug(TBuffer &, void *) const {
          TStreamerInfo *info = (TStreamerInfo*)fInfo;
          TStreamerElement *aElement = (TStreamerElement*)info->GetElems()[fElemId];
+         TString sequenceType;
+         aElement->GetSequenceType(sequenceType);
 
          printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
-                " %s, offset=%d\n",
+                " %s, offset=%d (%s)\n",
                 info->GetClass()->GetName(), aElement->GetName(), fElemId, info->GetTypes()[fElemId],
-                aElement->ClassName(), fOffset);
+                aElement->ClassName(), fOffset, sequenceType.Data());
       }
 
       void AddToOffset(Int_t delta)
@@ -2494,6 +2500,8 @@ void TStreamerInfo::AddReadAction(Int_t i, TStreamerElement* element)
 {
    // Add a read action for the given element.
 
+   if (element->TestBit(TStreamerElement::kWrite)) return;
+
    switch (fType[i]) {
       // read basic types
       case TStreamerInfo::kBool:    fReadObjectWise->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,fOffset[i]) );    break;
@@ -2728,8 +2736,16 @@ void TStreamerInfo::AddReadAction(Int_t i, TStreamerElement* element)
 }
 
 //______________________________________________________________________________
-void TStreamerInfo::AddWriteAction(Int_t i, TStreamerElement* /*element*/ )
+void TStreamerInfo::AddWriteAction(Int_t i, TStreamerElement *element )
 {
+   if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
+      // Skip element cached for reading purposes.
+      return;
+   }
+   if (element->GetType() >= kArtificial &&  !element->TestBit(TStreamerElement::kWrite)) {
+      // Skip artificial element used for reading purposes.
+      return;
+   }
    switch (fType[i]) {
       // write basic types
       case TStreamerInfo::kBool:    fWriteObjectWise->AddAction( WriteBasicType<Bool_t>, new TConfiguration(this,i,fOffset[i]) );    break;
@@ -2889,6 +2905,10 @@ TStreamerInfoActions::TActionSequence *TStreamerInfoActions::TActionSequence::Cr
          // when it is making branches for a split object.
          continue;
       }
+      if (element->TestBit(TStreamerElement::kWrite)) {
+         // Skip element that only for writing.
+         continue;
+      }
       Int_t asize = element->GetSize();
       if (element->GetArrayLength()) {
          asize /= element->GetArrayLength();
@@ -2988,6 +3008,14 @@ TStreamerInfoActions::TActionSequence *TStreamerInfoActions::TActionSequence::Cr
             // when it is making branches for a split object.
             continue;
          }
+         if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
+            // Skip element cached for reading purposes.
+            continue;
+         }
+         if (element->GetType() >= TVirtualStreamerInfo::kArtificial &&  !element->TestBit(TStreamerElement::kWrite)) {
+            // Skip artificial element used for reading purposes.
+            continue;
+         }
          Int_t asize = element->GetSize();
          if (element->GetArrayLength()) {
             asize /= element->GetArrayLength();
@@ -3105,7 +3133,8 @@ void TStreamerInfoActions::TActionSequence::AddToOffset(Int_t delta)
        iter != end;
        ++iter) 
    {
-      iter->fConfiguration->AddToOffset(delta);
+      if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
+         iter->fConfiguration->AddToOffset(delta);
    }
 }
 
@@ -3145,7 +3174,8 @@ TStreamerInfoActions::TActionSequence *TStreamerInfoActions::TActionSequence::Cr
              ++iter) 
          {
             TConfiguration *conf = iter->fConfiguration->Copy();
-            conf->AddToOffset(offset);
+            if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
+               conf->AddToOffset(offset);
             sequence->AddAction( iter->fAction, conf );
          }
       } else {
@@ -3155,7 +3185,8 @@ TStreamerInfoActions::TActionSequence *TStreamerInfoActions::TActionSequence::Cr
              ++iter) {
             if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
                TConfiguration *conf = iter->fConfiguration->Copy();
-               conf->AddToOffset(offset);
+               if (!iter->fConfiguration->fInfo->GetElements()->At(iter->fConfiguration->fElemId)->TestBit(TStreamerElement::kCache))
+                  conf->AddToOffset(offset);
                sequence->AddAction( iter->fAction, conf );
             }
          }
diff --git a/io/io/src/TStreamerInfoReadBuffer.cxx b/io/io/src/TStreamerInfoReadBuffer.cxx
index 296c6d7..bf9aa74 100644
--- a/io/io/src/TStreamerInfoReadBuffer.cxx
+++ b/io/io/src/TStreamerInfoReadBuffer.cxx
@@ -816,6 +816,8 @@ Int_t TStreamerInfo::ReadBuffer(TBuffer &b, const T &arr, Int_t first,
       TStreamerElement * aElement  = (TStreamerElement*)fElem[i];
       fgElement = aElement;
 
+      if (aElement->TestBit(TStreamerElement::kWrite)) continue;
+
       if (R__TestUseCache<T>(aElement)) {
          Int_t bufpos = b.Length();
          if (((TBufferFile&)b).PeekDataCache()==0) {
diff --git a/io/xml/src/TXMLEngine.cxx b/io/xml/src/TXMLEngine.cxx
index 1bd040a..d878f0a 100644
--- a/io/xml/src/TXMLEngine.cxx
+++ b/io/xml/src/TXMLEngine.cxx
@@ -1,4 +1,4 @@
-// @(#)root/xml:$Id$
+// @(#)root/xml:$Id: 1bd040ac1c03c58bcad15b5206d602680a831c0a $
 // Author: Sergey Linev  10.05.2004
 
 /*************************************************************************
@@ -98,6 +98,7 @@ public:
    {
       if (fCurrent!=fBuf) OutputCurrent();
       delete fOut;
+      free(fBuf);
    }
 
    void OutputCurrent()
@@ -273,14 +274,14 @@ public:
 
    Bool_t SkipSpaces(Bool_t tillendl = kFALSE)
    {
-      do {
+      while (fCurrent<fMaxAddr) {
          char symb = *fCurrent;
          if ((symb>26) && (symb!=' ')) return kTRUE;
 
          if (!ShiftCurrent()) return kFALSE;
 
          if (tillendl && (symb==10)) return kTRUE;
-      } while (fCurrent<fMaxAddr);
+      }
       return kFALSE;
    }
 
diff --git a/math/mathcore/inc/Math/OneDimFunctionAdapter.h b/math/mathcore/inc/Math/OneDimFunctionAdapter.h
index d74b212..f060f7d 100644
--- a/math/mathcore/inc/Math/OneDimFunctionAdapter.h
+++ b/math/mathcore/inc/Math/OneDimFunctionAdapter.h
@@ -102,8 +102,11 @@ public:
       clone
    */
    virtual OneDimMultiFunctionAdapter * Clone( ) const { 
-      if (fOwn) 
-         return new OneDimMultiFunctionAdapter( fFunc, fDim, fCoord, fParams); 
+      if (fOwn) { 
+         OneDimMultiFunctionAdapter * f =  new OneDimMultiFunctionAdapter( fFunc, fDim, fCoord, fParams); 
+         std::copy(fX, fX+fDim, f->fX); 
+         return f; 
+      }
       else 
          return new OneDimMultiFunctionAdapter( fFunc, fX, fCoord, fParams); 
    }
diff --git a/math/minuit/src/TMinuitMinimizer.cxx b/math/minuit/src/TMinuitMinimizer.cxx
index c87c953..0bfbfff 100644
--- a/math/minuit/src/TMinuitMinimizer.cxx
+++ b/math/minuit/src/TMinuitMinimizer.cxx
@@ -671,6 +671,13 @@ bool TMinuitMinimizer::GetMinosError(unsigned int i, double & errLow, double & e
       return false; 
    }
 
+   // check if parameter is fixed
+   if (fMinuit->fNiofex[i] == 0 ) { 
+      if (PrintLevel() > 0) Info("TMinuitMinimizer::GetMinosError","Parameter %s is fixed. There are no Minos error to calculate. Ignored.",VariableName(i).c_str());
+      errLow = 0; errUp = 0;
+      return true;
+   } 
+
    double arglist[2];
    int ierr = 0; 
 
diff --git a/math/smatrix/inc/Math/CholeskyDecomp.h b/math/smatrix/inc/Math/CholeskyDecomp.h
index 4a3cd7b..2d3e3f4 100644
--- a/math/smatrix/inc/Math/CholeskyDecomp.h
+++ b/math/smatrix/inc/Math/CholeskyDecomp.h
@@ -16,6 +16,9 @@
  *	factored code to provide a nice Cholesky decomposition class, along
  *	with separate methods for solving a single linear system and to
  *	obtain the inverse matrix from the decomposition
+ * @data July 15th 2013
+ * 	provide a version of that class which works if the dimension of the
+ * 	problem is only known at run time
  */
 
 #include <cmath>
@@ -28,9 +31,13 @@ namespace ROOT {
 /// helpers for CholeskyDecomp
 namespace CholeskyDecompHelpers {
    // forward decls
+   template<class F, class M> struct _decomposerGenDim;
    template<class F, unsigned N, class M> struct _decomposer;
+   template<class F, class M> struct _inverterGenDim;
    template<class F, unsigned N, class M> struct _inverter;
+   template<class F, class V> struct _solverGenDim;
    template<class F, unsigned N, class V> struct _solver;
+   template<typename G> class PackedArrayAdapter;
 }
 
 /// class to compute the Cholesky decomposition of a matrix
@@ -72,21 +79,6 @@ private:
    F fL[N * (N + 1) / 2];
    /// flag indicating a successful decomposition
    bool fOk;
-   /// adapter for packed arrays (to SMatrix indexing conventions)
-   template<typename G> class PackedArrayAdapter
-   {
-   private:
-      G* fArr; ///< pointer to first array element
-   public:
-      /// constructor
-      PackedArrayAdapter(G* arr) : fArr(arr) {}
-      /// read access to elements (make sure that j <= i)
-      const G operator()(unsigned i, unsigned j) const
-      { return fArr[((i * (i + 1)) / 2) + j]; }
-      /// write access to elements (make sure that j <= i)
-      G& operator()(unsigned i, unsigned j)
-      { return fArr[((i * (i + 1)) / 2) + j]; }
-   };
 public:
    /// perform a Cholesky decomposition
    /** perfrom a Cholesky decomposition of a symmetric positive
@@ -118,6 +110,7 @@ public:
       fL(), fOk(false)
    {
       using CholeskyDecompHelpers::_decomposer;
+      using CholeskyDecompHelpers::PackedArrayAdapter;
       fOk = _decomposer<F, N, PackedArrayAdapter<G> >()(
          fL, PackedArrayAdapter<G>(m));
    }
@@ -171,6 +164,7 @@ public:
    template<typename G> bool Invert(G* m) const
    {
       using CholeskyDecompHelpers::_inverter;
+      using CholeskyDecompHelpers::PackedArrayAdapter;
       if (fOk) {
          PackedArrayAdapter<G> adapted(m);
          _inverter<F,N,PackedArrayAdapter<G> >()(adapted, fL);
@@ -179,14 +173,168 @@ public:
    }
 };
 
+/// class to compute the Cholesky decomposition of a matrix
+/** class to compute the Cholesky decomposition of a symmetric
+ * positive definite matrix when the dimensionality of the problem is not known
+ * at compile time
+ *
+ * provides routines to check if the decomposition succeeded (i.e. if
+ * matrix is positive definite and non-singular), to solve a linear
+ * system for the given matrix and to obtain its inverse
+ *
+ * the actual functionality is implemented in templated helper
+ * classes which have specializations for dimensions N = 1 to 6
+ * to achieve a gain in speed for common matrix sizes
+ *
+ * usage example:
+ * @code
+ * // let m be a symmetric positive definite SMatrix (use type float
+ * // for internal computations, matrix size is 4x4)
+ * CholeskyDecomp<float, 4> decomp(m);
+ * // check if the decomposition succeeded
+ * if (!decomp) {
+ *   std::cerr << "decomposition failed!" << std::endl;
+ * } else {
+ *   // let rhs be a vector; we seek a vector x such that m * x = rhs
+ *   decomp.Solve(rhs);
+ *   // rhs now contains the solution we are looking for
+ *
+ *   // obtain the inverse of m, put it into m itself
+ *   decomp.Invert(m);
+ * }
+ * @endcode
+ */
+template<class F> class CholeskyDecompGenDim
+{
+private:
+   /** @brief dimensionality
+    * dimensionality of the problem */
+   unsigned fN; 
+   /// lower triangular matrix L
+   /** lower triangular matrix L, packed storage, with diagonal
+    * elements pre-inverted */
+   F *fL;
+   /// flag indicating a successful decomposition
+   bool fOk;
+public:
+   /// perform a Cholesky decomposition
+   /** perfrom a Cholesky decomposition of a symmetric positive
+    * definite matrix m
+    *
+    * this is the constructor to uses with an SMatrix (and objects
+    * that behave like an SMatrix in terms of using
+    * operator()(int i, int j) for access to elements)
+    */
+   template<class M> CholeskyDecompGenDim(unsigned N, const M& m) : 
+      fN(N), fL(new F[(fN * (fN + 1)) / 2]), fOk(false)
+   {
+      using CholeskyDecompHelpers::_decomposerGenDim;
+      fOk = _decomposerGenDim<F, M>()(fL, m, fN);
+   }
+
+   /// perform a Cholesky decomposition
+   /** perfrom a Cholesky decomposition of a symmetric positive
+    * definite matrix m
+    * 
+    * this is the constructor to use in special applications where
+    * plain arrays are used
+    *
+    * NOTE: the matrix is given in packed representation, matrix
+    * element m(i,j) (j <= i) is supposed to be in array element
+    * (i * (i + 1)) / 2 + j
+    */
+   template<typename G> CholeskyDecompGenDim(unsigned N, G* m) : 
+      fN(N), fL(new F[(fN * (fN + 1)) / 2]), fOk(false)
+   {
+      using CholeskyDecompHelpers::_decomposerGenDim;
+      using CholeskyDecompHelpers::PackedArrayAdapter;
+      fOk = _decomposerGenDim<F, PackedArrayAdapter<G> >()(
+         fL, PackedArrayAdapter<G>(m), fN);
+   }
+
+   /// destructor
+   ~CholeskyDecompGenDim() { delete[] fL; }
+
+   /// returns true if decomposition was successful
+   /** @returns true if decomposition was successful */
+   bool ok() const { return fOk; }
+   /// returns true if decomposition was successful
+   /** @returns true if decomposition was successful */
+   operator bool() const { return fOk; }
+
+   /// solves a linear system for the given right hand side
+   /** solves a linear system for the given right hand side
+    *
+    * Note that you can use both SVector classes and plain arrays for
+    * rhs. (Make sure that the sizes match!). It will work with any vector 
+    * implementing the operator [i]
+    *
+    * @returns if the decomposition was successful
+    */
+   template<class V> bool Solve(V& rhs) const
+   {
+      using CholeskyDecompHelpers::_solverGenDim;
+      if (fOk) _solverGenDim<F,V>()(rhs, fL, fN); return fOk;
+   }
+
+   /// place the inverse into m
+   /** place the inverse into m
+    *
+    * This is the method to use with an SMatrix.
+    *
+    * @returns if the decomposition was successful
+    */
+   template<class M> bool Invert(M& m) const
+   {
+      using CholeskyDecompHelpers::_inverterGenDim;
+      if (fOk) _inverterGenDim<F,M>()(m, fL, fN); return fOk;
+   }
+
+   /// place the inverse into m
+   /** place the inverse into m
+    *
+    * This is the method to use with a plain array.
+    *
+    * @returns if the decomposition was successful
+    *
+    * NOTE: the matrix is given in packed representation, matrix
+    * element m(i,j) (j <= i) is supposed to be in array element
+    * (i * (i + 1)) / 2 + j
+    */
+   template<typename G> bool Invert(G* m) const
+   {
+      using CholeskyDecompHelpers::_inverterGenDim;
+      using CholeskyDecompHelpers::PackedArrayAdapter;
+      if (fOk) {
+         PackedArrayAdapter<G> adapted(m);
+         _inverterGenDim<F,PackedArrayAdapter<G> >()(adapted, fL, fN);
+      }
+      return fOk;
+   }
+};
 
 namespace CholeskyDecompHelpers {
-   /// struct to do a Cholesky decomposition
-   template<class F, unsigned N, class M> struct _decomposer
+   /// adapter for packed arrays (to SMatrix indexing conventions)
+   template<typename G> class PackedArrayAdapter
+   {
+   private:
+      G* fArr; ///< pointer to first array element
+   public:
+      /// constructor
+      PackedArrayAdapter(G* arr) : fArr(arr) {}
+      /// read access to elements (make sure that j <= i)
+      const G operator()(unsigned i, unsigned j) const
+      { return fArr[((i * (i + 1)) / 2) + j]; }
+      /// write access to elements (make sure that j <= i)
+      G& operator()(unsigned i, unsigned j)
+      { return fArr[((i * (i + 1)) / 2) + j]; }
+   };
+   /// struct to do a Cholesky decomposition (general dimensionality)
+   template<class F, class M> struct _decomposerGenDim
    {
       /// method to do the decomposition
       /** @returns if the decomposition was successful */
-      bool operator()(F* dst, const M& src) const
+      bool operator()(F* dst, const M& src, unsigned N) const
       {
          // perform Cholesky decomposition of matrix: M = L L^T
          // only thing that can go wrong: trying to take square
@@ -223,14 +371,23 @@ namespace CholeskyDecompHelpers {
       }
    };
 
-   /// struct to obtain the inverse from a Cholesky decomposition
-   template<class F, unsigned N, class M> struct _inverter
+   /// struct to do a Cholesky decomposition
+   template<class F, unsigned N, class M> struct _decomposer
+   {
+      /// method to do the decomposition
+      /** @returns if the decomposition was successful */
+      bool operator()(F* dst, const M& src) const
+      { return _decomposerGenDim<F, M>()(dst, src, N); }
+   };
+
+   /// struct to obtain the inverse from a Cholesky decomposition (general dimensionality)
+   template<class F, class M> struct _inverterGenDim
    {
       /// method to do the inversion
-      void operator()(M& dst, const F* src) const
+      void operator()(M& dst, const F* src, unsigned N) const
       {
          // make working copy
-         F l[N * (N + 1) / 2];
+         F * l = new F[N * (N + 1) / 2];
          std::copy(src, src + ((N * (N + 1)) / 2), l);
          // ok, next step: invert off-diagonal part of matrix
          F* base1 = &l[1];
@@ -254,14 +411,23 @@ namespace CholeskyDecompHelpers {
                dst(i, j) = tmp;
             }
          }
+         delete [] l;
       }
    };
 
-   /// struct to solve a linear system using its Cholesky decomposition
-   template<class F, unsigned N, class V> struct _solver
+   /// struct to obtain the inverse from a Cholesky decomposition
+   template<class F, unsigned N, class M> struct _inverter
+   {
+      /// method to do the inversion
+      void operator()(M& dst, const F* src) const
+      { return _inverterGenDim<F, M>()(dst, src, N); }
+   };
+
+   /// struct to solve a linear system using its Cholesky decomposition (generalised dimensionality)
+   template<class F, class V> struct _solverGenDim
    {
       /// method to solve the linear system
-      void operator()(V& rhs, const F* l) const
+      void operator()(V& rhs, const F* l, unsigned N) const
       {
          // solve Ly = rhs
          for (unsigned k = 0; k < N; ++k) {
@@ -283,6 +449,14 @@ namespace CholeskyDecompHelpers {
       }
    };
 
+   /// struct to solve a linear system using its Cholesky decomposition
+   template<class F, unsigned N, class V> struct _solver
+   {
+      /// method to solve the linear system
+      void operator()(V& rhs, const F* l) const
+      { _solverGenDim<F, V>()(rhs, l, N); }
+   };
+
    /// struct to do a Cholesky decomposition (specialized, N = 6)
    template<class F, class M> struct _decomposer<F, 6, M>
    {
diff --git a/net/netx/Module.mk b/net/netx/Module.mk
index 9fe7880..cd4f1fb 100644
--- a/net/netx/Module.mk
+++ b/net/netx/Module.mk
@@ -82,7 +82,7 @@ $(NETXLIB):     $(NETXO) $(NETXDO) $(ORDER_) $(MAINLIBS) $(NETXLIBDEP) \
 		   "$(SOFLAGS)" libNetx.$(SOEXT) $@ "$(NETXO) $(NETXDO)" \
 		   "$(NETXLIBEXTRA)"
 
-$(NETXDS):      $(NETXH1) $(NETXL) $(XROOTDMAKE) $(ROOTCINTTMPDEP) $(XRDPLUGINS)
+$(NETXDS):      $(NETXH) $(NETXL) $(XROOTDMAKE) $(ROOTCINTTMPDEP) $(XRDPLUGINS)
 		$(MAKEDIR)
 		@echo "Generating dictionary $@..."
 		$(ROOTCINTTMP) -f $@ -c $(NETXINCEXTRA) $(NETXH) $(NETXL)
diff --git a/proof/afdsmgrd/afdsmgrd-v1.0.6.tar.gz b/proof/afdsmgrd/afdsmgrd-v1.0.6.tar.gz
deleted file mode 100644
index a32db73..0000000
Binary files a/proof/afdsmgrd/afdsmgrd-v1.0.6.tar.gz and /dev/null differ
diff --git a/proof/afdsmgrd/afdsmgrd-v1.1.0.tar.gz b/proof/afdsmgrd/afdsmgrd-v1.1.0.tar.gz
new file mode 100644
index 0000000..5d862b5
Binary files /dev/null and b/proof/afdsmgrd/afdsmgrd-v1.1.0.tar.gz differ
diff --git a/proof/doc/confman/ConfigProofPoD.md b/proof/doc/confman/ConfigProofPoD.md
new file mode 100644
index 0000000..1430100
--- /dev/null
+++ b/proof/doc/confman/ConfigProofPoD.md
@@ -0,0 +1,194 @@
+Setup a static PROOF cluster with PROOF on Demand
+=================================================
+
+Introduction
+------------
+
+Using PROOF on Demand is our current recommended way of running a PROOF
+cluster. The usage of PoD is in particular helpful for the following
+reasons:
+
+-   **Sandboxing.** Each user get their own personal PROOF cluster,
+    separated from the others: a problem occurring on one personal
+    cluster does not affect the workflow of other users.
+
+-   **Easier administration and self-servicing.** A user can restart their
+    personal PROOF cluster in case of troubles without waiting for a
+    system administrator's intervention.
+
+-   **Efficient multiuser scheduling.** PROOF on Demand makes PROOF run on
+    top of an existing resource management system, moving the problem of
+    scheduling many concurrent users outside of PROOF.
+
+This guide particularly refers to the setup of a static PROOF cluster
+running on physical hosts: the recommended setup is in practice the same
+as the ready-to-go Virtual Analysis Facility. If you want to use PROOF
+on the clouds there is no configuration to go through.
+
+Setup a resource management system
+----------------------------------
+
+Although PROOF on Demand can run on a cluster of nodes without using a
+resource management system (using `pod-ssh`), it is recommended to setup a
+dedicated one to benefit from the scheduling in a multiuser environment, or a
+dedicated queue on an existing one.
+
+As there's a variety of resource management systems, this guide does not cover
+their setup. The RMS preconfigured for the Virtual Analysis Facility is
+[HTCondor](http://research.cs.wisc.edu/htcondor/), which we recommend primarily
+because it has dynamic addition of workers built in.
+
+Configuration steps for all nodes
+---------------------------------
+
+### Setup CernVM-FS
+
+[CernVM-FS](http://cernvm.cern.ch/portal/filesystem) should be installed
+on all machines as the preferred method for software distribution.
+
+> Configuration instructions for the latest CernVM-FS can be found
+> [here](http://cernvm.cern.ch/portal/filesystem/techinformation).
+
+A brief step-by-step procedure to install CernVM-FS is hereby described.
+
+-   Download and install the latest stable version from
+    [here](http://cernvm.cern.ch/portal/filesystem): pick one which is
+    appropriate to your operating system. You need the `cvmfs` package,
+    you *don't* need the `cvmfs-devel` or `cvmfs-server` ones.
+
+-   As root user, run:
+
+        # cvmfs_config setup
+
+-   Start the `autofs` service: how to to this depends on your operating
+    system.
+
+    On Ubuntu using Upstart:
+
+        # restart autofs
+
+    On RHEL-based or older Ubuntus:
+
+        # service autofs restart
+
+-   Prepare a `/etc/cvmfs/default.local` file (create it if it does not
+    exists) with the following configuration bits:
+
+    ``` {.bash}
+    CVMFS_HTTP_PROXY=http://your-proxy-server.domain.ch:3128,DIRECT
+    CVMFS_REPOSITORIES=your-experiment.cern.ch,sft.cern.ch
+    CVMFS_QUOTA_LIMIT=50000
+    ```
+
+    You need to properly specify your closest HTTP caching proxy:
+    separate many of them via commas. The last fallback value, `DIRECT`,
+    tells cvmfs to connect directly without using any proxy at all.
+
+    Among the list of repositories (comma-separated), always specify
+    `sft.cern.ch` and the one containing the software to your experiment
+    (e.g., `cms.cern.ch`).
+
+    The quota limit is, in Megabytes, the amount of local disk space to
+    use as cache.
+
+-   Check the configuration and repositories with:
+
+        # cvmfs_config chksetup
+        OK
+        # cvmfs_config probe
+        Probing /cvmfs/cms.cern.ch... OK
+        Probing /cvmfs/sft.cern.ch... OK
+
+> You might need special configurations for some custom software
+> repositories! Special cases are not covered in this guide.
+
+### Firewall configuration
+
+[PROOF on Demand](http://pod.gsi.de/) is very flexible in handling
+various cases of network topologies. The best solution would be to allow
+all TCP communications between the cluster machines.
+
+No other incoming communication is required from the outside.
+
+Configuration steps for the head node only
+------------------------------------------
+
+### Setup HTTPS+SSH (sshcertauth) authentication
+
+> Latest recommended sshcertauth version is 0.8.5.
+>
+> [Download](https://github.com/dberzano/sshcertauth/archive/v0.8.5.zip)
+> and [read the
+> instructions](http://newton.ph.unito.it/~berzano/w/doku.php?id=proof:sshcertauth).
+
+If you want your users to connect to the PROOF cluster using their Grid
+user certificate and private key you might be interested in installing
+sshcertauth. Please refer to the [installation
+guide](http://newton.ph.unito.it/~berzano/w/doku.php?id=proof:sshcertauth)
+for further information.
+
+### PROOF on Demand
+
+> Latest recommended PROOF on Demand version is 3.12.
+>
+> **On CernVM-FS:** `/cvmfs/sft.cern.ch/lcg/external/PoD/3.12`
+>
+> **Source code:** [PoD download page](http://pod.gsi.de/download.html)
+> and [Installation
+> instructions](http://pod.gsi.de/doc/3.12/Installation.html)
+
+[PROOF on Demand](http://pod.gsi.de/) is required on the head node and on the
+user's client.
+
+In case your experiment provides a version of PoD on CernVM-FS you can use
+that one. Experiment-independent versions are available from the PH-SFT
+cvmfs repository.
+
+Only if you have specific reasons while you want to use a customly built
+PoD version, download the source code and compile it using the
+installation instructions.
+
+Please note that [CMake](http://www.cmake.org/) and
+[Boost](http://www.boost.org/) are required to build PoD.
+
+-   After you have built PoD, install it with:
+
+        make install
+
+-   After installing PoD, run:
+
+        pod-server getbins
+
+    This has to be done only once and downloads the binary packages that
+    will be dynamically transferred to the worker nodes as binary
+    payload, and prevents us from installing PoD on each cluster node.
+
+    It is important to do this step now, because in case PoD has been
+    installed in a directory where the user has no write privileges, as
+    in the case of system-wide installations, the user won't be able to
+    download those required packages in the PoD binary directory.
+
+> There is no need to "configure" PoD for your specific cluster: it is
+> just enough to install it on your head node.
+>
+> PoD does not have any system-wide persistent daemon running or any
+> system-wide configuration to be performed. Also, no part of PoD will
+> be ever run as root.
+>
+> Do not worry about environment or software configuration at this time:
+> there is no system configuration for that. All the environment for
+> your software dependencies will be set via proper scripts from the PoD
+> client.
+>
+> PoD client configuration and running is properly covered in the
+> appropriate manual page.
+
+### Firewall configuration
+
+The head node only requires **TCP ports 22 (SSH) and 443 (HTTPS)** to accept
+connections from the outside. Users will get an authentication "token"
+from port 443 and all PROOF traffic will be automatically tunneled in a
+SSH connection on port 22 by PoD.
+
+In case you are not using the HTTPS+SSH token+authentication method, access to
+the sole port 22 is all you need.
diff --git a/proof/doc/confman/DatasetStager.md b/proof/doc/confman/DatasetStager.md
new file mode 100644
index 0000000..e930670
--- /dev/null
+++ b/proof/doc/confman/DatasetStager.md
@@ -0,0 +1,183 @@
+The Dataset Stager
+==================
+
+Overview
+--------
+
+The [Dataset Stager (afdsmgrd)](http://afdsmgrd.googlecode.com/) is
+a daemon that coordinates the transfer of data from a remote storage
+to your local storage.
+
+For each file to transfer, a script is called. The script can be
+customized to support your source and destination protocol.
+
+Staging requests are issued from the ROOT console, where you can also
+control the progress of your staging. How to request stagings and how to
+check current transfer progress from ROOT is explained in the [PROOF interface
+to AliEn file catalog documentation](TDataSetManagerAliEn.html).
+
+Installation
+------------
+
+The Dataset Stager is distributed both on a repository on its own and as
+part of ROOT. The easiest way to compile it is to do it inside ROOT.
+
+Installing from ROOT
+--------------------
+
+When configuring the ROOT source, enable the Dataset Stager by adding
+`--enable-afdsmgrd`. Check in the list of enabled features if you have
+"afdsmgrd".
+
+After running `make` (and, optionally, `make install`) you'll find the
+daemon in the same directory of `root.exe`.
+
+The configuration file and init.d startup script will be in
+`$ROOTSYS/etc/proof`. The daemon can and **must** run as unprivileged
+user.
+
+Configuration
+-------------
+
+The Dataset Stager can share its configuration file with PROOF, as
+some directives are the same and unknown directives are just ignored.
+
+Directives are one per line and lines beginning with a pound sign (`#`)
+are used for comments.
+
+> The configuration file is automatically checked at each loop: this
+> means you can change configuration without restarting the daemon or
+> stopping your current transfers.
+
+A detailed description of each directive follows.
+
+set *VARIABLE=value*
+:   This statement will substitute every occurrence of `$VARIABLE` with
+    its *value* in the rest of the configuration file. You can have
+    multiple `set` statements.
+
+xpd.stagereqrepo [dir:]*directory*
+:   This directive is shared with PROOF: *directory* is the full path to
+    the dataset repository. **Defaults to empty:** without this
+    directive the daemon is not operative.
+
+    The `dir:` prefix is optional.
+
+dsmgrd.purgenoopds *true|false*
+:   Set it to *true* **(default is false)** to remove a dataset when no file to stage
+    is found. If no file to stage is found, but corrupted files exist, the
+    dataset is kept to signal failures. Used in combination with `xpd.stagereqrepo`
+    makes it "disposable": only the datasets effectively needed for signaling
+    the staging status will be kept, improving scalability and stability.
+
+dsmgrd.urlregex *regex* *subst*
+:   Each source URL present in the datasets will be matched to *regex*
+    and substituted to *subst*. *regex* supports grouping using
+    parentheses, and groups can be referenced in order using the dollar
+    sign with a number (`$1` for instance) in *subst*.
+
+    Matching and substitution for multiple URL schemas are supported by
+    using in addition directives `dsmgrd.urlregex2` up to
+    `dsmgrd.urlregex4` which have the same syntax of this one.
+
+    Example of URL translation via regexp:
+
+    > -   Configuration line:
+    >
+    >         dsmgrd.urlregex alien://(.*)$ root://xrd.cern.ch/$1
+    >
+    > -   Source URL:
+    >
+    >         alien:///alice/data/2012/LHC12b/000178209/ESDs/pass1/12000178209061.17/AliESDs.root
+    >
+    > -   Resulting URL:
+    >
+    >         root://xrd.cern.ch//alice/data/2012/LHC12b/000178209/ESDs/pass1/12000178209061.17/AliESDs.root
+    >
+dsmgrd.sleepsecs *secs*
+:   Seconds to sleep between each loop. The dataset stager checks at
+    each loop the status of the managed transfers. Defaults to **30
+    seconds**.
+
+dsmgrd.scandseveryloops *n*
+:   Every `n` loops, the dataset repository is checked for newly
+    incoming staging requests. Defaults to **10**.
+
+dsmgrd.parallelxfrs *n*
+:   Number of concurrent transfers. Defaults to **8**.
+
+dsmgrd.stagecmd *shell\_command*
+:   Command to run in order to stage each file. It might be whatever you
+    want (executable, shell script...). If you add `$URLTOSTAGE` and/or
+    `$TREENAME` in the *shell\_command*, they'll be substituted
+    respectively with the destination URL and the default ROOT tree name
+    in the file (as specified in the dataset staging request from ROOT).
+
+    An example:
+
+        dsmgrd.stagecmd /path/to/afdsmgrd-xrd-stage-verify.sh "$URLTOSTAGE" "$TREENAME"
+
+    Return value of the command is ignored: standard output is
+    considered, as explained here.
+
+    Defaults to `/bin/false`.
+
+dsmgrd.cmdtimeoutsecs *secs*
+:   Timeout on staging command, expressed in seconds: after this
+    timeout, the command is considered failed and it is killed (in first
+    place with `SIGSTOP`, then if it is unresponsive with `SIGKILL`). It
+    defaults to zero, which means "no timeout", i.e. external command
+    may run forever, if no value is specified. Defaults to **0 (no
+    timeout)**.
+
+dsmgrd.corruptafterfails *n*
+:   Set this to a number above zero to tell the daemon to mark files as
+    corrupted after a certain number of either download or verification
+    failures. A value of **0 (default)** tells the daemon to retry
+    forever.
+
+Configuring the MonALISA monitoring plugin
+------------------------------------------
+
+The Dataset Stager supports generic monitoring plugins. The only plugin
+distributed with the stager is the MonALISA monitoring plugin.
+
+dsmgrd.notifyplugin */path/to/libafdsmgrd\_notify\_apmon.so*
+:   Set it to the path of the MonALISA plugin shared object. By default,
+    notification plugin is disabled.
+
+dsmgrd.apmonurl *apmon://apmon.cern.ch*
+:   This variable tells the ApMon notification plugin how to contact one
+    or more MonALISA server(s) to activate monitoring via ApMon. It
+    supports two kinds of URLs:
+
+    -   `http[s]://host/path/configuration_file.conf` (a remote file
+        where to fetch the list of servers from)
+
+    -   `apmon://[:password@]monalisahost[:8884]` (a single server to
+        contact directly)
+
+    If the variable is not set, yet the plugin is loaded, MonALISA
+    monitoring is inhibited until a valid configuration variable is
+    provided.
+
+dsmgrd.apmonprefix *MY::CLUSTER::PREFIX*
+:   Since MonALISA organizes information in "clusters" and "hosts", here
+    you can specify what to use as cluster prefix for monitoring
+    datasets information and daemon status. If this variable is not set,
+    MonALISA monitoring is inhibited. Please note that the suffix
+    `_datasets` or `_status` is appended for each of the two types of
+    monitoring.
+
+A sample configuration file
+---------------------------
+
+    xpd.stagereqrepo /opt/aaf/var/proof/datasets
+    dsmgrd.purgenoopds true
+    dsmgrd.urlregex alien://(.*)$ /storage$1
+    dsmgrd.sleepsecs 20
+    dsmgrd.scandseveryloops 30
+    dsmgrd.parallelxfrs 10
+    dsmgrd.stagecmd /opt/aaf/bin/af-xrddm-verify.sh "$URLTOSTAGE" "$TREENAME"
+    dsmgrd.cmdtimeoutsecs 3600
+    dsmgrd.corruptafterfails 0
diff --git a/proof/doc/confman/DeployVirtualAnalysisFacility.md b/proof/doc/confman/DeployVirtualAnalysisFacility.md
new file mode 100644
index 0000000..a4f5430
--- /dev/null
+++ b/proof/doc/confman/DeployVirtualAnalysisFacility.md
@@ -0,0 +1,220 @@
+Deploying the Virtual Analysis Facility
+=======================================
+
+Introduction
+------------
+
+Thanks to CernVM and PROOF on Demand, it is possible to deploy a ready
+to use Virtual Analysis Facility on your cloud (either public, private
+or even your desktop computer).
+
+On the server side, "configuring" the Virtual Analysis Facility is
+simply a matter of starting a certain number of CernVM virtual machines
+that will become part of your PROOF cluster. CernVM uses
+contextualization to specialize each virtual machine to be either a head
+node or a worker node.
+
+The Virtual Analysis Facility comes with many preconfigured things:
+
+-   a HTCondor cluster capable of running PROOF on Demand
+
+-   certificate authentication
+
+-   your experiment's software (if available on CernVM-FS)
+
+Obtain the CernVM image and contextualization
+---------------------------------------------
+
+### Download the CernVM bare image
+
+The Virtual Analysis Facility currently works with *CernVM Batch 2.7.1
+64-bit*. This means that you need to have this CernVM image available
+either on your local hard disk (in case of a desktop deployment) or in
+your cloud's image repository.
+
+> For convenience we provide the direct link for the working versions:
+>
+> -   [CernVM 2.7.1 batch 64-bit for
+>     **KVM**](https://cernvm.cern.ch/releases/19/cernvm-batch-node-2.7.1-2-3-x86_64.hdd.gz)
+>
+> -   [CernVM 2.7.1 batch 64-bit for
+>     **Xen**](https://cernvm.cern.ch/releases/19/cernvm-batch-node-2.7.1-2-3-x86_64.ext3.gz)
+>
+> Images are gzipped. In most cases you'll need to gunzip them before
+> registering to your image repository.
+
+### Create VM configuration profiles
+
+CernVM images are base images supporting boot-time customization via
+configuration profiles called "contexts". Context creation can be
+performed through the [CernVM Online](https://cernvm-online.cern.ch/)
+website. The site is immediately accessible if you have a CERN account.
+
+Go to your [CernVM Online
+Dashboard](https://cernvm-online.cern.ch/dashboard), click on the
+**Create new context...** dropdown and select **Virtual Analysis Facility
+node**.
+
+There's only a few parameters to configure.
+
+Context name
+:   A name for your context (such as *VAF Master for ATLAS*). Any name
+    will work.
+
+Role
+:   Use this to configure either a *master* or a *slave*.
+
+VAF master (only available when configuring a slave)
+:   IP address or FQDN of the Virtual Analysis Facility master.
+
+Auth method
+:   Choose between *ALICE LDAP* (useful only for ALICE users) or *Pool
+    accounts* (good for authenticating all the other Grid users).
+
+Num. pool accounts (only available when using pool accounts auth)
+:   Number of pool accounts to create.
+
+Proxy for CVMFS
+:   An URL specifying the proxy server for CernVM-FS, such as
+    `http://ca-proxy.cern.ch:3128/`. If you leave it empty, proxy will
+    be automatically discovered.
+
+HTCondor shared secret
+:   VMs part of the same cluster should have the same value of this
+    field. It is used to mutually authenticate VMs and it is used like a
+    password.
+
+Context password
+:   Current profile will be saved on the [CernVM Online
+    repository](http://cernvm-online.cern.ch/). If you don't want the
+    information there to be publicly available to other users, type in
+    a value for protecting the context with an encryption password.
+
+You will have to create a profile for the **master** and the **slave**. Since
+most of the configuration variables are the same (like the *HTCondor
+shared secret*) you can create one, clone it and change only what's
+needed to change.
+
+Deploy it on the cloud
+----------------------
+
+Provided you have access to a certain cloud API, you'll need to
+instantiate a certain number of CernVM batch images with proper
+contextualization: one for the master, as many as you want as slaves.
+
+CernVM supports contextualization through the "user data" field
+supported by all cloud infrastructures.
+
+Each cloud infrastructure has a different method of setting the "user
+data". The following description will focus on:
+
+-   [OpenNebula](http://opennebula.org/)
+
+-   OpenStack (such as the [CERN Agile
+    infrastructure](https://openstack.cern.ch/))
+
+-   [Amazon EC2](http://aws.amazon.com/ec2/)-compatible interfaces via
+    the open [Eucalyptus](http://www.eucalyptus.com/)
+    [Euca2ools](http://www.eucalyptus.com/eucalyptus-cloud/tools): many popular
+    clouds support such interface and tools
+
+### Download the CernVM Online contextualizations
+
+Go to the CernVM Online Dashboard page where you have previously
+customized the contexts for your master and your slaves.
+
+Click on the rightmost button on the line of the desired context and
+select **Get rendered context** from the dropdown: save the output to a
+text file (such as `my_vaf_context.txt`, the name we will use in the
+examples that follow). This file will be subsequently passed as the so
+called "user-data" file to the cloud API.
+
+> Repeat the operation for both the master context and the slave
+> context.
+
+### OpenStack API: nova
+
+Example of a CernVM instantiation using `nova`:
+
+``` {.bash}
+nova boot \
+  --flavor m1.xlarge \
+  --image cernvm-batch-node-2.6.0-4-1-x86_64 \
+  --key-name my_default_keyparir \
+  --user-data my_vaf_context.txt \
+  Name-Of-My-New-VM
+```
+
+The `--user-data` option requires the context file we've just
+downloaded.
+
+### EC2 API: euca-tools
+
+Example of a CernVM instantiation using `euca-tools`:
+
+``` {.bash}
+euca-run-instances \
+  --instance-type m1.xlarge \
+  --key my_default_keyparir \
+  --user-data-file my_vaf_context.txt \
+  cernvm-batch-node-2.6.0-4-1-x86_64
+```
+
+The `--user-data-file` option is the context file we've just downloaded.
+
+### OpenNebula
+
+An example VM definition follows:
+
+``` {.ruby}
+CONTEXT=[
+  EC2_USER_DATA="<base64_encoded_string>",
+]
+CPU="6"
+VCPU="6"
+DISK=[
+  IMAGE="cernvm-batch-node-2.6.0-4-1-x86_64",
+  TARGET="vda" ]
+MEMORY="16000"
+NAME="CernVM-VAF-Node"
+NIC=[
+  NETWORK="My-OpenNebula-VNet" ]
+OS=[
+  ARCH="x86_64" ]
+```
+
+The `<base64_encoded_string>` requires the base64 version of the whole
+downloaded context definition. You can obtain it by running:
+
+    cat my_vaf_context.txt | base64 | tr -d '\n'
+
+Network security groups
+-----------------------
+
+In order to make the Virtual Analysis Facility work properly, the
+firewall of your infrastructure must be configured to allow some
+connections.
+
+Some ports need to allow "external" connections while other ports might
+be safely opened to allow only connections from other nodes of the
+Virtual Analysis Facility.
+
+### Ports to open on all nodes
+
+HTCondor ports
+:   Allow **TCP and UDP range 9600-9700** only between nodes of the Virtual
+    Analysis Facility.
+
+Only HTCondor and PoD communication is needed between the nodes. No HTCondor
+ports need to be opened to the world.
+
+### Additional ports to open on the front end node
+
+HTTPS
+:   Allow **TCP 443** from all
+
+SSH
+:   Allow **TCP 22** from all
+
+No other ports need to be opened from the outside. Your definition of
+*allow from all* might vary.
diff --git a/proof/doc/confman/Makefile b/proof/doc/confman/Makefile
new file mode 100644
index 0000000..12bd6d9
--- /dev/null
+++ b/proof/doc/confman/Makefile
@@ -0,0 +1,54 @@
+#
+# Makefile for creating HTML out of Markdown for the PROOF configuration
+# manual.
+#
+# Pandoc is used for the conversion. Thanks to Olivier Couet for the Markdown
+# ROOT documentation generation scripts.
+#
+# Pandoc sample installation on OSX (using Homebrew):
+#
+#   $> brew install haskell-platform
+#   $> cabal install pandoc
+#   $> export PATH=$HOME/.cabal/bin:$PATH
+#
+
+PANDOC_OPTS := -s -S --toc --chapters --number-sections -f markdown -H css/github.css
+PANDOC_OPTS_INDEX := -s -S -f markdown -H css/github.css
+
+INPUT_MDS := \
+	ConfigProofPoD.md \
+	DeployVirtualAnalysisFacility.md \
+	UsingVirtualAnalysisFacility.md \
+	TDataSetManagerAliEn.md \
+	DatasetStager.md
+
+INDEX_MD := index.md
+INDEX_HTML := index.html
+
+OUTPUT_HTML = $(INPUT_MDS:.md=.html)
+
+.PHONY: all html clean
+
+all: html
+
+html: idx $(OUTPUT_HTML)
+
+idx:
+	@echo Generating HTML index
+	@(echo "Index" > $(INDEX_MD) ; \
+	  echo "=====" >> $(INDEX_MD) ; \
+	  echo "" >> $(INDEX_MD) ; \
+	  for Md in $(INPUT_MDS) ; do \
+	    echo "1. [$$(head -n1 $$Md)]($${Md%.*}.html)" ; \
+	  done >> $(INDEX_MD) )
+	@pandoc $(PANDOC_OPTS_INDEX) $(INDEX_MD) -o $(INDEX_HTML)
+
+%.html: %.md
+	@echo Generating HTML: $@
+	@(OFFSET=$$(for F in $(INPUT_MDS) ; do echo $$F ; done | grep -n $< | cut -d: -f1) ; \
+	  let OFFSET-- ; \
+	  pandoc $(PANDOC_OPTS) --number-offset $$OFFSET $< -o $@)
+
+clean:
+	@echo Cleaning up
+	@rm -f $(OUTPUT_HTML) $(INDEX_MD) $(INDEX_HTML)
diff --git a/proof/doc/confman/TDataSetManagerAliEn.md b/proof/doc/confman/TDataSetManagerAliEn.md
new file mode 100644
index 0000000..80a4998
--- /dev/null
+++ b/proof/doc/confman/TDataSetManagerAliEn.md
@@ -0,0 +1,429 @@
+A PROOF interface to the AliEn file catalog
+===========================================
+
+Overview
+--------
+
+Datasets have been invented to provide PROOF users a cleaner access to
+sets of uniform data: each dataset has a name which helps identifying
+the kind of data stored, plus some meta-information, such as:
+
+-   default tree name
+
+-   number of events in the default tree
+
+-   file size
+
+-   integrity information: *is my file corrupted?*
+
+-   locality information: *is my remote file available on a local
+    storage?*
+
+Datasets are also used by the [staging daemon
+afdsmgrd](http://afdsmgrd.googlecode.com/) to trigger data staging,
+*i.e.* to request some data from being transferred from a remote storage
+to the local analysis facility disks.
+
+PROOF datasets are handled by the *dataset manager*, a generic catalog of
+datasets which has been historically implemented by the class
+`TDataSetManagerFile`, which stored each dataset inside a ROOT file.
+
+This dataset manager has been conceived for a small *(i.e., hundreds)*
+number of datasets which reflected data stored on the local analysis facility
+disks. As the PROOF analysis model became popular in ALICE, the number
+of datasets grew posing many problems.
+
+-   To give the possibility to process remote data, current datasets
+    mimick file catalog functionalities by including also lists of files
+    currently not staged on the local analysis facility.
+
+-   Since users can create their own datasets, in many cases containing
+    duplicate data, it has become demanding to provide maintenance and
+    support.
+
+-   Locality information in datasets is static: this means that, if a
+    file gets deleted from a disk, the corresponding dataset(s) must be
+    synchronized manually.
+
+### An interface to the AliEn file catalog
+
+The new `TDataSetManagerAliEn` class is a new dataset manager which acts
+as an intermediate layer between PROOF datasets and the AliEn file
+catalog.
+
+Dataset names do not represent any longer a static list of files:
+instead, it represents a **query string** to the AliEn file catalog that
+creates a dataset dynamically.
+
+**Locality information** is also filled on the fly by contacting the local
+file server: for instance, in case a *xrootd* pool of disks is used,
+fresh online information along with the exact host (endpoint) where each
+file is located is provided dynamically in a reasonable amount of time.
+
+Both file catalog queries and locality information are cached on ROOT
+files: cache is shared between users and its expiration time is
+configurable.
+
+Since dataset information is now volatile, a separate and more
+straightforward method for issuing staging requests has also been
+provided.
+
+Configuration
+-------------
+
+### PROOF
+
+Using the new dataset manager requires the `xpd.datasetsrc` directive in
+the xproofd configuration file:
+
+    xpd.datasetsrc alien cache:/path/to/dataset/cache urltemplate:http://myserver:1234/data<path> cacheexpiresecs:86400
+
+alien
+:   Tells PROOF that the dataset manager is the AliEn interface (as
+    opposed to `file`).
+
+cache
+:   Specify a path *on the local filesystem* of the host running user's
+    PROOF master.
+
+    > This path is not a URL but just a local path. Moreover, the path
+    > must be visible from the host that will run each user's master,
+    > since a separate dataset manager instance is created per user.
+
+    > If the cache directory does not exist, it is created, if possible,
+    > with open permissions (`rwxrwxrwx`). On a production environment
+    > it is advisable to create the cache directory manually beforehand
+    > with the same permissions.
+
+urltemplate
+:   Template used for translating between an `alien://` URL and the
+    local storage's URL.
+
+    `<path>` is written literally and will be substituted with the full
+    AliEn path without the protocol.
+
+    > An example on how URL translation works:
+    >
+    > -   Template URL:
+    >
+    >         root://alice-caf.cern.ch/<path>
+    >
+    > -   Source URL:
+    >
+    >         alien:///alice/data/2012/LHC12b/000178209/ESDs/pass1/12000178209061.17/AliESDs.root
+    >
+    > -   Resulting URL:
+    >
+    >         root://alice-caf.cern.ch//alice/data/2012/LHC12b/000178209/ESDs/pass1/12000178209061.17/AliESDs.root
+    >
+cacheexpiresecs
+:   Number of seconds before cached information is considered expired
+    and refetched *(e.g., 86400 for one day)*.
+
+### PROOF-Lite
+
+One of the advantages of such a dynamic AliEn catalog interface is that
+it is possible to use it with PROOF-Lite.
+
+By default, PROOF-Lite creates on the client session (which acts as a
+master as well) a file-based dataset manager. To enable the AliEn
+dataset manager in a PROOF-Lite session, run:
+
+``` {.cpp}
+gEnv->SetValue("Proof.DataSetManager",
+  "alien cache:/path/to/dataset/cache "
+  "urltemplate:root://alice-caf.cern.ch/<path> "
+  "cacheexpiresecs:86400");
+TProof::Open("");
+```
+
+where the parameters meaning has been described in the previous section.
+
+> Please note that the environment must be set **before** opening the
+> PROOF-Lite session!
+
+Usage
+-----
+
+The new dataset manager is backwards-compatible with the legacy
+interface: each time you want to process or obtain a dataset, instead of
+specifying a string containing a dataset name you will specify a query
+string to the file catalog.
+
+### Query string format
+
+The query string is the string you will use in place of the dataset
+name. It does not correspond to a static dataset: instead it represents
+a virtual dataset whose information is filled in on the fly.
+
+There are two different formats you can use:
+
+-   specify data features (such as period and run numbers) for **official
+    data or Monte Carlo**
+
+-   specify the **AliEn find** command parameters directly
+
+In the query string it is also possible to specify if you want to
+process data from AliEn, only staged data or data from AliEn in "cache
+mode".
+
+#### Official data and Monte Carlo format
+
+These are the string formats to be used respectively for official data
+and official Monte Carlo productions:
+
+    Data;Period=<LHCPERIOD>;Variant=[ESDs|AODXXX];Run=<RUNLIST>;Pass=<PASS>
+
+    Sim;Period=<LHCPERIOD>;Variant=[ESDs|AODXXX];Run=<RUNLIST>;
+
+Period
+:   The LHC period.
+
+    Example of valid values: `LHC10h`, `LHC11h_2`, `LHC11f_Technical`
+
+Variant
+:   Data variant, which might be `ESDs` (or `ESD`) for ESDs and `AODXXX`
+    for AODs corresponding to the *XXX* set.
+
+    Example of valid values: `ESDs`, `AOD073`, `AOD086`
+
+Run
+:   Runs to be processed, in the form of a single run (`130831`), an
+    inclusive range (`130831-130833`), or a list of runs and/or ranges
+    (`130831-130835,130840,130842`).
+
+    Duplicate runs are automatically removed, so in case you specify
+    `130831-130835,130833` run number 130833 will be processed only
+    once.
+
+Pass *(only for data, not for Monte Carlo)*
+:   The pass number or name. In case you specify only a number `X`, it
+    will be expanded to `passX`.
+
+    Example of valid values: `1`, `pass1`, `pass2`, `cpass1_muon`
+
+This is an example of a full valid string:
+
+    Data;Period=LHC10h;Variant=AOD086;Run=130831-130833;Pass=pass1
+
+#### AliEn find format
+
+Whenever a user would like to process data which has not been produced
+officially, or whose directory structure in the AliEn file catalog is
+non-standard, an interface to the AliEn shell's `find` command is
+provided.
+
+This is the command format:
+
+    Find;BasePath=<BASEPATH>;FileName=<FILENAME>;Anchor=<ANCHOR>;TreeName=<TREENAME>;Regexp=<REGEXP>
+
+Parameters `BasePath` and `FileName` are passed as-is to the AliEn [find
+command](http://alien2.cern.ch/index.php?option=com_content&view=article&id=53&Itemid=99#Searching_for_files),
+and are mandatory.
+
+Parameters `Anchor`, `TreeName` and `Regexp` are optional.
+
+Here's a detailed description of the parameters.
+
+BasePath
+:   Start search under the specified path on the AliEn file catalog.
+
+    Jolly characters are supported: the asterisk (`*`) and the
+    percentage sign (`%`) are interchangeable.
+
+    Examples of valid values are:
+
+        /alice/data/2010/LHC10h/000123456/*.*
+        /alice/cern.ch/user/d/dummy/my_pp_production/%.%
+
+FileName
+:   File name to look for.
+
+    Examples of valid values are: `root_archive.zip`, `aod_archive.zip`,
+    `custom_archive.zip`, `AliAOD.root.
+
+Anchor *(optional)*
+:   In case `FileName` is a zip archive, the anchor is the name of a
+    ROOT file inside the archive to point to.
+
+    Examples of valid values are: `AliAOD.root`, `AliESDs.root`,
+    `MyRootFile.root`.
+
+    > Using the AliEn file catalog it is possible to point directly to a
+    > ROOT file stored in an archive without using the anchor.
+    >
+    > There is however a substantial difference in how data is
+    > retrieved, especially during staging: auxiliary ROOT files
+    > *(friends)* are stored inside the archive along with the "main"
+    > file, so that when you use the archive as `FileName` with the
+    > proper `Anchor` you are still referencing to the same file, but
+    > you are giving instructions of downloading the archive.
+    >
+    > Using the ROOT file name directly must be done in very special
+    > cases (*i.e.*, to save space) and only when one is completely sure
+    > that no external files in the archive are required for analysis.
+
+TreeName *(optional)*
+:   Name of each file's default tree.
+
+    Examples of valid values are: `/aodTree`, `/esdTree`, `/myCustomTree`,
+    `/TheDirectory/TheTree`.
+
+Regexp *(optional)*
+:   Additional extended regular expression applied after find command is
+    run, to fine-grain search results.
+
+    Only `alien://` paths matching the regular expression are
+    considered, others are discarded.
+
+    Examples of valid values are:
+
+        /[0-9]{6}/[0-9]{3,4}
+        \.root$
+
+    > ROOT class
+    > [TPMERegexp](http://root.cern.ch/root/html/TPMERegexp.html) is
+    > used to perform regular expression matching.
+
+
+Example of an AliEn raw find dataset string:
+
+    Find;BasePath=/alice/data/2010/LHC10h/000139505/ESDs/pass1/*.*;FileName=root_archive.zip;Anchor=AliESDs.root
+
+#### Data access modes
+
+It is possible to append to the format string the `Mode` specifier that
+affects the way URLs are generated.
+
+    Mode=[local|remote|cache]
+
+This parameter is optional and defaults to `local`. Description of each
+possible value follows:
+
+local
+:   Local storage is checked for the presence of data you requested.
+    Output URLs will be relative to your local storage. Also, locality
+    information *(i.e., is your file staged?)* is filled.
+
+    If you run a PROOF analysis on a dataset with this mode specified,
+    only data marked as "staged" will be processed.
+
+    This method is the preferred one, since it does not overload the
+    remote storage, and it enables users to process partially-staged
+    datasets, or partially-reconstructed runs, without the need to
+    manually update static datasets.
+
+    > This is the default if no mode is specified, and it is also the
+    > most efficient one.
+    >
+    > Despite it might take some time (up to a couple of minutes to
+    > locate ~4000 files), returned information is always reliable
+    > (because it's dynamic) and speeds up analysis (because analysis
+    > will always be run only on files having local copies).
+    >
+    > Moreover this information is cached for a configurable period of
+    > time, so that subsequent calls to the same dataset will be faster.
+
+remote
+:   Only AliEn URLs are returned.
+
+    A PROOF analysis run on a dataset with this mode specified will
+    always obtain data from a remote storage, according to the AliEn
+    file catalog.
+
+    > Tasks run on remote data are usually much slower than using local
+    > storage.
+
+cache
+:   URLs pointing to local copies of files are returned, but does not check
+    whether the file is locally present or not.
+
+    If local storage is configured for retrieving from AliEn files that
+    are not available locally (which is the case of xrootd with vMSS),
+    then data will be downloaded *while analysis is running*.
+
+    It is called *cache mode* because it treats the local storage as a
+    cache for the remote storage.
+
+    > This mode is usually very slow on a busy analysis facility since
+    > retrieving data in real time without any kind of scheduling is
+    > inefficient. It also conflicts with the preferred method, which is
+    > to stage data asynchronously using the [stager
+    > daemon](http://afdsmgrd.googlecode.com/).
+
+#### Force cache refresh
+
+If the cached information for a certain AliEn file catalog query is wrong,
+it is possible to force querying the catalog again by using the keyword
+`ForceUpdate`:
+
+    Data;ForceUpdate;Period=LHC10h;Variant=AOD086;Run=130831-130833;Pass=pass1
+
+### Staging requests
+
+Issuing staging requests and keeping track of them requires an auxiliary
+database that can be read and updated by the [data stager
+daemon](http://afdsmgrd.googlecode.com/).
+
+Whenever a staging request is issued, a ROOT file containing the dataset
+is saved in a special directory on the master's filesystem, monitored by
+the file stager.
+
+#### PROOF configuration
+
+In the xproofd configuration file, there is a directive to specify the
+directory used as repository for staging requests:
+
+    xpd.stagereqrepo [dir:]/path/to/local/directory
+
+> The literal `dir:` prefix is optional.
+
+This directive is shared between PROOF and the stager daemon, so that the
+same configuration file can be used for both.
+
+Permissions on this directory must be kept open.
+
+> Versions of the stager daemon prior to v1.0.7 do not support open
+> permissions and the staging repository directive.
+
+#### Request and monitor staging
+
+Staging requests and monitoring can be done from within a PROOF session.
+
+`gProof->RequestStagingDataSet("QueryString")`
+:   Requests staging of the dataset specified via the query string.
+
+    Staging request is honored if the stager daemon is running.
+
+    > In order to avoid requesting to stage undesired data, it is
+    > advisable to check in advance the results of your query string:
+    >
+    > `gProof->ShowDataSet("QueryString")`
+
+`TProof->ShowStagingStatusDataSet("QueryString"[, "opts"])`
+:   Shows progress status of a previously given staging request with
+    data specified by the query string.
+
+    Options are optional, and passed as-is to the `::Print()` method.
+
+    > It is possible to show all the files marked as corrupted by the
+    > daemon:
+    >
+    >     gProof->ShowStagingStatusDataSet("QueryString", "C")
+    >
+    > Or all the files successfully staged and not corrupted:
+    >
+    >     gProof->ShowStagingStatusDataSet("QueryString", "Sc")
+
+`gProof->GetStagingStatusDataSet("QueryString")`
+:   Gets a `TFileCollection` containing information on the staging
+    request specified by the query string.
+
+    Works exactly like `ShowStagingStatusDataSet()` but returns an
+    object instead of displaying information on the screen.
+
+`gProof->CancelStagingDataSet("QueryString")`
+:   Removes a dataset from the list of staging requests. Datasets used
+    as staging requests are usually removed automatically by the staging
+    daemon if everything went right, so this command is used mostly to
+    purge a completed staging request when it has some corrupted files.
diff --git a/proof/doc/confman/UsingVirtualAnalysisFacility.md b/proof/doc/confman/UsingVirtualAnalysisFacility.md
new file mode 100644
index 0000000..7a9325d
--- /dev/null
+++ b/proof/doc/confman/UsingVirtualAnalysisFacility.md
@@ -0,0 +1,379 @@
+Using the Virtual Analysis Facility
+===================================
+
+Introduction
+------------
+
+The Virtual Analysis Facility can be easily used by having installed on
+your client the following software:
+
+-   [ROOT](http://root.cern.ch/)
+
+-   [PROOF on Demand](http://pod.gsi.de/)
+
+-   The VAF client *(see below)*: a convenience tool that sets up the
+    environment for your experiment's software both on your client and
+    on the PROOF worker nodes
+
+> If you are the end user, you'll probably might skip the part that
+> concerns how to configure the VAF client: your system administrator
+> has probably and conveniently set it up for you.
+
+The Virtual Analysis Facility client
+------------------------------------
+
+The Virtual Analysis Facility client takes care of setting the
+environment for the end user required by your software's experiment. The
+environment will both be set on the client and on each PROOF node.
+
+Technically it is a Bash shell script which provides shortcuts for PROOF
+on Demand commands and ensures local and remote environment consistency:
+by executing it you enter a new clean environment where all your
+software dependencies have already been set up.
+
+Local and remote environment configuration is split into a series of
+files, which give the possibility to:
+
+-   have a system-wide, sysadmin-provided experiment configuration
+
+-   execute user actions either *before* or *after* the execution of the
+    system-wide script (for instance, choosing the preferred version of
+    the experiment's software)
+
+-   transfer a custom user **payload** on each PROOF worker (for instance,
+    user's client-generated Grid credentials to make PROOF workers
+    capable of accessing a remote authenticated storage)
+
+Configuration files are searched for in two different locations:
+
+-   a system-wide directory: `<client_install_dir>/etc`
+
+-   user's home directory: `~/.vaf`
+
+> A system-wide configuration file always has precedence over user's
+> configuration. It is thus possible for the sysadmin to enforce a
+> policy where some scripts cannot ever be overridden.
+
+Thanks to this separation, users can maintain an uncluttered directory
+with very simple configuration files that contain only what really needs
+or is allowed to be customized: for instance, user might specify a single line
+containing the needed ROOT version, while all the technicalities to set
+up the environment are taken care of inside system-installed scripts,
+leaving the user's configuration directory clean and uncluttered.
+
+### Local environment configuration
+
+All the local environment files are loaded at the time of the
+client's startup following a certain order
+
+-   `common.before`
+
+-   `local.before`
+
+-   `local.conf`
+
+-   `$VafConf_LocalPodLocation/PoD_env.sh`
+
+-   `common.after`
+
+-   `local.after`
+
+The `common.*` files are sourced both for the local and the remote
+environment. This might be convenient to avoid repeating the same
+configuration in different places.
+
+Each file is looked for first in the system-wide directory and then in
+the user's directory. If a configuration file does not exist, it is
+silently skipped.
+
+The `$VafConf_LocalPodLocation/PoD_env.sh` environment script, provided
+with each PROOF on Demand installation, *must exist*: without this file,
+the VAF client won't start.
+
+### List of VAF-specific variables
+
+There are some special variables that need to be set in one of the above
+configuration files.
+
+`$VafConf_LocalPodLocation`
+:   Full path to the PoD installation on the client.
+
+    > The `$VafConf_LocalPodLocation` variable must be set before the
+    > `PoD_env.sh` script gets sourced, so set it either in
+    > `common.before`, `local.before` or `local.conf`. Since PoD is
+    > usually system-wide installed, its location is normally
+    > system-wide set in either the `local.conf` file by the system
+    > administrator.
+
+`$VafConf_RemotePodLocation`
+:   Full path to the PoD installation on the VAF master node.
+
+    *Note: this variable should be set in the configuration files for
+    the local environment despite it refers to a software present on the
+    remote nodes.*
+
+`$VafConf_PodRms` *(optional)*
+:   Name of the Resource Management System used for submitting PoD jobs.
+    Run `pod-submit -l` to see the possible values.
+
+    If not set, defaults to `condor`.
+
+`$VafConf_PodQueue` *(optional)*
+:   Queue name where to submit PoD jobs.
+
+    If no queue has been given, the default one configured on your RMS
+    will be used.
+
+### Remote environment configuration
+
+All the PoD commands sent to the VAF master will live in the environment
+loaded via using the following scripts.
+
+Similarly to the local environment, configuration is split in different files
+to allow for a system-wide configuration, which has precedence over
+user's configuration in the home directory. If a script cannot be found,
+it will be silently skipped.
+
+-   `<output_of_payload>`
+
+-   `common.before`
+
+-   `remote.before`
+
+-   `remote.conf`
+
+-   `common.after`
+
+-   `remote.after`
+
+For an explanation on how to pass extra data to the workers safely
+through the payload, see below.
+
+### Payload: sending local files to the remote nodes
+
+In many cases it is necessary to send some local data to the remote
+workers: it is very common, for instance, to distribute a local Grid
+authentication proxy on the remote workers to let them authenticate to
+access a data storage.
+
+The `payload` file must be an executable generating some output that
+will be prepended to the remote environment preparation. Differently
+than the other environment scripts, it is not executed: instead, it is
+first run, then *the output it produces will be executed*.
+
+Let's see a practical example to better understand how it works. We need
+to send our Grid proxy to the master node.
+
+This is our `payload` executable script:
+
+``` {.bash}
+#!/bin/bash
+echo "echo '`cat /tmp/x509up_u$UID | base64 | tr -d '\r\n'`'" \
+  "| base64 -d > /tmp/x509up_u\$UID"
+```
+
+This script will be executed locally, providing another "script line" as
+output:
+
+``` {.bash}
+echo 'VGhpcyBpcyB0aGUgZmFrZSBjb250ZW50IG9mIG91ciBHcmlkIHByb3h5IGZpbGUuCg==' | base64 -d > /tmp/x509up_u$UID
+```
+
+This line will be prepended to the remote environment script and will be
+executed before anything else on the remote node: it will effectively
+decode the Base64 string back to the proxy file and write it into the
+`/tmp` directory. Note also that the first `$UID` is not escaped and
+will be substituted *locally* with your user ID *on your client
+machine*, while the second one has the dollar escaped (`\$UID`) and will
+be substituted *remotely* with your user ID *on the remote node*.
+
+> It is worth noting that the remote environment scripts will be sent to
+> the remote node using a secure connection (SSH), thus there is no
+> concern in placing sensitive user data there.
+
+Installing the Virtual Analysis Facility client
+-----------------------------------------------
+
+### Download the client from Git
+
+The Virtual Analysis Facility client is available on
+[GitHub](https://github.com/dberzano/virtual-analysis-facility):
+
+``` {.bash}
+git clone git://github.com/dberzano/virtual-analysis-facility.git /dest/dir
+```
+
+The client will be found in `/dest/dir/client/bin/vaf-enter`: it is
+convenient to add it to the `$PATH` so that the users might simply start
+it by typing `vaf-enter`.
+
+### Install the experiment's configuration files system-wide
+
+A system administrator might find convenient to install the experiment
+environment scripts system-wide.
+
+Configuration scripts for LHC experiments are shipped with the VAF
+client and can be found in
+`/dest/dir/client/config-samples/<experiment_name>`. To make them used
+by default by the VAF client, place them in the `/dest/dir/etc`
+directory like this:
+
+``` {.bash}
+rsync -a /dest/dir/client/config-samples/<experiment_name>/ /dest/dir/etc/
+```
+
+Remember that the trailing slash in the source directory name has a
+meaning in `rsync` and must not be omitted.
+
+> Remember that system-wide configuration files will always have
+> precedence over user's configuration files, so *don't place there
+> files that are supposed to be provided by the user!*
+
+Entering the Virtual Analysis Facility environment
+--------------------------------------------------
+
+The Virtual Analysis Facility client is a wrapper around commands sent
+to the remote host by means of PROOF on Demand's `pod-remote`. The VAF
+client takes care of setting up passwordless SSH from your client node
+to the VAF master.
+
+### Getting the credentials
+
+> You can skip this paragraph if the remote server wasn't configured for
+> HTTPS+SSH authentication.
+
+In our example we will assume that the remote server's name is
+`cloud-gw-213.to.infn.it`: substitute it with your remote endpoint.
+
+First, check that you have your Grid certificate and private key
+installed both in your browser and in the `~/.globus` directory of your
+client.
+
+Point your browser to `https://cloud-gw-213.to.infn.it/auth/`: you'll
+probably be asked for a certificate to choose for authentication. Pick
+one and you'll be presented with the following web page:
+
+![Web authentication with sshcertauth](img/sshcertauth-web.png)
+
+The webpage clearly explains you what to do next.
+
+### Customizing user's configuration
+
+Before entering the VAF environment, you should customize the user's
+configuration. How to do so depends on your experiment, but usually you
+should essentially specify the version of the experiment's software you
+need.
+
+For instance, in the CMS use case, only one file is needed:
+`~/.vaf/common.before`, which contains something like:
+
+``` {.bash}
+# Version of CMSSW (as reported by "scram list")
+export VafCmsswVersion='CMSSW_5_3_9_sherpa2beta2'
+```
+
+### Entering the VAF environment
+
+Open a terminal on your client machine (can be either your local
+computer or a remote user interface) and type:
+
+    vaf-enter <username>@cloud-gw-213.to.infn.it
+
+You'll substitute `<username>` with the username that either your system
+administrator or the web authentication (if you used it) provided you.
+
+You'll be presented with a neat shell which looks like the following:
+
+    Entering VAF environment: dberzano at cloud-gw-213.to.infn.it
+    Remember: you are still in a shell on your local computer!
+    pod://dberzano@cloud-gw-213.to.infn.it [~] >
+
+This shell runs on your local computer and it has the environment
+properly set up.
+
+PoD and PROOF workflow
+----------------------
+
+> The following operations are valid inside the `vaf-enter` environment.
+
+### Start your PoD server
+
+With PROOF on Demand, each user has the control of its own personal
+PROOF cluster. The first thing to do is to start the PoD server and the
+PROOF master like this:
+
+    vafctl --start
+
+A successful output will be similar to:
+
+    **    Starting remote PoD server on dberzano at cloud-gw-213.to.infn.it:/cvmfs/sft.cern.ch/lcg/external/PoD/3.12/x86_64-slc5-gcc41-python24-boost1.53
+    **  Server is started. Use "pod-info -sd" to check the status of the server.
+
+### Request and wait for workers
+
+Now the server is started but you don't have any worker available. To
+request for `<n>` workers, do:
+
+    vafreq <n>
+
+To check how many workers became available for use:
+
+    pod-info -n
+
+To continuously update the check (`Ctrl-C` to terminate):
+
+    vafcount
+
+Example of output:
+
+    Updating every 5 seconds. Press Ctrl-C to stop monitoring...
+    [20130411-172235] 0
+    [20130411-172240] 0
+    [20130411-172245] 12
+    [20130411-172250] 12
+    ...
+
+To execute a command after a certain number of workers is available (in
+the example we wait for 5 workers then start ROOT):
+
+    vafwait 5 && root -l
+
+> Workers take some time before becoming available. Also, it is possible
+> that not all the requested workers will be satisfied.
+
+### Start ROOT and use PROOF
+
+When you are satisfied with the available number of active workers, you
+may start your PROOF analysis. Start ROOT, and from its prompt connect
+to PROOF like this:
+
+    root [0] TProof::Open("pod://");
+
+Example of output:
+
+    Starting master: opening connection ...
+    Starting master: OK                                                 
+    Opening connections to workers: OK (12 workers)                 
+    Setting up worker servers: OK (12 workers)                 
+    PROOF set to parallel mode (12 workers)
+
+### Stop or restart your PoD cluster
+
+At the end of your session, remember to free the workers by stopping
+your PoD server:
+
+    vafctl --stop
+
+> PoD will stop the PROOF master and the workers after detecting they've
+> been idle for a certain amount of time anyway, but it is a good habit
+> to stop it for yourself when you're finished using it, so that you are
+> immediately freeing resources and let them be available for other
+> users.
+
+In case of a major PROOF failure (i.e., crash), you can simply restart
+your personal PROOF cluster by running:
+
+    vafctl --start
+
+PoD will stop and restart the PROOF master. You'll need to request the
+workers again at this point.
diff --git a/proof/doc/confman/css/github.css b/proof/doc/confman/css/github.css
new file mode 100755
index 0000000..13903c0
--- /dev/null
+++ b/proof/doc/confman/css/github.css
@@ -0,0 +1,300 @@
+<style>
+body {
+  font-family: Helvetica, arial, sans-serif;
+  font-size: 14px;
+  line-height: 1.6;
+  padding-top: 10px;
+  padding-bottom: 10px;
+  background-color: white;
+  padding: 30px; }
+
+body > *:first-child {
+  margin-top: 0 !important; }
+body > *:last-child {
+  margin-bottom: 0 !important; }
+
+a {
+  text-decoration: none;
+  color: #4183C4; }
+a.absent {
+  color: #cc0000; }
+a.anchor {
+  display: block;
+  padding-left: 30px;
+  margin-left: -30px;
+  cursor: pointer;
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0; }
+
+h1, h2, h3, h4, h5, h6 {
+  margin: 20px 0 10px;
+  padding: 0;
+  font-weight: bold;
+  -webkit-font-smoothing: antialiased;
+  cursor: text;
+  position: relative; }
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
+  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNj [...]
+  text-decoration: none; }
+
+h1 tt, h1 code {
+  font-size: inherit; }
+
+h2 tt, h2 code {
+  font-size: inherit; }
+
+h3 tt, h3 code {
+  font-size: inherit; }
+
+h4 tt, h4 code {
+  font-size: inherit; }
+
+h5 tt, h5 code {
+  font-size: inherit; }
+
+h6 tt, h6 code {
+  font-size: inherit; }
+
+h1 {
+  font-size: 28px;
+  color: black; }
+
+h2 {
+  font-size: 24px;
+  border-bottom: 1px solid #cccccc;
+  color: black; }
+
+h3 {
+  font-size: 18px; }
+
+h4 {
+  font-size: 16px; }
+
+h5 {
+  font-size: 14px; }
+
+h6 {
+  color: #777777;
+  font-size: 14px; }
+
+p, blockquote, ul, ol, dl, li, table, pre {
+  margin: 15px 0; }
+
+hr {
+  background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4g [...]
+  border: 0 none;
+  color: #cccccc;
+  height: 4px;
+  padding: 0;
+}
+
+body > h2:first-child {
+  margin-top: 0;
+  padding-top: 0; }
+body > h1:first-child {
+  margin-top: 0;
+  padding-top: 0; }
+  body > h1:first-child + h2 {
+    margin-top: 0;
+    padding-top: 0; }
+body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
+  margin-top: 0;
+  padding-top: 0; }
+
+a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
+  margin-top: 0;
+  padding-top: 0; }
+
+h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
+  margin-top: 0; }
+
+li p.first {
+  display: inline-block; }
+li {
+  margin: 0; }
+ul, ol {
+  padding-left: 30px; }
+
+ul :first-child, ol :first-child {
+  margin-top: 0; }
+
+dl {
+  padding: 0; }
+  dl dt {
+    font-size: 14px;
+    font-weight: bold;
+    font-style: italic;
+    padding: 0;
+    margin: 15px 0 5px; }
+    dl dt:first-child {
+      padding: 0; }
+    dl dt > :first-child {
+      margin-top: 0; }
+    dl dt > :last-child {
+      margin-bottom: 0; }
+  dl dd {
+    margin: 0 0 15px;
+    padding: 0 15px; }
+    dl dd > :first-child {
+      margin-top: 0; }
+    dl dd > :last-child {
+      margin-bottom: 0; }
+
+blockquote {
+  border-left: 4px solid #dddddd;
+  padding: 0 15px;
+  color: #777777; }
+  blockquote > :first-child {
+    margin-top: 0; }
+  blockquote > :last-child {
+    margin-bottom: 0; }
+
+table {
+  padding: 0;border-collapse: collapse; }
+  table tr {
+    border-top: 1px solid #cccccc;
+    background-color: white;
+    margin: 0;
+    padding: 0; }
+    table tr:nth-child(2n) {
+      background-color: #f8f8f8; }
+    table tr th {
+      font-weight: bold;
+      border: 1px solid #cccccc;
+      margin: 0;
+      padding: 6px 13px; }
+    table tr td {
+      border: 1px solid #cccccc;
+      margin: 0;
+      padding: 6px 13px; }
+    table tr th :first-child, table tr td :first-child {
+      margin-top: 0; }
+    table tr th :last-child, table tr td :last-child {
+      margin-bottom: 0; }
+
+img {
+  max-width: 100%; }
+
+span.frame {
+  display: block;
+  overflow: hidden; }
+  span.frame > span {
+    border: 1px solid #dddddd;
+    display: block;
+    float: left;
+    overflow: hidden;
+    margin: 13px 0 0;
+    padding: 7px;
+    width: auto; }
+  span.frame span img {
+    display: block;
+    float: left; }
+  span.frame span span {
+    clear: both;
+    color: #333333;
+    display: block;
+    padding: 5px 0 0; }
+span.align-center {
+  display: block;
+  overflow: hidden;
+  clear: both; }
+  span.align-center > span {
+    display: block;
+    overflow: hidden;
+    margin: 13px auto 0;
+    text-align: center; }
+  span.align-center span img {
+    margin: 0 auto;
+    text-align: center; }
+span.align-right {
+  display: block;
+  overflow: hidden;
+  clear: both; }
+  span.align-right > span {
+    display: block;
+    overflow: hidden;
+    margin: 13px 0 0;
+    text-align: right; }
+  span.align-right span img {
+    margin: 0;
+    text-align: right; }
+span.float-left {
+  display: block;
+  margin-right: 13px;
+  overflow: hidden;
+  float: left; }
+  span.float-left span {
+    margin: 13px 0 0; }
+span.float-right {
+  display: block;
+  margin-left: 13px;
+  overflow: hidden;
+  float: right; }
+  span.float-right > span {
+    display: block;
+    overflow: hidden;
+    margin: 13px auto 0;
+    text-align: right; }
+
+code, tt {
+  margin: 0 2px;
+  padding: 0 5px;
+  white-space: nowrap;
+  border: 1px solid #eaeaea;
+  background-color: #f8f8f8;
+  border-radius: 3px; }
+
+pre code {
+  margin: 0;
+  padding: 0;
+  white-space: pre;
+  border: none;
+  background: transparent; }
+
+.highlight pre {
+  background-color: #f8f8f8;
+  border: 1px solid #cccccc;
+  font-size: 13px;
+  line-height: 19px;
+  overflow: auto;
+  padding: 6px 10px;
+  border-radius: 3px; }
+
+pre {
+  background-color: #f8f8f8;
+  border: 1px solid #cccccc;
+  font-size: 13px;
+  line-height: 19px;
+  overflow: auto;
+  padding: 6px 10px;
+  border-radius: 3px; }
+  pre code, pre tt {
+    background-color: transparent;
+    border: none; }
+
+sup {
+    font-size: 0.83em;
+    vertical-align: super;
+    line-height: 0;
+}
+* {
+	-webkit-print-color-adjust: exact;
+}
+ at media screen and (min-width: 914px) {
+    body {
+        width: 854px;
+        margin:0 auto;
+    }
+}
+ at media print {
+	table, pre {
+		page-break-inside: avoid;
+	}
+	pre {
+		word-wrap: break-word;
+	}
+}
+</style>
diff --git a/proof/doc/confman/img/sshcertauth-web.png b/proof/doc/confman/img/sshcertauth-web.png
new file mode 100644
index 0000000..801117c
Binary files /dev/null and b/proof/doc/confman/img/sshcertauth-web.png differ
diff --git a/proof/proof/inc/TDSet.h b/proof/proof/inc/TDSet.h
index ebc3717..a824e81 100644
--- a/proof/proof/inc/TDSet.h
+++ b/proof/proof/inc/TDSet.h
@@ -93,6 +93,7 @@ private:
    TString          fDataSet;    // Name of the dataset of which this element is part
    TList           *fAssocObjList;  // List of objects associated to this element
                                    // (e.g. TObjString describing associated files)
+   Float_t          fMaxProcTime; // Max processing time in secs; -1 no limit
 
    Bool_t           HasBeenLookedUp() const { return TestBit(kHasBeenLookedUp); }
 
@@ -140,9 +141,12 @@ public:
    void             SetLookedUp() { SetBit(kHasBeenLookedUp); }
    TFileInfo       *GetFileInfo(const char *type = "TTree");
 
+   Float_t          GetMaxProcTime() const { return fMaxProcTime; }
+   void             SetMaxProcTime(Float_t mpt) { fMaxProcTime = mpt; }
+
    Int_t            MergeElement(TDSetElement *elem);
 
-   ClassDef(TDSetElement,8)  // A TDSet element
+   ClassDef(TDSetElement,9)  // A TDSet element
 };
 
 
diff --git a/proof/proof/inc/TDataSetManagerAliEn.h b/proof/proof/inc/TDataSetManagerAliEn.h
index 511148a..17f4c4d 100644
--- a/proof/proof/inc/TDataSetManagerAliEn.h
+++ b/proof/proof/inc/TDataSetManagerAliEn.h
@@ -1,4 +1,4 @@
-// @(#)root/proof:$Id$
+// @(#)root/proof:$Id: 511148a2a899e02c8f5b86a7d87caee2e5979f9d $
 // Author: Dario Berzano, 26.11.12
 
 /*************************************************************************
@@ -123,7 +123,7 @@ class TDataSetManagerAliEn : public TDataSetManager {
          ULong_t cacheExpire_s);
       TDataSetManagerAliEn(const char *, const char *, const char *cfgStr);
 
-      virtual TList *GetFindCommandsFromUri(TString &uri, EDataMode &dataMode);
+      virtual TList *GetFindCommandsFromUri(TString &uri, EDataMode &dataMode, Bool_t &forceUpdate);
 
       virtual ~TDataSetManagerAliEn();
       virtual TFileCollection *GetDataSet(const char *uri, const char * = 0);
diff --git a/proof/proof/inc/TProof.h b/proof/proof/inc/TProof.h
index ddc6008..43a01d5 100644
--- a/proof/proof/inc/TProof.h
+++ b/proof/proof/inc/TProof.h
@@ -138,9 +138,10 @@ class TSelector;
 // 32 -> 33: Development cycle 5.29/04 (fixed worker activation, new startup technology, ...)
 // 33 -> 34: Development cycle 5.33/02 (fix load issue, ...)
 // 34 -> 35: Development cycle 5.99/01 (PLite on workers, staging requests in separate dsmgr...)
+// 35 -> 36: SetParallel in dynamic mode (changes default in GoParallel), cancel staging requests
 
 // PROOF magic constants
-const Int_t       kPROOF_Protocol        = 35;            // protocol version number
+const Int_t       kPROOF_Protocol        = 36;            // protocol version number
 const Int_t       kPROOF_Port            = 1093;          // IANA registered PROOF port
 const char* const kPROOF_ConfFile        = "proof.conf";  // default config file
 const char* const kPROOF_ConfDir         = "/usr/local/root";  // default config dir
@@ -158,6 +159,7 @@ const char* const kPROOF_TerminateWorker = "+++ terminating +++"; // signal work
 const char* const kPROOF_WorkerIdleTO    = "+++ idle-timeout +++"; // signal worker idle timeout in MarkBad
 const char* const kPROOF_InputDataFile   = "inputdata.root";      // Default input data file name
 const char* const kPROOF_MissingFiles    = "MissingFiles";  // Missingfile list name
+const Long64_t    kPROOF_DynWrkPollInt_s = 10;  // minimum number of seconds between two polls for dyn wrks
 
 #ifndef R__WIN32
 const char* const kCP     = "/bin/cp -fp";
@@ -464,7 +466,8 @@ private:
       kSetDefaultTreeName  = 12, //Set the default tree name
       kCache               = 13, //Show/clear cache
       kRequestStaging      = 14, //Request staging of a dataset
-      kStagingStatus       = 15  //Obtain staging status for the given dataset
+      kStagingStatus       = 15, //Obtain staging status for the given dataset
+      kCancelStaging       = 16  //Cancels dataset staging request
    };
    enum ESendFileOpt {
       kAscii               = 0x0,
@@ -505,6 +508,8 @@ private:
    TList          *fRecvMessages;    //Messages received during collect not yet processed
    TList          *fSlaveInfo;       //!list returned by kPROOF_GETSLAVEINFO
    Bool_t          fSendGroupView;   //if true send new group view
+   Bool_t          fIsPollingWorkers;  //will be set to kFALSE to prevent recursive dyn workers check in dyn mode
+   Long64_t        fLastPollWorkers_s;  //timestamp (in seconds) of last poll for workers, -1 if never checked
    TList          *fActiveSlaves;    //list of active slaves (subset of all slaves)
    TString         fActiveSlavesSaved;// comma-separated list of active slaves (before last call to
                                       // SetParallel or Activate/DeactivateWorkers)
@@ -588,6 +593,8 @@ private:
    Int_t           fRedirectNext;
 
    TString         fPerfTree;        // If non-null triggers saving of the performance info into fPerfTree
+
+   TList          *fWrksOutputReady; // List of workers ready to send output (in control output sending mode)
    
    static TPluginHandler *fgLogViewer;  // Log dialog box plugin
 
@@ -642,12 +649,13 @@ private:
    void     AskStatistics();
    void     AskParallel();
    Int_t    GoParallel(Int_t nodes, Bool_t accept = kFALSE, Bool_t random = kFALSE);
+   Int_t    GoMoreParallel(Int_t nWorkersToAdd);
    Int_t    SetParallelSilent(Int_t nodes, Bool_t random = kFALSE);
    void     RecvLogFile(TSocket *s, Int_t size);
    void     NotifyLogMsg(const char *msg, const char *sfx = "\n");
    Int_t    BuildPackage(const char *package, EBuildPackageOpt opt = kBuildAll, Int_t chkveropt = 2);
    Int_t    BuildPackageOnClient(const char *package, Int_t opt = 0, TString *path = 0, Int_t chkveropt = 2);
-   Int_t    LoadPackage(const char *package, Bool_t notOnClient = kFALSE, TList *loadopts = 0);
+   Int_t    LoadPackage(const char *package, Bool_t notOnClient = kFALSE, TList *loadopts = 0, TList *workers = 0);
    Int_t    LoadPackageOnClient(const char *package, TList *loadopts = 0);
    Int_t    UnloadPackage(const char *package);
    Int_t    UnloadPackageOnClient(const char *package);
@@ -678,6 +686,7 @@ private:
    Int_t    HandleInputMessage(TSlave *wrk, TMessage *m, Bool_t deactonfail = kFALSE);
    void     HandleSubmerger(TMessage *mess, TSlave *sl);
    void     SetMonitor(TMonitor *mon = 0, Bool_t on = kTRUE);
+   Int_t    PollForNewWorkers();
 
    void     ReleaseMonitor(TMonitor *mon);
 
@@ -862,6 +871,9 @@ public:
    void        StopProcess(Bool_t abort, Int_t timeout = -1);
    void        Browse(TBrowser *b);
 
+   virtual Int_t Echo(const TObject *obj);
+   virtual Int_t Echo(const char *str);
+
    Int_t       SetParallel(Int_t nodes = -1, Bool_t random = kFALSE);
    void        SetLogLevel(Int_t level, UInt_t mask = TProofDebug::kAll);
 
@@ -878,17 +890,17 @@ public:
    Int_t         ClearPackages();
    Int_t         ClearPackage(const char *package);
    Int_t         DownloadPackage(const char *par, const char *dstdir = 0);
-   Int_t         EnablePackage(const char *package, Bool_t notOnClient = kFALSE);
+   Int_t         EnablePackage(const char *package, Bool_t notOnClient = kFALSE, TList *workers = 0);
    Int_t         EnablePackage(const char *package, const char *loadopts,
-                               Bool_t notOnClient = kFALSE);
+                               Bool_t notOnClient = kFALSE, TList *workers = 0);
    Int_t         EnablePackage(const char *package, TList *loadopts,
-                               Bool_t notOnClient = kFALSE);
-   Int_t         UploadPackage(const char *par, EUploadPackageOpt opt = kUntar);
+                               Bool_t notOnClient = kFALSE, TList *workers = 0);
+   Int_t         UploadPackage(const char *par, EUploadPackageOpt opt = kUntar, TList *workers = 0);
    virtual Int_t Load(const char *macro, Bool_t notOnClient = kFALSE, Bool_t uniqueOnly = kTRUE,
                       TList *wrks = 0);
 
-   Int_t       AddDynamicPath(const char *libpath, Bool_t onClient = kFALSE, TList *wrks = 0);
-   Int_t       AddIncludePath(const char *incpath, Bool_t onClient = kFALSE, TList *wrks = 0);
+   Int_t       AddDynamicPath(const char *libpath, Bool_t onClient = kFALSE, TList *wrks = 0, Bool_t doCollect = kTRUE);
+   Int_t       AddIncludePath(const char *incpath, Bool_t onClient = kFALSE, TList *wrks = 0, Bool_t doCollect = kTRUE);
    Int_t       RemoveDynamicPath(const char *libpath, Bool_t onClient = kFALSE);
    Int_t       RemoveIncludePath(const char *incpath, Bool_t onClient = kFALSE);
 
@@ -913,6 +925,7 @@ public:
    virtual Bool_t RequestStagingDataSet(const char *dataset);
    virtual TFileCollection *GetStagingStatusDataSet(const char *dataset);
    virtual void   ShowStagingStatusDataSet(const char *dataset, const char *optStr = "filter:SsCc");
+   virtual Bool_t CancelStagingDataSet(const char *dataset);
 
    virtual Int_t SetDataSetTreeName( const char *dataset, const char *treename);
 
diff --git a/proof/proof/inc/TProofLog.h b/proof/proof/inc/TProofLog.h
index 5d57956..27ac471 100644
--- a/proof/proof/inc/TProofLog.h
+++ b/proof/proof/inc/TProofLog.h
@@ -1,4 +1,4 @@
-// @(#)root/proof:$Id$
+// @(#)root/proof:$Id: 5d579564fccbadad9cd6f81ccb7726dddea80e0d $
 // Author: G. Ganis   31/08/06
 
 /*************************************************************************
@@ -64,7 +64,7 @@ public:
    TList *GetListOfLogs() const { return fElem; }
    Int_t  Grep(const char *txt, Int_t from = 0);
    void   Print(Option_t *opt = 0) const;
-   void   Prt(const char *what);
+   void   Prt(const char *what, Bool_t newline = kTRUE);
    Int_t  Retrieve(const char *ord = "*",
                   TProofLog::ERetrieveOpt opt = TProofLog::kTrailing,
                   const char *fname = 0, const char *pattern = 0);
diff --git a/proof/proof/inc/TSlave.h b/proof/proof/inc/TSlave.h
index 3110eda..e2c4f8a 100644
--- a/proof/proof/inc/TSlave.h
+++ b/proof/proof/inc/TSlave.h
@@ -58,6 +58,9 @@ public:
 
    enum ESlaveType { kMaster, kSlave };
    enum ESlaveStatus { kInvalid, kActive, kInactive };
+   enum EStatusBits {
+      kOutputRequested = BIT(15)       // If output has been requested
+   };
 
 private:
 
diff --git a/proof/proof/inc/TVirtualProofPlayer.h b/proof/proof/inc/TVirtualProofPlayer.h
index a7aa325..8ba1d78 100644
--- a/proof/proof/inc/TVirtualProofPlayer.h
+++ b/proof/proof/inc/TVirtualProofPlayer.h
@@ -60,6 +60,7 @@ public:
    virtual Long64_t  Process(TDSet *set,
                              TSelector *selector, Option_t *option = "",
                              Long64_t nentries = -1, Long64_t firstentry = 0) = 0;
+   virtual Bool_t    JoinProcess(TList *workers) = 0;
    virtual Long64_t  Finalize(Bool_t force = kFALSE, Bool_t sync = kFALSE) = 0;
    virtual Long64_t  Finalize(TQueryResult *qr) = 0;
    virtual Long64_t  DrawSelect(TDSet *set, const char *varexp,
diff --git a/proof/proof/src/TDSet.cxx b/proof/proof/src/TDSet.cxx
index 568eb9a..66de197 100644
--- a/proof/proof/src/TDSet.cxx
+++ b/proof/proof/src/TDSet.cxx
@@ -124,6 +124,7 @@ TDSetElement::TDSetElement(const char *file, const char *objname, const char *di
    fAssocObjList = 0;
    if (dir)
       fDirectory = dir;
+   fMaxProcTime = -1.;
 
    ResetBit(kWriteV3);
    ResetBit(kHasBeenLookedUp);
@@ -149,6 +150,7 @@ TDSetElement::TDSetElement(const TDSetElement& elem)
    fFriends = 0;
    fDataSet = elem.fDataSet;
    fAssocObjList = 0;
+   fMaxProcTime = elem.fMaxProcTime;
    ResetBit(kWriteV3);
    ResetBit(kHasBeenLookedUp);
    ResetBit(kEmpty);
@@ -987,8 +989,14 @@ void TDSet::SetObjName(const char *objname)
 {
    // Set/change object name.
 
-   if (objname)
+   if (objname) {
       fObjName = objname;
+      TIter next(GetListOfElements());
+      TDSetElement *e;
+      while ((e = (TDSetElement *) next())) {
+         e->SetTitle(objname);
+      }
+   }
 }
 
 //______________________________________________________________________________
diff --git a/proof/proof/src/TDataSetManagerAliEn.cxx b/proof/proof/src/TDataSetManagerAliEn.cxx
index e7b71c0..bb66409 100644
--- a/proof/proof/src/TDataSetManagerAliEn.cxx
+++ b/proof/proof/src/TDataSetManagerAliEn.cxx
@@ -121,9 +121,10 @@ TGridResult *TAliEnFind::GetGridResult(Bool_t forceNewQuery)
       TPMERegexp *reArchSubst = NULL;
       TString substWith;
       if (fArchSubst) {
-         TString temp = Form("/%s$", fFileName.Data());
+         TString temp;
+         temp.Form("/%s$", fFileName.Data());
          reArchSubst = new TPMERegexp(temp.Data());
-         substWith = Form("/root_archive.zip#%s", fFileName.Data());
+         substWith.Form("/root_archive.zip#%s", fFileName.Data());
       }
 
       TIter it(fGridResult);
@@ -312,8 +313,9 @@ void TDataSetManagerAliEn::Init(TString cacheDir, TString urlTpl,
   fUrlTpl = urlTpl;
   fUrlTpl.ReplaceAll("<path>", "$1");
 
-  fCache = new TDataSetManagerFile("_cache_", "_cache_",
-    Form("dir:%s perms:open", cacheDir.Data()));
+  TString dsDirFmt;
+  dsDirFmt.Form("dir:%s perms:open", cacheDir.Data());
+  fCache = new TDataSetManagerFile("_cache_", "_cache_", dsDirFmt);
 
   if (fCache->TestBit(TObject::kInvalidObject)) {
     Error("Init", "Cannot initialize cache on directory %s", cacheDir.Data());
@@ -379,7 +381,7 @@ TDataSetManagerAliEn::~TDataSetManagerAliEn()
 
 //______________________________________________________________________________
 TList *TDataSetManagerAliEn::GetFindCommandsFromUri(TString &uri,
-  EDataMode &dataMode)
+  EDataMode &dataMode, Bool_t &forceUpdate)
 {
   // Parse kind
   TPMERegexp reKind("^(Data;|Sim;|Find;)");
@@ -466,19 +468,20 @@ TList *TDataSetManagerAliEn::GetFindCommandsFromUri(TString &uri,
           TGrid::Connect("alien:");
           if (!gGrid) {
             delete findCommands;
+            delete runList;
             return NULL;
           }
         }
 
-        basePath = Form("/alice/sim/%s", lhcPeriod.Data());  // no year
+        basePath.Form("/alice/sim/%s", lhcPeriod.Data());  // no year
         if (!gGrid->Cd(basePath.Data())) {
-          basePath = Form("/alice/sim/%d/%s", year, lhcPeriod.Data());
+          basePath.Form("/alice/sim/%d/%s", year, lhcPeriod.Data());
         }
         temp.Form("/%06d", runList->at(i));
         basePath.Append(temp);
 
         if (!esd) {
-          temp = Form("/AOD%03d", aodNum);
+          temp.Form("/AOD%03d", aodNum);
           basePath.Append(temp);
         }
       }
@@ -492,13 +495,13 @@ TList *TDataSetManagerAliEn::GetFindCommandsFromUri(TString &uri,
         if ((pass[0] >= '0') && (pass[0] <= '9')) pass.Prepend("pass");
 
         // Data
-        basePath = Form("/alice/data/%d/%s/%09d/ESDs/%s", year,
+        basePath.Form("/alice/data/%d/%s/%09d/ESDs/%s", year,
           lhcPeriod.Data(), runList->at(i), pass.Data());
         if (esd) {
           basePath.Append("/*.*");
         }
         else {
-          temp = Form("/AOD%03d", aodNum);
+          temp.Form("/AOD%03d", aodNum);
           basePath.Append(temp);
         }
       }
@@ -524,7 +527,11 @@ TList *TDataSetManagerAliEn::GetFindCommandsFromUri(TString &uri,
 
   }
 
-  // If no valid data found, then findCommands is NULL
+  // Force update or use cache (when possible)
+  TPMERegexp reForceUpdate("(^|;)ForceUpdate(;|$)");
+  forceUpdate = (reForceUpdate.Match(uri) == 3);
+
+  // If no valid data was found, then findCommands is NULL
   return findCommands;
 }
 
@@ -712,9 +719,10 @@ TFileCollection *TDataSetManagerAliEn::GetDataSet(const char *uri, const char *)
 {
   TFileCollection *fc = NULL;  // global collection
 
-  EDataMode dataMode;
   TString sUri(uri);
-  TList *findCmds = GetFindCommandsFromUri(sUri, dataMode);
+  EDataMode dataMode;
+  Bool_t forceUpdate;
+  TList *findCmds = GetFindCommandsFromUri(sUri, dataMode, forceUpdate);
   if (!findCmds) return NULL;
 
   fc = new TFileCollection();  // this fc will contain all data
@@ -736,9 +744,13 @@ TFileCollection *TDataSetManagerAliEn::GetDataSet(const char *uri, const char *)
     Long_t now = gSystem->Now();
     now = now/1000 + 788914800;  // magic is secs between Jan 1st 1970 and 1995
 
-    if ((mtime > 0) && (now-mtime > fCacheExpire_s)) {
+    if (forceUpdate) {
+      if (gDebug >= 1)
+        Info("GetDataSet", "Ignoring cached query result: forcing update");
+    }
+    else if ((mtime > 0) && (now-mtime > fCacheExpire_s)) {
       if (gDebug >= 1)
-        Info("GetDataSet", "Dataset cache expired");
+        Info("GetDataSet", "Dataset cache has expired");
     }
     else {
       if (gDebug >= 1)
diff --git a/proof/proof/src/TProof.cxx b/proof/proof/src/TProof.cxx
index 726b19c..9b66b76 100644
--- a/proof/proof/src/TProof.cxx
+++ b/proof/proof/src/TProof.cxx
@@ -516,6 +516,8 @@ void TProof::InitMembers()
    fSlaveInfo = 0;
    fMasterServ = kFALSE;
    fSendGroupView = kFALSE;
+   fIsPollingWorkers = kFALSE;
+   fLastPollWorkers_s = -1;
    fActiveSlaves = 0;
    fInactiveSlaves = 0;
    fUniqueSlaves = 0;
@@ -597,6 +599,8 @@ void TProof::InitMembers()
    
    fPerfTree = "";
 
+   fWrksOutputReady = 0;
+
    fSelector = 0;
 
    // Check if the user defined a list of environment variables to send over:
@@ -685,6 +689,10 @@ TProof::~TProof()
    SafeDelete(fInputData);
    SafeDelete(fRunningDSets);
    SafeDelete(fCloseMutex);
+   if (fWrksOutputReady) {
+      fWrksOutputReady->SetOwner(kFALSE);
+      delete fWrksOutputReady;
+   }
 
    // remove file with redirected logs
    if (TestBit(TProof::kIsClient)) {
@@ -968,7 +976,7 @@ Int_t TProof::Init(const char *, const char *conffile,
    fAllMonitor->DeActivateAll();
 
    // By default go into parallel mode
-   Int_t nwrk = -1;
+   Int_t nwrk = GetRemoteProtocol() > 35 ? -1 : 9999;
    TNamed *n = 0;
    if (TProof::GetEnvVars() &&
       (n = (TNamed *) TProof::GetEnvVars()->FindObject("PROOF_NWORKERS"))) {
@@ -1096,7 +1104,7 @@ void TProof::ParseConfigField(const char *config)
             // Check if we have to add a var
             if (wrk == "" || wrk.BeginsWith("valgrind_opts:")) {
                wrk.ReplaceAll("valgrind_opts:","");
-               var.Form("%s --log-file=<logfilewrk>.valgrind.log %s%s", cmd.Data(), wrk.Data(), cq);
+               var.Form("%s --log-file=<logfilewrk>.__valgrind__.log %s%s", cmd.Data(), wrk.Data(), cq);
                TProof::AddEnvVar("PROOF_SLAVE_WRAPPERCMD", var);
                TString nwrks("2");
                Int_t inw = opt.Index('#');
@@ -1112,8 +1120,8 @@ void TProof::ParseConfigField(const char *config)
                }
                wrklab = nwrks;
                // Register the additional worker log in the session file
-               // (for the master is done automatically)
-               TProof::AddEnvVar("PROOF_ADDITIONALLOG", "valgrind.log*");
+               // (for the master this is done automatically)
+               TProof::AddEnvVar("PROOF_ADDITIONALLOG", "__valgrind__.log*");
             } else if (wrk != "") {
                wrklab = "ALL";
             }
@@ -1137,6 +1145,30 @@ void TProof::ParseConfigField(const char *config)
          Printf(" ---> (Reminder: this debug run makes sense only if you are running a debug version of ROOT)");
          Printf(" ");
 
+      } else if (opt.BeginsWith("igprof-pp")) {
+
+         // IgProf profiling on master and worker. PROOF does not set the
+         // environment for you: proper environment variables (like PATH and
+         // LD_LIBRARY_PATH) should be set externally
+
+         Printf("*** Requested IgProf performance profiling ***");
+         TString addLogExt = "__igprof.pp__.log";
+         TString addLogFmt = "igprof -pk -pp -t proofserv.exe -o %s.%s";
+         TString tmp;
+
+         if (IsLite()) {
+            addLogFmt.Append("\"");
+            addLogFmt.Prepend("\"");
+         }
+
+         tmp.Form(addLogFmt.Data(), "<logfilemst>", addLogExt.Data());
+         TProof::AddEnvVar("PROOF_MASTER_WRAPPERCMD",  tmp.Data());
+
+         tmp.Form(addLogFmt.Data(), "<logfilewrk>", addLogExt.Data());
+         TProof::AddEnvVar("PROOF_SLAVE_WRAPPERCMD", tmp.Data() );
+
+         TProof::AddEnvVar("PROOF_ADDITIONALLOG", addLogExt.Data());
+
       } else if (opt.BeginsWith("workers=")) {
 
          // Request for a given number of workers (within the max) or worker
@@ -1227,7 +1259,8 @@ Int_t TProof::AddWorkers(TList *workerList)
    UInt_t nSlavesDone = 0;
    Int_t ord = 0;
 
-   // Loop over all workers and start them
+   // Loop over all new workers and start them
+   Bool_t goMoreParallel = (fSlaves->GetEntries() > 0);
 
    // a list of TSlave objects for workers that are being added
    TList *addedWorkers = new TList();
@@ -1343,15 +1376,30 @@ Int_t TProof::AddWorkers(TList *workerList)
    // use fEnabledPackages, fLoadedMacros,
    // gSystem->GetDynamicPath() and gSystem->GetIncludePath()
    // no need to load packages that are only loaded and not enabled (dyn mode)
-   Int_t nwrk = -1;
+   Int_t nwrk = GetRemoteProtocol() > 35 ? -1 : 9999;
    TNamed *n = 0;
    if (TProof::GetEnvVars() &&
       (n = (TNamed *) TProof::GetEnvVars()->FindObject("PROOF_NWORKERS"))) {
       TString s(n->GetTitle());
       if (s.IsDigit()) nwrk = s.Atoi();
    }
-   GoParallel(nwrk, kFALSE, 0);
-      
+
+   if (fDynamicStartup && goMoreParallel) {
+
+      PDB(kGlobal, 3)
+         Info("AddWorkers", "Will invoke GoMoreParallel()");
+      Int_t nw = GoMoreParallel(nwrk);
+      PDB(kGlobal, 3)
+         Info("AddWorkers", "GoMoreParallel()=%d", nw);
+
+   }
+   else {
+      // Not in Dynamic Workers mode
+      PDB(kGlobal, 3)
+         Info("AddWorkers", "Will invoke GoParallel()");
+      GoParallel(nwrk, kFALSE, 0);
+   }
+
    if (gProofServ && gProofServ->GetEnabledPackages() &&
        gProofServ->GetEnabledPackages()->GetSize() > 0) {
       TIter nxp(gProofServ->GetEnabledPackages());      
@@ -1359,16 +1407,28 @@ Int_t TProof::AddWorkers(TList *workerList)
       while ((pck = (TPair *) nxp())) {
          // Upload and Enable methods are intelligent and avoid
          // re-uploading or re-enabling of a package to a node that has it.
-         if (UploadPackage(pck->GetName()) >= 0)
-            EnablePackage(pck->GetName(), (TList *) pck->Value(), kTRUE);
+         if (fDynamicStartup && goMoreParallel) {
+            // Upload only on added workers
+            PDB(kGlobal, 3)
+               Info("AddWorkers", "Will invoke UploadPackage() and EnablePackage() on added workers");
+            if (UploadPackage(pck->GetName(), kUntar, addedWorkers) >= 0)
+               EnablePackage(pck->GetName(), (TList *) pck->Value(), kTRUE, addedWorkers);
+         }
+         else {
+            PDB(kGlobal, 3)
+               Info("AddWorkers", "Will invoke UploadPackage() and EnablePackage() on all workers");
+            if (UploadPackage(pck->GetName()) >= 0)
+               EnablePackage(pck->GetName(), (TList *) pck->Value(), kTRUE);
+         }
       }
    }
 
-
    if (fLoadedMacros) {
       TIter nxp(fLoadedMacros);
       TObjString *os = 0;
       while ((os = (TObjString *) nxp())) {
+         PDB(kGlobal, 3)
+            Info("AddWorkers", "Will invoke Load() on selected workers");
          Printf("Loading a macro : %s", os->GetName());
          Load(os->GetName(), kTRUE, kTRUE, addedWorkers);
       }
@@ -1377,22 +1437,41 @@ Int_t TProof::AddWorkers(TList *workerList)
    TString dyn = gSystem->GetDynamicPath();
    dyn.ReplaceAll(":", " ");
    dyn.ReplaceAll("\"", " ");
-   AddDynamicPath(dyn, kFALSE, addedWorkers);
+   PDB(kGlobal, 3)
+      Info("AddWorkers", "Will invoke AddDynamicPath() on selected workers");
+   AddDynamicPath(dyn, kFALSE, addedWorkers, fDynamicStartup);
+
    TString inc = gSystem->GetIncludePath();
    inc.ReplaceAll("-I", " ");
    inc.ReplaceAll("\"", " ");
-   AddIncludePath(inc, kFALSE, addedWorkers);
-
-   // Cleanup
-   delete addedWorkers;
+   PDB(kGlobal, 3)
+      Info("AddWorkers", "Will invoke AddIncludePath() on selected workers");
+   AddIncludePath(inc, kFALSE, addedWorkers, fDynamicStartup);
 
    // Update list of current workers
+   PDB(kGlobal, 3)
+      Info("AddWorkers", "Will invoke SaveWorkerInfo()");
    SaveWorkerInfo();
 
-   // Inform the client that the number of workers is changed
-   if (fDynamicStartup && gProofServ)
+   // Inform the client that the number of workers has changed
+   if (fDynamicStartup && gProofServ) {
+      PDB(kGlobal, 3)
+         Info("AddWorkers", "Will invoke SendParallel()");
       gProofServ->SendParallel(kTRUE);
 
+      if (goMoreParallel && fPlayer) {
+         // In case we are adding workers dynamically to an existing process, we
+         // should invoke a special player's Process() to set only added workers
+         // to the proper state
+         PDB(kGlobal, 3)
+            Info("AddWorkers", "Will send the PROCESS message to selected workers");
+         fPlayer->JoinProcess(addedWorkers);
+      }
+   }
+
+   // Cleanup
+   delete addedWorkers;
+
    return 0;
 }
 
@@ -2560,6 +2639,13 @@ Int_t TProof::Collect(TMonitor *mon, Long_t timeout, Int_t endtype, Bool_t deact
    // If timeout >= 0, wait at most timeout seconds (timeout = -1 by default,
    // which means wait forever).
    // If defined (>= 0) endtype is the message that stops this collection.
+   // Collect also stops its execution from time to time to check for new
+   // workers in Dynamic Startup mode.
+
+   Int_t collectId = gRandom->Integer(9999);
+
+   PDB(kCollect, 3)
+      Info("Collect", ">>>>>> Entering collect responses #%04d", collectId);
 
    // Reset the status flag and clear the messages in the list, if any
    fStatus = 0;
@@ -2627,7 +2713,19 @@ Int_t TProof::Collect(TMonitor *mon, Long_t timeout, Int_t endtype, Bool_t deact
          }
       }
 
+      // Preemptive poll for new workers on the master only in Dynamic Mode and only
+      // during processing (TODO: should work on Top Master only)
+      if (TestBit(TProof::kIsMaster) && !IsIdle() && fDynamicStartup && !fIsPollingWorkers &&
+         ((fLastPollWorkers_s == -1) || (time(0)-fLastPollWorkers_s >= kPROOF_DynWrkPollInt_s))) {
+         fIsPollingWorkers = kTRUE;
+         PollForNewWorkers();
+         fLastPollWorkers_s = time(0);
+         fIsPollingWorkers = kFALSE;
+      }
+
       // Wait for a ready socket
+      PDB(kCollect, 3)
+         Info("Collect", "Will invoke Select() #%04d", collectId);
       TSocket *s = mon->Select(1000);
 
       if (s && s != (TSocket *)(-1)) {
@@ -2666,13 +2764,41 @@ Int_t TProof::Collect(TMonitor *mon, Long_t timeout, Int_t endtype, Bool_t deact
          if (s == (TSocket *)(-1) && nto > 0)
             nto--;
       }
+
+      // Check if there are workers with ready output to be sent and ask the first to send it
+      if (IsMaster() && fWrksOutputReady && fWrksOutputReady->GetSize() > 0) {
+         // Maximum number of concurrent sendings
+         Int_t mxws = gEnv->GetValue("Proof.ControlSendOutput", 1);
+         if (TProof::GetParameter(fPlayer->GetInputList(), "PROOF_ControlSendOutput", mxws) != 0)
+            mxws = gEnv->GetValue("Proof.ControlSendOutput", 1);
+         TIter nxwr(fWrksOutputReady);
+         TSlave *wrk = 0;
+         while (mxws && (wrk = (TSlave *) nxwr())) {
+            if (!wrk->TestBit(TSlave::kOutputRequested)) {
+               // Ask worker for output
+               TMessage sendoutput(kPROOF_SENDOUTPUT);
+               PDB(kCollect, 2)
+                  Info("Collect", "worker %s was asked to send its output to master",
+                                                wrk->GetOrdinal());
+               if (wrk->GetSocket()->Send(sendoutput) != 1) {
+                  wrk->SetBit(TSlave::kOutputRequested);
+                  mxws--;
+               }
+            } else {
+               // Count
+               mxws--;
+            }
+         }
+      }
+
       // Check if we need to check the socket activity (we do it every 10 cycles ~ 10 sec)
       sto = -1;
       if (--nsto <= 0) {
          sto = (Long_t) actto;
          nsto = 60;
       }
-   }
+
+   } // end loop over active monitors
 
    // If timed-out, deactivate the remaining sockets
    if (nto == 0) {
@@ -2709,10 +2835,90 @@ Int_t TProof::Collect(TMonitor *mon, Long_t timeout, Int_t endtype, Bool_t deact
 
    ActivateAsyncInput();
 
+   PDB(kCollect, 3)
+      Info("Collect", "<<<<<< Exiting collect responses #%04d", collectId);
+
    return cnt;
 }
 
 //______________________________________________________________________________
+Int_t TProof::PollForNewWorkers()
+{
+   // Asks the PROOF Serv for new workers in Dynamic Startup mode and activates
+   // them. Returns the number of new workers found, or <0 on errors.
+
+   // Requests for worker updates
+   Int_t dummy = 0;
+   TList *reqWorkers = new TList();
+   reqWorkers->SetOwner(kFALSE);
+
+   if (!TestBit(TProof::kIsMaster)) {
+      Error("PollForNewWorkers", "Can't invoke: not on a master -- should not happen!");
+      return -1;
+   }
+   if (!gProofServ) {
+      Error("PollForNewWorkers", "No ProofServ available -- should not happen!");
+      return -1;
+   }
+
+   gProofServ->GetWorkers(reqWorkers, dummy, kTRUE);  // last 2 are dummy
+
+   // List of new workers only (TProofNodeInfo)
+   TList *newWorkers = new TList();
+   newWorkers->SetOwner(kTRUE);
+
+   TIter next(reqWorkers);
+   TProofNodeInfo *ni;
+   TString fullOrd;
+   while (( ni = dynamic_cast<TProofNodeInfo *>(next()) )) {
+
+      // Form the full ordinal
+      fullOrd.Form("%s.%s", gProofServ->GetOrdinal(), ni->GetOrdinal().Data());
+
+      TIter nextInner(fSlaves);
+      TSlave *sl;
+      Bool_t found = kFALSE;
+      while (( sl = dynamic_cast<TSlave *>(nextInner()) )) {
+         if ( strcmp(sl->GetOrdinal(), fullOrd.Data()) == 0 ) {
+            found = kTRUE;
+            break;
+         }
+      }
+
+      if (found) delete ni;
+      else {
+         newWorkers->Add(ni);
+         PDB(kGlobal, 1)
+            Info("PollForNewWorkers", "New worker found: %s:%s",
+               ni->GetNodeName().Data(), fullOrd.Data());
+      }
+   }
+
+   delete reqWorkers;  // not owner
+
+   Int_t nNewWorkers = newWorkers->GetEntries();
+
+   // Add the new workers
+   if (nNewWorkers > 0) {
+      PDB(kGlobal, 1)
+         Info("PollForNewWorkers", "Requesting to add %d new worker(s)", newWorkers->GetEntries());
+      Int_t rv = AddWorkers(newWorkers);
+      if (rv < 0) {
+         Error("PollForNewWorkers", "Call to AddWorkers() failed (got %d < 0)", rv);
+         return -1;
+      }
+      // Don't delete newWorkers: AddWorkers() will do that
+   }
+   else {
+      PDB(kGlobal, 2)
+         Info("PollForNewWorkers", "No new worker found");
+      delete newWorkers;
+   }
+
+   return nNewWorkers;
+}
+
+//______________________________________________________________________________
 void TProof::CleanGDirectory(TList *ol)
 {
    // Remove links to objects in list 'ol' from gDirectory
@@ -2915,6 +3121,11 @@ Int_t TProof::HandleInputMessage(TSlave *sl, TMessage *mess, Bool_t deactonfail)
             // Deactivate the worker, if required
             if (deactonfail) DeactivateWorker(sl->fOrdinal);
          }
+         // Remove from the workers-ready list
+         if (fWrksOutputReady && fWrksOutputReady->FindObject(sl)) {
+            sl->ResetBit(TSlave::kOutputRequested);
+            fWrksOutputReady->Remove(sl);
+         }
          rc = 1;
          break;
 
@@ -3005,6 +3216,20 @@ Int_t TProof::HandleInputMessage(TSlave *sl, TMessage *mess, Bool_t deactonfail)
          }
          break;
 
+      case kPROOF_SENDOUTPUT:
+         {  // Worker is ready to send output: make sure the relevant bit is reset
+            sl->ResetBit(TSlave::kOutputRequested);
+            PDB(kGlobal,2)
+               Info("HandleInputMessage","kPROOF_SENDOUTPUT: enter (%s)", sl->GetOrdinal());
+            // Create the list if not yet done
+            if (!fWrksOutputReady) {
+               fWrksOutputReady = new TList;
+               fWrksOutputReady->SetOwner(kFALSE);
+            }
+            fWrksOutputReady->Add(sl);
+         }
+         break;
+
       case kPROOF_OUTPUTOBJECT:
          {
             PDB(kGlobal,2)
@@ -4966,6 +5191,12 @@ Long64_t TProof::Process(TDSet *dset, const char *selector, Option_t *option,
 
    // Make sure we get a fresh result
    fOutputList.Clear();
+
+   // Make sure that the workers ready list is empty
+   if (fWrksOutputReady) {
+      fWrksOutputReady->SetOwner(kFALSE);
+      fWrksOutputReady->Clear();
+   }
    
    Long64_t rv = -1;
    if (selector && strlen(selector)) {
@@ -6599,6 +6830,33 @@ Int_t TProof::SendFile(const char *file, Int_t opt, const char *rfile, TSlave *w
 }
 
 //______________________________________________________________________________
+Int_t TProof::Echo(const TObject *obj)
+{
+   // Sends an object to master and workers and expect them to send back a
+   // message with the output of its TObject::Print(). Returns -1 on error, the
+   // number of workers that received the objects on success.
+
+   if (!IsValid() || !obj) return -1;
+   TMessage mess(kPROOF_ECHO);
+   mess.WriteObject(obj);
+   return Broadcast(mess);
+}
+
+//______________________________________________________________________________
+Int_t TProof::Echo(const char *str)
+{
+   // Sends a string to master and workers and expect them to echo it back to
+   // the client via a message. It is a special case of the generic Echo()
+   // that works with TObjects. Returns -1 on error, the number of workers that
+   // received the message on success.
+
+   TObjString *os = new TObjString(str);
+   Int_t rv = Echo(os);
+   delete os;
+   return rv;
+}
+
+//______________________________________________________________________________
 Int_t TProof::SendObject(const TObject *obj, ESlaves list)
 {
    // Send object to master or slave servers. Returns number of slaves object
@@ -6689,7 +6947,7 @@ Int_t TProof::SetParallel(Int_t nodes, Bool_t random)
    if (fDynamicStartup && nodes < 0) {
       if (gSystem->Getenv("PROOF_NWORKERS")) gSystem->Unsetenv("PROOF_NWORKERS");
    }
-   
+
    Int_t n = SetParallelSilent(nodes, random);
    if (TestBit(TProof::kIsClient)) {
       if (n < 1) {
@@ -6708,6 +6966,107 @@ Int_t TProof::SetParallel(Int_t nodes, Bool_t random)
 }
 
 //______________________________________________________________________________
+Int_t TProof::GoMoreParallel(Int_t nWorkersToAdd)
+{
+   // Add nWorkersToAdd workers to current list of workers. This function is
+   // works on the master only, and only when an analysis is ongoing. A message
+   // is sent back to the client when we go "more" parallel.
+   // Returns -1 on error, number of total (not added!) workers on success.
+
+   if (!IsValid() || !IsMaster() || IsIdle()) {
+      Error("GoMoreParallel", "Can't invoke here -- should not happen!");
+      return -1;
+   }
+   if (!gProofServ) {
+      Error("GoMoreParallel", "No ProofServ available -- should not happen!");
+      return -1;
+   }
+
+   TSlave *sl = 0x0;
+   TIter next( fSlaves );
+   Int_t nAddedWorkers = 0;
+
+   while (((nAddedWorkers < nWorkersToAdd) || (nWorkersToAdd == -1)) &&
+          (( sl = dynamic_cast<TSlave *>( next() ) ))) {
+
+      // If worker is of an invalid type, break everything: it should not happen!
+      if ((sl->GetSlaveType() != TSlave::kSlave) &&
+          (sl->GetSlaveType() != TSlave::kMaster)) {
+         Error("GoMoreParallel", "TSlave is neither a Master nor a Slave: %s:%s",
+            sl->GetName(), sl->GetOrdinal());
+         R__ASSERT(0);
+      }
+
+      // Skip current worker if it is not a good candidate
+      if ((!sl->IsValid()) || (fBadSlaves->FindObject(sl)) ||
+          (strcmp("IGNORE", sl->GetImage()) == 0)) {
+         PDB(kGlobal, 2)
+            Info("GoMoreParallel", "Worker %s:%s won't be considered",
+               sl->GetName(), sl->GetOrdinal());
+         continue;
+      }
+
+      // Worker is good but it is already active: skip it
+      if (fActiveSlaves->FindObject(sl)) {
+         Info("GoMoreParallel", "Worker %s:%s is already active: skipping",
+            sl->GetName(), sl->GetOrdinal());
+         continue;
+      }
+
+      //
+      // From here on: worker is a good candidate
+      //
+
+      if (sl->GetSlaveType() == TSlave::kSlave) {
+         sl->SetStatus(TSlave::kActive);
+         fActiveSlaves->Add(sl);
+         fInactiveSlaves->Remove(sl);
+         fActiveMonitor->Add(sl->GetSocket());
+         nAddedWorkers++;
+         PDB(kGlobal, 2)
+            Info("GoMoreParallel", "Worker %s:%s marked as active!",
+               sl->GetName(), sl->GetOrdinal());
+      }
+      else {
+         // Can't add masters dynamically: this should not happen!
+         Error("GoMoreParallel", "Dynamic addition of master is not supported");
+         R__ASSERT(0);
+      }
+
+   } // end loop over all slaves
+
+   // Get slave status (will set the slaves fWorkDir correctly)
+   PDB(kGlobal, 3)
+      Info("GoMoreParallel", "Will invoke AskStatistics() -- implies a Collect()");
+   AskStatistics();
+
+   // Find active slaves with unique image
+   PDB(kGlobal, 3)
+      Info("GoMoreParallel", "Will invoke FindUniqueSlaves()");
+   FindUniqueSlaves();
+
+   // Send new group-view to slaves
+   PDB(kGlobal, 3)
+      Info("GoMoreParallel", "Will invoke SendGroupView()");
+   SendGroupView();
+
+   PDB(kGlobal, 3)
+      Info("GoMoreParallel", "Will invoke GetParallel()");
+   Int_t nTotalWorkers = GetParallel();
+
+   // Notify the client that we've got more workers, and print info on
+   // Master's log as well
+   TString s;
+   s.Form("PROOF just went more parallel (%d additional worker%s, %d worker%s total)",
+      nAddedWorkers, (nAddedWorkers == 1) ? "" : "s",
+      nTotalWorkers, (nTotalWorkers == 1) ? "" : "s");
+   gProofServ->SendAsynMessage(s);
+   Info("GoMoreParallel", "%s", s.Data());
+
+   return nTotalWorkers;
+}
+
+//______________________________________________________________________________
 Int_t TProof::GoParallel(Int_t nodes, Bool_t attach, Bool_t random)
 {
    // Go in parallel mode with at most "nodes" slaves. Since the fSlaves
@@ -7749,7 +8108,8 @@ Int_t TProof::BuildPackageOnClient(const char *pack, Int_t opt, TString *path, I
 }
 
 //______________________________________________________________________________
-Int_t TProof::LoadPackage(const char *package, Bool_t notOnClient, TList *loadopts)
+Int_t TProof::LoadPackage(const char *package, Bool_t notOnClient,
+   TList *loadopts, TList *workers)
 {
    // Load specified package. Executes the PROOF-INF/SETUP.C script
    // on all active nodes. If notOnClient = true, don't load package
@@ -7779,10 +8139,20 @@ Int_t TProof::LoadPackage(const char *package, Bool_t notOnClient, TList *loadop
    TMessage mess(kPROOF_CACHE);
    mess << Int_t(kLoadPackage) << pac;
    if (loadopts) mess << loadopts;
-   Broadcast(mess);
+
    // On the master, workers that fail are deactivated
    Bool_t deactivateOnFailure = (IsMaster()) ? kTRUE : kFALSE;
-   Collect(kActive, -1, -1, deactivateOnFailure);
+
+   if (workers) {
+      PDB(kPackage, 3)
+         Info("LoadPackage", "Sending load message to selected workers only");
+      Broadcast(mess, workers);
+      Collect(workers, -1, -1, deactivateOnFailure);
+   }
+   else {
+      Broadcast(mess);
+      Collect(kActive, -1, -1, deactivateOnFailure);  
+   }
 
    return fStatus;
 }
@@ -8055,21 +8425,23 @@ Int_t TProof::UnloadPackages()
 }
 
 //______________________________________________________________________________
-Int_t TProof::EnablePackage(const char *package, Bool_t notOnClient)
+Int_t TProof::EnablePackage(const char *package, Bool_t notOnClient,
+   TList *workers)
 {
    // Enable specified package. Executes the PROOF-INF/BUILD.sh
    // script if it exists followed by the PROOF-INF/SETUP.C script.
    // In case notOnClient = true, don't enable the package on the client.
    // The default is to enable packages also on the client.
+   // If specified, enables packages only on the specified workers.
    // Returns 0 in case of success and -1 in case of error.
    // Provided for backward compatibility.
 
-   return EnablePackage(package, (TList *)0, notOnClient);
+   return EnablePackage(package, (TList *)0, notOnClient, workers);
 }
 
 //______________________________________________________________________________
 Int_t TProof::EnablePackage(const char *package, const char *loadopts,
-                            Bool_t notOnClient)
+                            Bool_t notOnClient, TList *workers)
 {
    // Enable specified package. Executes the PROOF-INF/BUILD.sh
    // script if it exists followed by the PROOF-INF/SETUP.C script.
@@ -8082,7 +8454,8 @@ Int_t TProof::EnablePackage(const char *package, const char *loadopts,
    //     off         no check; failure may occur at loading
    //     on          check ROOT version [default]
    //     svn         check ROOT version and SVN revision number.
-   // (Use ';', ' ' or '|' to separate 'chkv=<o>' from the rest.) 
+   // (Use ';', ' ' or '|' to separate 'chkv=<o>' from the rest.)
+   // If specified, enables packages only on the specified workers.
    // Returns 0 in case of success and -1 in case of error.
 
    TList *optls = 0;
@@ -8129,7 +8502,7 @@ Int_t TProof::EnablePackage(const char *package, const char *loadopts,
       }
    }
    // Run
-   Int_t rc = EnablePackage(package, optls, notOnClient);
+   Int_t rc = EnablePackage(package, optls, notOnClient, workers);
    // Clean up
    SafeDelete(optls);
    // Done
@@ -8138,7 +8511,7 @@ Int_t TProof::EnablePackage(const char *package, const char *loadopts,
 
 //______________________________________________________________________________
 Int_t TProof::EnablePackage(const char *package, TList *loadopts,
-                            Bool_t notOnClient)
+                            Bool_t notOnClient, TList *workers)
 {
    // Enable specified package. Executes the PROOF-INF/BUILD.sh
    // script if it exists followed by the PROOF-INF/SETUP.C script.
@@ -8198,7 +8571,7 @@ Int_t TProof::EnablePackage(const char *package, TList *loadopts,
       optls = 0;
    }
 
-   if (LoadPackage(pac, notOnClient, optls) == -1)
+   if (LoadPackage(pac, notOnClient, optls, workers) == -1)
       return -1;
 
    return 0;
@@ -8299,7 +8672,8 @@ Int_t TProof::DownloadPackage(const char *pack, const char *dstdir)
 }
 
 //______________________________________________________________________________
-Int_t TProof::UploadPackage(const char *pack, EUploadPackageOpt opt)
+Int_t TProof::UploadPackage(const char *pack, EUploadPackageOpt opt,
+   TList *workers)
 {
    // Upload a PROOF archive (PAR file). A PAR file is a compressed
    // tar file with one special additional directory, PROOF-INF
@@ -8415,8 +8789,11 @@ Int_t TProof::UploadPackage(const char *pack, EUploadPackageOpt opt)
       mess3 << (UInt_t) opt;
    }
 
-   // loop over all selected nodes
-   TIter next(fUniqueSlaves);
+   // Loop over all slaves with unique fs image, or to a selected
+   // list of workers, if specified
+   if (!workers)
+      workers = fUniqueSlaves;
+   TIter next(workers);
    TSlave *sl = 0;
    while ((sl = (TSlave *) next())) {
       if (!sl->IsValid())
@@ -8814,7 +9191,8 @@ Int_t TProof::Load(const char *macro, Bool_t notOnClient, Bool_t uniqueWorkers,
 }
 
 //______________________________________________________________________________
-Int_t TProof::AddDynamicPath(const char *libpath, Bool_t onClient, TList *wrks)
+Int_t TProof::AddDynamicPath(const char *libpath, Bool_t onClient, TList *wrks,
+   Bool_t doCollect)
 {
    // Add 'libpath' to the lib path search.
    // Multiple paths can be specified at once separating them with a comma or
@@ -8841,17 +9219,22 @@ Int_t TProof::AddDynamicPath(const char *libpath, Bool_t onClient, TList *wrks)
       m << TString("-");
 
    // Forward the request
-   if (wrks)
+   if (wrks) {
       Broadcast(m, wrks);
-   else
+      if (doCollect)
+         Collect(wrks, fCollectTimeout);
+   }
+   else {
       Broadcast(m);
-   Collect(kActive, fCollectTimeout);
+      Collect(kActive, fCollectTimeout);
+   }
 
    return 0;
 }
 
 //______________________________________________________________________________
-Int_t TProof::AddIncludePath(const char *incpath, Bool_t onClient, TList *wrks)
+Int_t TProof::AddIncludePath(const char *incpath, Bool_t onClient, TList *wrks,
+   Bool_t doCollect)
 {
    // Add 'incpath' to the inc path search.
    // Multiple paths can be specified at once separating them with a comma or
@@ -8878,11 +9261,15 @@ Int_t TProof::AddIncludePath(const char *incpath, Bool_t onClient, TList *wrks)
       m << TString("-");
 
    // Forward the request
-   if (wrks)
+   if (wrks) {
       Broadcast(m, wrks);
-   else
+      if (doCollect)
+         Collect(wrks, fCollectTimeout);
+   }
+   else {
       Broadcast(m);
-   Collect(kActive, fCollectTimeout);
+      Collect(kActive, fCollectTimeout);
+   }
 
    return 0;
 }
@@ -11003,6 +11390,32 @@ Bool_t TProof::RequestStagingDataSet(const char *dataset)
 }
 
 //______________________________________________________________________________
+Bool_t TProof::CancelStagingDataSet(const char *dataset)
+{
+   // Cancels a dataset staging request. Returns kTRUE on success, kFALSE on
+   // failure. Dataset not found equals to a failure.
+
+   if (fProtocol < 36) {
+      Error("CancelStagingDataSet",
+         "functionality not supported by the server");
+      return kFALSE;
+   }
+
+   TMessage mess(kPROOF_DATASETS);
+   mess << Int_t(kCancelStaging);
+   mess << TString(dataset);
+   Broadcast(mess);
+
+   Collect();
+   if (fStatus != 0) {
+      Error("CancelStagingDataSet", "cancel staging request was unsuccessful");
+      return kFALSE;
+   }
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
 TFileCollection *TProof::GetStagingStatusDataSet(const char *dataset)
 {
    // Obtains a TFileCollection showing the staging status of the specified
@@ -11760,8 +12173,16 @@ void TProof::SaveWorkerInfo()
 
    // Do we need to register an additional line for another log?
    TString addlogext;
+   TString addLogTag;
    if (gSystem->Getenv("PROOF_ADDITIONALLOG")) {
       addlogext = gSystem->Getenv("PROOF_ADDITIONALLOG");
+      TPMERegexp reLogTag("^__(.*)__\\.log");  // $
+      if (reLogTag.Match(addlogext) == 2) {
+         addLogTag = reLogTag[1];
+      }
+      else {
+         addLogTag = "+++";
+      }
       if (gDebug > 0)
          Info("SaveWorkerInfo", "request for additional line with ext: '%s'",  addlogext.Data());
    }
@@ -11784,9 +12205,9 @@ void TProof::SaveWorkerInfo()
                    wrk->GetOrdinal(), logfile.Data());
       // Additional line, if required
       if (addlogext.Length() > 0) {
-         fprintf(fwrk,"%s@%s:%d %d %s %s.%s\n",
+         fprintf(fwrk,"%s@%s:%d %d %s(%s) %s.%s\n",
                      wrk->GetUser(), wrk->GetName(), wrk->GetPort(), status,
-                     wrk->GetOrdinal(), logfile.Data(), addlogext.Data());
+                     wrk->GetOrdinal(), addLogTag.Data(), logfile.Data(), addlogext.Data());
       }
 
    }
@@ -11817,6 +12238,12 @@ void TProof::SaveWorkerInfo()
       else continue;  // invalid (should not happen)
       fprintf(fwrk, "%s 2 %s %s.log\n",
               sli->GetName(), sli->GetOrdinal(), logfile.Data());
+      // Additional line, if required
+      if (addlogext.Length() > 0) {
+         fprintf(fwrk, "%s 2 %s(%s) %s.%s\n",
+                 sli->GetName(), sli->GetOrdinal(), addLogTag.Data(),
+                 logfile.Data(), addlogext.Data());
+      }
    }
 
    // Close file
diff --git a/proof/proof/src/TProofLite.cxx b/proof/proof/src/TProofLite.cxx
index 58f0f2d..aaadd86 100644
--- a/proof/proof/src/TProofLite.cxx
+++ b/proof/proof/src/TProofLite.cxx
@@ -279,6 +279,9 @@ Int_t TProofLite::Init(const char *, const char *conffile,
    fCurrentMonitor   = 0;
    fServSock         = 0;
 
+   fTerminatedSlaveInfos = new TList;
+   fTerminatedSlaveInfos->SetOwner(kTRUE);
+
    // Control how to start the workers; copy-on-write (fork) is *very*
    // experimental and available on Unix only.
    fForkStartup      = kFALSE;
diff --git a/proof/proof/src/TProofLog.cxx b/proof/proof/src/TProofLog.cxx
index e097351..5ad8eba 100644
--- a/proof/proof/src/TProofLog.cxx
+++ b/proof/proof/src/TProofLog.cxx
@@ -107,9 +107,9 @@ Int_t TProofLog::Retrieve(const char *ord, TProofLog::ERetrieveOpt opt,
          } else {
             nd++;
          }
-         Int_t frac = (nd + nb) / nel * 100;
-         msg.Form("Retrieving logs: %d ok, %d not ok (%d %% processed) \r", nd, nb, frac);
-         Prt(msg.Data());
+         Float_t frac = ((Float_t)nd + (Float_t)nb) * 100. / (Float_t)nel;
+         msg.Form("Retrieving logs: %d ok, %d not ok (%.0f%% processed)\r", nd, nb, frac);
+         Prt(msg.Data(), kFALSE);
       }
    }
    Prt("\n");
@@ -177,7 +177,7 @@ void TProofLog::Print(Option_t *opt) const
 }
 
 //________________________________________________________________________
-void TProofLog::Prt(const char *what)
+void TProofLog::Prt(const char *what, Bool_t newline)
 {
    // Special printing procedure
 
@@ -187,7 +187,8 @@ void TProofLog::Prt(const char *what)
          Emit("Prt(const char*)", what);
       } else {
          FILE *where = (fFILE) ? (FILE *)fFILE : stderr;
-         fprintf(where, "%s\n", what);
+         fputs(what, where);
+         if (newline) fputc('\n', where);
       }
    }
 }
@@ -375,29 +376,43 @@ Int_t TProofLogElem::Retrieve(TProofLog::ERetrieveOpt opt, const char *pattern)
 
    // Make sure we have a reference manager
    if (!fLogger->fMgr || !fLogger->fMgr->IsValid()) {
-      Warning("Retrieve","No reference manager: corruption?");
+      Warning("Retrieve", "No reference manager: corruption?");
       return -1;
    }
 
+   // Print some info on the file
+   if (gDebug >= 2) {
+      Info("Retrieve", "Retrieving from ordinal %s file %s with pattern %s",
+         GetName(), GetTitle(), (pattern ? pattern : "(no pattern)"));
+   }
+
    // Determine offsets
    if (opt == TProofLog::kAll) {
       // Re-read everything
       fFrom = 0;
       fTo = -1;
+      if (gDebug >= 1)
+         Info("Retrieve", "Retrieving the whole file");
    } else if (opt == TProofLog::kLeading) {
       // Read leading part
       fFrom = 0;
       fTo = fgMaxTransferSize;
+      if (gDebug >= 1)
+         Info("Retrieve", "Retrieving the leading %lld lines of file", fTo);
    } else if (opt == TProofLog::kGrep) {
       // Retrieve lines containing 'pattern', which must be defined
       if (!pattern || strlen(pattern) <= 0) {
          Error("Retrieve", "option 'Grep' requires a pattern");
          return -1;
       }
+      if (gDebug >= 1)
+         Info("Retrieve", "Retrieving only lines filtered with %s", pattern);
    } else {
       // Read trailing part
       fFrom = -fgMaxTransferSize;
       fTo = -1;
+      if (gDebug >= 1)
+         Info("Retrieve", "Retrieving the last %lld lines of file", -fFrom);
    }
 
    // Reset the macro
@@ -410,10 +425,21 @@ Int_t TProofLogElem::Retrieve(TProofLog::ERetrieveOpt opt, const char *pattern)
    // Readout the buffer
    TObjString *os = 0;
    if (fLogger->fMgr) {
-      if (opt == TProofLog::kGrep)
-         os = fLogger->fMgr->ReadBuffer(GetTitle(), pattern);
+      TString fileName = GetTitle();
+      if (fileName.Contains("__igprof.pp__")) {
+         // File is an IgProf log. Override all patterns and preprocess it
+         if (gDebug >= 1)
+            Info("Retrieve", "Retrieving analyzed IgProf performance profile");
+         TString analyzeAndFilter = \
+           "|( T=`mktemp` && cat > \"$T\" ; igprof-analyse -d -g \"$T\" ; rm -f \"$T\" )";
+         if (pattern && (*pattern == '|'))
+            analyzeAndFilter.Append(pattern);
+         os = fLogger->fMgr->ReadBuffer(fileName.Data(), analyzeAndFilter.Data());
+      }
+      else if (opt == TProofLog::kGrep)
+         os = fLogger->fMgr->ReadBuffer(fileName.Data(), pattern);
       else
-         os = fLogger->fMgr->ReadBuffer(GetTitle(), fFrom, len);
+         os = fLogger->fMgr->ReadBuffer(fileName.Data(), fFrom, len);
    }
    if (os) {
       // Loop over lines
diff --git a/proof/proof/src/TProofServ.cxx b/proof/proof/src/TProofServ.cxx
index e4230e8..6e1b59e 100644
--- a/proof/proof/src/TProofServ.cxx
+++ b/proof/proof/src/TProofServ.cxx
@@ -833,7 +833,7 @@ Int_t TProofServ::CreateServer()
 
    if (!fLogFile) {
       RedirectOutput();
-      // If for some reason we failed setting a redirection fole for the logs
+      // If for some reason we failed setting a redirection file for the logs
       // we cannot continue
       if (!fLogFile || (fLogFileDes = fileno(fLogFile)) < 0) {
          LogToMaster();
@@ -1476,7 +1476,7 @@ Int_t TProofServ::HandleSocketInput(TMessage *mess, Bool_t all)
 {
    // Process input coming from the client or from the master server.
    // If 'all' is kFALSE, process only those messages that can be handled
-   // during qurey processing.
+   // during query processing.
    // Returns -1 if the message could not be processed, <-1 if something went
    // wrong. Returns 1 if the action may have changed the parallel state.
    // Returns 2 if the message has to be enqueued.
@@ -1651,6 +1651,23 @@ Int_t TProofServ::HandleSocketInput(TMessage *mess, Bool_t all)
          }
          break;
 
+      case kPROOF_SENDOUTPUT:
+         {
+            PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_SENDOUTPUT",
+                                 "worker was asked to send output to master");
+            Int_t sorc = 0;
+            if (SendResults(fSocket, fPlayer->GetOutputList()) != 0) {
+               Error("HandleSocketInput:kPROOF_SENDOUTPUT", "problems sending output list");
+               sorc = 1;
+            }
+            // Signal the master that we are idle
+            fSocket->Send(kPROOF_SETIDLE);
+            SetIdle(kTRUE);
+            DeletePlayer();
+            SendLogFile(sorc);
+         }
+         break;
+
       case kPROOF_QUERYLIST:
          {
             HandleQueryList(mess);
@@ -1841,17 +1858,17 @@ Int_t TProofServ::HandleSocketInput(TMessage *mess, Bool_t all)
          } else {
             TProofServLogHandlerGuard hg(fLogFile, fSocket, "", fRealTimeLog);
             PDB(kGlobal, 1) Info("HandleSocketInput:kPROOF_CACHE","enter");
-            Int_t status = HandleCache(mess, pslb);
+            Int_t hcrc = HandleCache(mess, pslb);
             // Notify
-            SendLogFile(status);
+            SendLogFile(hcrc);
          }
          break;
 
       case kPROOF_WORKERLISTS:
-         {  Int_t xrc = -1;
+         {  Int_t wlrc = -1;
             if (all) {
                if (IsMaster())
-                  xrc = HandleWorkerLists(mess);
+                  wlrc = HandleWorkerLists(mess);
                else
                   Warning("HandleSocketInput:kPROOF_WORKERLISTS",
                         "Action meaning-less on worker nodes: protocol error?");
@@ -1859,7 +1876,7 @@ Int_t TProofServ::HandleSocketInput(TMessage *mess, Bool_t all)
                rc = -1;
             }
             // Notify
-            SendLogFile(xrc);
+            SendLogFile(wlrc);
          }
          break;
 
@@ -2016,13 +2033,13 @@ Int_t TProofServ::HandleSocketInput(TMessage *mess, Bool_t all)
          break;
 
       case kPROOF_DATASETS:
-         {  Int_t xrc = -1;
+         {  Int_t dsrc = -1;
             if (fProtocol > 16) {
-               xrc = HandleDataSets(mess, pslb);
+               dsrc = HandleDataSets(mess, pslb);
             } else {
                Error("HandleSocketInput", "old client: no or incompatible dataset support");
             }
-            SendLogFile(xrc);
+            SendLogFile(dsrc);
          }
          break;
 
@@ -2125,6 +2142,75 @@ Int_t TProofServ::HandleSocketInput(TMessage *mess, Bool_t all)
          }
          break;
 
+      case kPROOF_ECHO:
+         {  // Echo request: an object has been sent along. If the object is a
+            // string, it is simply echoed back to the client from the master
+            // and each worker. Elsewhere, the output of TObject::Print() is
+            // sent. Received object is disposed after usage.
+
+            TObject *obj = mess->ReadObject(0x0);  // class type ignored
+
+            if (IsMaster()) {
+               // We are on master
+               // dbTODO: forward on dynamic startup when wrks are up
+               if (IsParallel() && fProof && !fProof->UseDynamicStartup()) {
+                  fProof->Echo(obj);  // forward to lower layer
+               }
+            }
+
+            TMessage rmsg(kPROOF_MESSAGE);
+            TString smsg;
+
+            if (obj->InheritsFrom(TObjString::Class())) {
+               // It's a string: echo it
+               smsg.Form("Echo response from %s:%s: %s",
+                  gSystem->HostName(), GetOrdinal(),
+                  ((TObjString *)obj)->String().Data());
+            }
+            else {
+               // Not a string: collect Print() output and send it
+
+               // Output to tempfile
+               TString tmpfn = "echo-out-";
+               FILE *tf = gSystem->TempFileName(tmpfn, fDataDir);
+               if (!tf || (gSystem->RedirectOutput(tmpfn.Data()) == -1)) {
+                  Error("HandleSocketInput", "Can't redirect output");
+                  if (tf) {
+                     fclose(tf);
+                     gSystem->Unlink(tmpfn);
+                  }
+                  rc = -1;
+                  delete obj;
+                  break;
+               }
+               //cout << obj->ClassName() << endl;
+               obj->Print();
+               gSystem->RedirectOutput(0x0);  // restore
+               fclose(tf);
+
+               // Read file back and send it via message
+               smsg.Form("*** Echo response from %s:%s ***\n",
+                  gSystem->HostName(), GetOrdinal());
+               TMacro *fr = new TMacro();
+               fr->ReadFile(tmpfn);
+               TIter nextLine(fr->GetListOfLines());
+               TObjString *line;
+               while (( line = (TObjString *)nextLine() )) {
+                  smsg.Append( line->String() );
+               }
+
+               // Close the reader (TMacro) and remove file
+               delete fr;
+               gSystem->Unlink(tmpfn);
+            }
+
+            // Send message and dispose object
+            rmsg << smsg;
+            GetSocket()->Send(rmsg);
+            delete obj;
+         }
+         break;
+
       default:
          Error("HandleSocketInput", "unknown command %d", what);
          rc = -2;
@@ -2693,7 +2779,11 @@ void TProofServ::SendParallel(Bool_t async)
 
    Int_t nparallel = 0;
    if (IsMaster()) {
+      PDB(kGlobal, 2)
+         Info("SendParallel", "Will invoke AskParallel()");
       fProof->AskParallel();
+      PDB(kGlobal, 2)
+         Info("SendParallel", "Will invoke GetParallel()");
       nparallel = fProof->GetParallel();
    } else {
       nparallel = 1;
@@ -3225,11 +3315,13 @@ Int_t TProofServ::SetupCommon()
       // Dataset manager for staging requests
       TString dsReqCfg = gEnv->GetValue("Proof.DataSetStagingRequests", "");
       if (!dsReqCfg.IsNull()) {
-         TPMERegexp reReqDir("(^| )dir:([^ ]+)( |$)");
+         TPMERegexp reReqDir("(^| )(dir:)?([^ ]+)( |$)");
 
-         if (reReqDir.Match(dsReqCfg) == 4) {
+         if (reReqDir.Match(dsReqCfg) == 5) {
+            TString dsDirFmt;
+            dsDirFmt.Form("dir:%s perms:open", reReqDir[3].Data());
             fDataSetStgRepo = new TDataSetManagerFile("_stage_", "_stage_",
-              Form("dir:%s perms:open", reReqDir[2].Data()));
+               dsDirFmt);
             if (fDataSetStgRepo &&
                fDataSetStgRepo->TestBit(TObject::kInvalidObject)) {
                Warning("SetupCommon",
@@ -3238,7 +3330,7 @@ Int_t TProofServ::SetupCommon()
             }
          } else {
             Warning("SetupCommon",
-              "specify, with dir:<path>, a valid path for staging requests");
+              "specify, with [dir:]<path>, a valid path for staging requests");
          }
       } else if (gProofDebugLevel > 0) {
          Warning("SetupCommon", "no repository for staging requests available");
@@ -4068,62 +4160,104 @@ void TProofServ::HandleProcess(TMessage *mess, TString *slb)
       SafeDelete(enl);
       SafeDelete(evl);
 
-      // Check if we are in merging mode (i.e. parameter PROOF_UseMergers exists)
-      Bool_t isInMergingMode = kFALSE;
-      if (!(TestBit(TProofServ::kHighMemory))) {
-         Int_t nm = 0;
-         if (TProof::GetParameter(input, "PROOF_UseMergers", nm) == 0) {
-            isInMergingMode = (nm >= 0) ? kTRUE : kFALSE;
-         }
-      }
-      PDB(kGlobal, 2) Info("HandleProcess", "merging mode check: %d", isInMergingMode);
+      Bool_t outok = (fPlayer->GetExitStatus() != TVirtualProofPlayer::kAborted &&
+                        fPlayer->GetOutputList()) ? kTRUE : kFALSE;
+      if (outok) {
+         // Check if in controlled output sending mode
+         Int_t cso = gEnv->GetValue("Proof.ControlSendOutput", 1);
+         if (TProof::GetParameter(input, "PROOF_ControlSendOutput", cso) != 0)
+            cso = gEnv->GetValue("Proof.ControlSendOutput", 1);
+         if (cso > 0) {
+
+            // Control output sending mode: wait for the master to ask for the objects.
+            // Allows controls of memory usage on the master.
+            TMessage msg(kPROOF_SENDOUTPUT);
+            fSocket->Send(msg);
 
-      if (!IsMaster() && isInMergingMode &&
-          fPlayer->GetExitStatus() != TVirtualProofPlayer::kAborted && fPlayer->GetOutputList()) {
-         // Worker in merging mode.
-         //----------------------------
-         // First, it reports only the size of its output to the master
-         // + port on which it can possibly accept outputs from other workers if it becomes a merger
-         // Master will later tell it where it should send the output (either to the master or to some merger)
-         // or if it should become a merger
+            // Set idle
+            SetIdle(kTRUE);
 
-         TMessage msg_osize(kPROOF_SUBMERGER);
-         msg_osize << Int_t(TProof::kOutputSize);
-         msg_osize << fPlayer->GetOutputList()->GetEntries();
+            // Do not cleanup the player yet: it will be used in sending output activities
+            deleteplayer = kFALSE;
 
-         fMergingSocket = new TServerSocket(0);
-         Int_t merge_port = 0;
-         if (fMergingSocket) {
-            PDB(kGlobal, 2)
-               Info("HandleProcess", "possible port for merging connections: %d",
-                                     fMergingSocket->GetLocalPort());
-            merge_port = fMergingSocket->GetLocalPort();
-         }
-         msg_osize << merge_port;
-         fSocket->Send(msg_osize);
+            PDB(kGlobal, 1)
+               Info("HandleProcess", "controlled mode: worker %s has finished,"
+                                     " sizes sent to master", fOrdinal.Data());
+         } else {
 
-         // Set idle
-         SetIdle(kTRUE);
 
-         // Do not cleanup the player yet: it will be used in sub-merging activities
-         deleteplayer = kFALSE;
+            // Check if we are in merging mode (i.e. parameter PROOF_UseMergers exists)
+            Bool_t isInMergingMode = kFALSE;
+            if (!(TestBit(TProofServ::kHighMemory))) {
+               Int_t nm = 0;
+               if (TProof::GetParameter(input, "PROOF_UseMergers", nm) == 0) {
+                  isInMergingMode = (nm >= 0) ? kTRUE : kFALSE;
+               }
+            }
+            PDB(kGlobal, 2) Info("HandleProcess", "merging mode check: %d", isInMergingMode);
+
+            if (!IsMaster() && isInMergingMode) {
+               // Worker in merging mode.
+               //----------------------------
+               // First, it reports only the size of its output to the master
+               // + port on which it can possibly accept outputs from other workers if it becomes a merger
+               // Master will later tell it where it should send the output (either to the master or to some merger)
+               // or if it should become a merger
+
+               TMessage msg_osize(kPROOF_SUBMERGER);
+               msg_osize << Int_t(TProof::kOutputSize);
+               msg_osize << fPlayer->GetOutputList()->GetEntries();
+
+               fMergingSocket = new TServerSocket(0);
+               Int_t merge_port = 0;
+               if (fMergingSocket) {
+                  PDB(kGlobal, 2)
+                     Info("HandleProcess", "possible port for merging connections: %d",
+                                           fMergingSocket->GetLocalPort());
+                  merge_port = fMergingSocket->GetLocalPort();
+               }
+               msg_osize << merge_port;
+               fSocket->Send(msg_osize);
+
+               // Set idle
+               SetIdle(kTRUE);
+
+               // Do not cleanup the player yet: it will be used in sub-merging activities
+               deleteplayer = kFALSE;
+
+               PDB(kSubmerger, 2) Info("HandleProcess", "worker %s has finished", fOrdinal.Data());
+
+            } else {
+               // Sub-master OR worker not in merging mode
+               // ---------------------------------------------
+               PDB(kGlobal, 2)  Info("HandleProcess", "sending result directly to master");
+               if (SendResults(fSocket, fPlayer->GetOutputList()) != 0)
+                  Warning("HandleProcess","problems sending output list");
+
+               // Masters reset the mergers, if any
+               if (IsMaster()) fProof->ResetMergers();
+
+               // Signal the master that we are idle
+               fSocket->Send(kPROOF_SETIDLE);
+
+               // Set idle
+               SetIdle(kTRUE);
+
+               // Notify the user
+               SendLogFile();
+            }
+
 
-         PDB(kSubmerger, 2) Info("HandleProcess", "worker %s has finished", fOrdinal.Data());
 
-      } else {
-         // Sub-master OR worker not in merging mode
-         // ---------------------------------------------
-         if (fPlayer->GetExitStatus() != TVirtualProofPlayer::kAborted && fPlayer->GetOutputList()) {
-            PDB(kGlobal, 2)  Info("HandleProcess", "sending result directly to master");
-            if (SendResults(fSocket, fPlayer->GetOutputList()) != 0)
-               Warning("HandleProcess","problems sending output list");
-         } else {
-            if (fPlayer->GetExitStatus() != TVirtualProofPlayer::kAborted)
-               Warning("HandleProcess","the output list is empty!");
-            if (SendResults(fSocket) != 0)
-               Warning("HandleProcess", "problems sending output list");
          }
 
+      } else {
+         // No output list
+         if (fPlayer->GetExitStatus() != TVirtualProofPlayer::kAborted)
+            Warning("HandleProcess","the output list is empty!");
+         if (SendResults(fSocket) != 0)
+            Warning("HandleProcess", "problems sending output list");
+
          // Masters reset the mergers, if any
          if (IsMaster()) fProof->ResetMergers();
 
@@ -6782,23 +6916,19 @@ Int_t TProofServ::HandleDataSets(TMessage *mess, TString *slb)
 
       case TProof::kStagingStatus:
          {
-            (*mess) >> uri;  // TString
-
             if (!fDataSetStgRepo) {
                Error("HandleDataSets",
                   "no dataset staging request repository available");
                return -1;
             }
 
-            // TODO what is slb?
-            //if (slb) slb->Form("%d %s %s", type, uri.Data(), opt.Data());
+            (*mess) >> uri;  // TString
 
             // Transform URI in a valid dataset name
-            TString validUri = uri;
-            while (reInvalid.Substitute(validUri, "_")) {}
+            while (reInvalid.Substitute(uri, "_")) {}
 
             // Get the list
-            TFileCollection *fc = fDataSetStgRepo->GetDataSet(validUri.Data());
+            TFileCollection *fc = fDataSetStgRepo->GetDataSet(uri.Data());
             if (fc) {
                fSocket->SendObject(fc, kMESS_OK);
                delete fc;
@@ -6807,12 +6937,32 @@ Int_t TProofServ::HandleDataSets(TMessage *mess, TString *slb)
             else {
                // No such dataset: not an error, but don't send message
                Info("HandleDataSets", "no pending staging request for %s",
-                  validUri.Data());
+                  uri.Data());
                return 0;
             }
          }
          break;
 
+      case TProof::kCancelStaging:
+         {
+            if (!fDataSetStgRepo) {
+               Error("HandleDataSets",
+                  "no dataset staging request repository available");
+               return -1;
+            }
+
+            (*mess) >> uri;
+
+            // Transform URI in a valid dataset name
+            while (reInvalid.Substitute(uri, "_")) {}
+
+            if (!fDataSetStgRepo->RemoveDataSet(uri.Data()))
+               return -1;  // failure
+
+            return 0;  // success
+         }
+         break;
+
       case TProof::kShowDataSets:
          {
             (*mess) >> uri >> opt;
diff --git a/proof/proofbench/inc/TProofPerfAnalysis.h b/proof/proofbench/inc/TProofPerfAnalysis.h
index f633596..b6d6f3e 100644
--- a/proof/proofbench/inc/TProofPerfAnalysis.h
+++ b/proof/proofbench/inc/TProofPerfAnalysis.h
@@ -38,7 +38,11 @@ class TTree;
 class TProofPerfAnalysis : public TNamed {
 
 public:              // public because of Sun CC bug
+   class TFileInfo;
+   class TPackInfo;
+   class TWrkEntry;
    class TWrkInfo;
+   class TWrkInfoFile;
 
 private:
    TFile  *fFile;                // The open performance file
@@ -46,6 +50,7 @@ private:
    TString fTreeName;            // The name of the performance tree
    TTree  *fTree;                // The performance tree
    TSortedList fWrksInfo;        // Sorted list of workers info
+   TSortedList fFilesInfo;       // Sorted list of files info
    Float_t fInitTime;            // End of initialization time for this query
    Float_t fMergeTime;           // Begin of merging time for this query
    Float_t fMaxTime;             // Max time for this query (slowest worker)
@@ -54,15 +59,26 @@ private:
    Double_t fEvtRateMax;         // Max event processing rate per packet
    Double_t fMBRateMax;          // Max MB processing rate per packet
    Double_t fLatencyMax;         // Max retrieval latency per packet
+   TH1F *fEvtRate;               // Event processing rate vs query time
+   TH1F *fEvtRateRun;            // Event processing rate running avg vs query time
+   TH1F *fMBRate;                // Byte processing rate vs query time
+   TH1F *fMBRateRun;             // Byte processing rate running avg vs query time
+   Double_t fEvtRateAvgMax;      // Max running event processing rate
+   Double_t fMBRateAvgMax;       // Max running MB processing rate
+   Double_t fEvtRateAvg;         // Average event processing rate
+   Double_t fMBRateAvg;          // Average MB processing rate
 
-   static Int_t fgDebug;         // Verbosity level
+   Int_t fDebug;                 // Local verbosity level
+
+   static Bool_t fgDebug;         // Global verbosity on/off
 
    Int_t CompareOrd(const char *ord1, const char *ord2);
    void  FillFileDist(TH1F *hf, TH1F *hb, TH2F *hx, Bool_t wdet = kFALSE);
    void  FillFileDistOneSrv(TH1F *hx, Bool_t wdet = kFALSE);
    void  FillWrkInfo(Bool_t force = kFALSE);
+   void  FillFileInfo(Bool_t force = kFALSE);
    TString GetCanvasTitle(const char *t);
-   void  GetFileInfo(TList *wl, TList *sl);
+   void  GetWrkFileList(TList *wl, TList *sl);
    void  LoadTree(TDirectory *dir);
 
 public:
@@ -81,8 +97,16 @@ public:
    void  WorkerActivity();                     // Analyse the worker activity
    void  PrintWrkInfo(Int_t showlast = 10);    // Print workers info
    void  PrintWrkInfo(const char *wrk);        // Print worker info by name
-   
+
+   void  PrintFileInfo(Int_t showlast = 10, const char *opt = "", const char *out = 0);   // Print file info
+   void  PrintFileInfo(const char *fn, const char *opt = "P", const char *out = 0);        // Print file info by name
+   void  FileProcPlot(const char *fn, const char *out = 0); // Plot info about file processing
+   void  FileRatePlot(const char *fns = 0);    // Plot info about file processing rates
+
+   void  Summary(Option_t *opt = "", const char *out = "");
+  
    void  SetDebug(Int_t d = 0);   // Setter for the verbosity level
+   static void  SetgDebug(Bool_t on = kTRUE);   // Overall verbosity level
 
    ClassDef(TProofPerfAnalysis, 0)   // Set of tools to analyse the performance tree
 };
diff --git a/proof/proofbench/src/TProofPerfAnalysis.cxx b/proof/proofbench/src/TProofPerfAnalysis.cxx
index daaa11e..c6f2d51 100644
--- a/proof/proofbench/src/TProofPerfAnalysis.cxx
+++ b/proof/proofbench/src/TProofPerfAnalysis.cxx
@@ -33,9 +33,10 @@
 #include "TStyle.h"
 #include "TSystem.h"
 #include "TTree.h"
+#include "TMath.h"
 
 //
-// Auxilliary internal class
+// Auxilliary internal classes
 //_______________________________________________________________________
 class TProofPerfAnalysis::TWrkInfo : public TNamed {
 public:
@@ -92,14 +93,132 @@ public:
                                           return 1; }
 };
 
-Int_t TProofPerfAnalysis::fgDebug = 0;
+
+class TProofPerfAnalysis::TPackInfo : public TNamed {
+public:
+   TPackInfo(const char *ord, const char *host) :  TNamed(ord, host), fStart(0), fStop(-1), fSize(0), fMBRate(0.) { }
+   TPackInfo(const char *ord, const char *host, Float_t start, Float_t stop, Long64_t sz, Double_t mbr)
+            :  TNamed(ord, host), fStart(start), fStop(stop), fSize(sz), fMBRate(mbr) { }
+   Float_t   fStart;            // When the packet has been assigned
+   Float_t   fStop;             // When the packet has been finished
+   Long64_t  fSize;             // Packet size
+   Double_t  fMBRate;           // Processing rate MB/s
+   void Print(Option_t *opt= "") const {
+      if (!strcmp(opt, "S")) {
+         Printf("       \t%10lld evts, \t%12.2f MB/s, \t%12.3f -> %12.3f s", fSize, fMBRate, fStart, fStop);
+      } else {
+         Printf("   %s:\t%s  \t%10lld evts, \t%12.2f MB/s, \t%12.3f -> %12.3f s", GetTitle(), GetName(), fSize, fMBRate, fStart, fStop);
+      }
+   }
+};
+
+class TProofPerfAnalysis::TWrkInfoFile : public TNamed {
+public:
+   TWrkInfoFile(const char *ord, const char *name) :  TNamed(ord, name) { }
+   ~TWrkInfoFile() {fPackets.SetOwner(kFALSE); fPackets.Clear();}
+   TList     fPackets;          // Packest from this file processed by this worker
+   void Print(Option_t *opt= "") const {
+      if (!strcmp(opt, "R")) {
+         Printf(" Worker: %s,\tpacket(s): %d", GetName(), fPackets.GetSize());
+      } else {
+         Printf(" Worker: %s,\t%d packet(s) from file: %s", GetName(), fPackets.GetSize(), GetTitle());
+      }
+      TIter nxp(&fPackets);
+      TObject *o = 0;
+      while ((o = nxp())) { o->Print("S"); }
+   }
+};
+
+class TProofPerfAnalysis::TWrkEntry : public TObject {
+public:
+   TWrkEntry(Double_t xx, Double_t er, Double_t mbr, Double_t pt) : fXx(xx), fEvtRate(er), fMBRate(mbr), fProcTime(pt) { }
+   Double_t fXx;             // Bin center
+   Double_t fEvtRate;        // Event processing rate from this worker for this packet
+   Double_t fMBRate;         // I/O processing rate from this worker for this packet
+   Double_t fProcTime;       // Processing time
+   void Print(Option_t * = "") const { Printf("%.4f \t%.3f evt/s \t%.3f MB/s \t%.3f s ", fXx, fEvtRate, fMBRate, fProcTime); }
+};
+
+//_______________________________________________________________________
+class TProofPerfAnalysis::TFileInfo : public TNamed {
+public:
+   TFileInfo(const char *name, const char *srv) :
+      TNamed(name, srv), fPackets(0), fRPackets(0), fStart(0), fStop(-1),
+      fSizeAvg(0), fSizeMax(-1.), fSizeMin(-1.),
+      fMBRateAvg(0), fMBRateMax(-1.), fMBRateMin(-1.), fSizeP(0),
+      fRateP(0), fRatePRemote(0), fMBRateP(0), fMBRatePRemote(0) { }
+   virtual ~TFileInfo() {SafeDelete(fSizeP);
+                         SafeDelete(fRateP); SafeDelete(fRatePRemote);
+                         SafeDelete(fMBRateP); SafeDelete(fMBRatePRemote);
+                         fPackList.SetOwner(kTRUE); fPackList.Clear();
+                         fWrkList.SetOwner(kTRUE); fWrkList.Clear();
+                         fRWrkList.SetOwner(kTRUE); fRWrkList.Clear();}
+
+   Int_t     fPackets;          // Number of packets from this file
+   Int_t     fRPackets;         // Number of different remote workers processing this file
+
+   TList     fPackList;          // List of packet info
+   TList     fWrkList;          // List of worker names processing this packet
+   TList     fRWrkList;         // List of remote worker names processing this packet
+
+   Float_t   fStart;            // When the first packet has been assigned
+   Float_t   fStop;             // When the last packet has been finished
+
+   Long64_t  fSizeAvg;          // Average Packet size
+   Long64_t  fSizeMax;          // Max packet size
+   Long64_t  fSizeMin;          // Min packet size
+
+   Double_t  fMBRateAvg;        // Average MB rate
+   Double_t  fMBRateMax;        // Max MB rate
+   Double_t  fMBRateMin;        // Min MB rate
+
+   TGraph   *fSizeP;             // Packet size vs packet (all)
+   TGraph   *fRateP;             // Event processing rate vs packet (all)
+   TGraph   *fRatePRemote;       // Event processing rate vs packet (remote workers)
+   TGraph   *fMBRateP;           // Byte processing rate vs packet (all)
+   TGraph   *fMBRatePRemote;     // Byte processing rate vs packet (remote workers)
+
+   void Print(Option_t *opt = "") const {
+      Printf(" +++ TFileInfo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
+      Printf(" +++ Server:         %s", GetTitle());
+      Printf(" +++ File:           %s", GetName());
+      Printf(" +++ Processing interval:  %f -> %f", fStart, fStop);
+      Printf(" +++ Packets:         %d (%d remote)", fPackets, fRPackets);
+      Printf(" +++ Processing wrks: %d (%d remote)", fWrkList.GetSize(), fRWrkList.GetSize());
+      if (!strcmp(opt, "P")) fPackList.Print();
+      if (!strcmp(opt, "WP")) fWrkList.Print("R");
+      if (fPackets > 0) {
+         Printf(" +++ MB rates:       %f MB/s (avg), %f MB/s (min), %f MB/s (max)",
+                fMBRateAvg / fPackets, fMBRateMin, fMBRateMax);
+         Printf(" +++ Sizes:          %lld  (avg), %lld (min), %lld (max)",
+                fSizeAvg / fPackets, fSizeMin, fSizeMax);
+      }
+      Printf(" +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
+   }
+
+   Int_t Compare(const TObject *o) const { TFileInfo *wi = (TFileInfo *)o;
+                                           if (wi) {
+                                             if (fStop < wi->fStop) {
+                                                return -1;
+                                             } else if (fStop == wi->fStop) {
+                                                return 0;
+                                             }
+                                          }
+                                          return 1; }
+};
+
+Bool_t TProofPerfAnalysis::fgDebug = kTRUE;
 //________________________________________________________________________
 TProofPerfAnalysis::TProofPerfAnalysis(const char *perffile,
                                const char *title, const char *treename)
                : TNamed(perffile, title), fTreeName(treename),
                  fInitTime(-1.), fMergeTime(-1.), fMaxTime(-1.),
                  fEvents(0), fPackets(0),
-                 fEvtRateMax(-1.), fMBRateMax(-1.), fLatencyMax(-1.)
+                 fEvtRateMax(-1.), fMBRateMax(-1.), fLatencyMax(-1.),
+                 fEvtRate(0), fEvtRateRun(0), fMBRate(0), fMBRateRun(0),
+                 fEvtRateAvgMax(-1.), fMBRateAvgMax(-1.),
+                 fEvtRateAvg(-1.), fMBRateAvg(0),
+                 fDebug(0)
 {
    // Constructor: open the file and attach to the tree
 
@@ -144,10 +263,14 @@ TProofPerfAnalysis::TProofPerfAnalysis(const char *perffile,
       SafeDelete(fFile);
       return;
    }
-   Printf(" +++ TTree '%s' has %lld entries", fTreeName.Data(), fTree->GetEntries());
+   if (fgDebug)
+      Printf(" +++ TTree '%s' has %lld entries", fTreeName.Data(), fTree->GetEntries());
 
    // Init worker information
    FillWrkInfo();
+
+   // Init file information
+   FillFileInfo();
    
    // Done
    return;
@@ -209,7 +332,7 @@ void TProofPerfAnalysis::LoadTree(TDirectory *dir)
          if (tn.Index(re) != kNPOS) {
             if ((fTree = dynamic_cast<TTree *>(dir->Get(tn)))) {
                fTreeName = tn;
-               Printf(" +++ Found and loaded TTree '%s'", tn.Data());
+               if (fgDebug) Printf(" +++ Found and loaded TTree '%s'", tn.Data());
                return;
             }
          }
@@ -234,7 +357,7 @@ void TProofPerfAnalysis::FileDist(Bool_t writedet)
    // Fill file info
    TList *wrkList = new TList;
    TList *srvList = new TList;
-   GetFileInfo(wrkList, srvList);
+   GetWrkFileList(wrkList, srvList);
    Info("FileDist", "%d workers were active during this query", wrkList->GetSize());
    Info("FileDist", "%d servers were active during this query", srvList->GetSize());
 
@@ -407,7 +530,7 @@ void TProofPerfAnalysis::FileDist(Bool_t writedet)
 }
 
 //________________________________________________________________________
-void TProofPerfAnalysis::GetFileInfo(TList *wl, TList *sl)
+void TProofPerfAnalysis::GetWrkFileList(TList *wl, TList *sl)
 {
    // Fill file info
 
@@ -706,6 +829,64 @@ void TProofPerfAnalysis::PrintWrkInfo(const char *wn)
 }
 
 //________________________________________________________________________
+void TProofPerfAnalysis::PrintFileInfo(Int_t showlast, const char *opt, const char *out)
+{
+   // Print information for all or the slowest showlast workers.
+   // Use showlast < 0 to print all
+   
+   RedirectHandle_t rh;
+   if (out && strlen(out) > 0) gSystem->RedirectOutput(out, "w", &rh);
+
+   // Create the sorted list
+   Int_t k = fFilesInfo.GetSize();
+   TIter nxf(&fFilesInfo);
+   TFileInfo *fi = 0;
+   while ((fi = (TFileInfo *)nxf())) {
+      // Print info about files processed last
+      k--;
+      if (showlast < 0 || k < showlast) fi->Print(opt);
+   }
+
+   if (out && strlen(out) > 0) gSystem->RedirectOutput(0, 0, &rh);
+}
+
+//________________________________________________________________________
+void TProofPerfAnalysis::PrintFileInfo(const char *fn, const char *opt, const char *out)
+{
+   // Print information for file 'fn' (path including directory) or server 'fn'.
+   // Multiple specifications separated by ','
+   // or ' ' are supported, as well as wildcards '*', e.g. 'pippo.root, h4mu*,lxb10*"
+
+   if (!fn || (fn && strlen(fn) <= 0)) {
+      Error("PrintFileInfo", "file path must be defined!");
+      return;
+   }
+   
+   RedirectHandle_t rh;
+   if (out && strlen(out) > 0) gSystem->RedirectOutput(out, "w", &rh);
+
+   // Check exact name
+   TFileInfo *fi = (TFileInfo *) fFilesInfo.FindObject(fn);
+   if (fi) {
+      fi->Print(opt);
+   } else {
+      // Check matching
+      TString fw(fn), f;
+      TIter nxf(&fFilesInfo);
+      while ((fi = (TFileInfo *)nxf())) {
+         TString n(fi->GetName()), s(fi->GetTitle());
+         Ssiz_t from = 0;
+         while (fw.Tokenize(f, from, "[, ]")) {
+            TRegexp re(f, kTRUE);
+            if (n.Index(re) != kNPOS || s.Index(re) != kNPOS) fi->Print(opt);
+         }
+      }
+   }
+
+   if (out && strlen(out) > 0) gSystem->RedirectOutput(0, 0, &rh);
+}
+
+//________________________________________________________________________
 void TProofPerfAnalysis::FillWrkInfo(Bool_t force)
 {
    // Fill basic worker info; if 'force' rescan the TTree even already done
@@ -729,14 +910,79 @@ void TProofPerfAnalysis::FillWrkInfo(Bool_t force)
    TPerfEvent* pep = &pe;
    fTree->SetBranchAddress("PerfEvents",&pep);
    Long64_t entries = fTree->GetEntries();
+
+   // First determine binning for global rates
+   Int_t nraw = entries * 2, jj = 0, kk = 0;
+   Double_t *xraw = new Double_t[nraw];
+   for (Long64_t k=0; k<entries; k++) {
+      fTree->GetEntry(k);
+      // Analyse only packets
+      if (pe.fType == TVirtualPerfStats::kPacket) {
+         Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         Float_t start = stop - pe.fProcTime;
+         // Bins
+         xraw[jj++] = start;
+         xraw[jj++] = stop;
+      }
+   }
+   Int_t nbins = jj;
+   Int_t *jidx = new Int_t[nbins];
+   memset(jidx, 0, nbins * sizeof(Int_t));
+   TMath::Sort(nbins, xraw, jidx, kFALSE);
+   Double_t *xbins = new Double_t[nbins];
+   jj = 0;
+   for (kk = 0; kk < nbins; kk++) {
+      Double_t xtmp = xraw[jidx[kk]];
+      if (jj == 0 || xtmp > xbins[jj - 1] + .5) {
+         xbins[jj] = xtmp;
+         jj++;
+      }
+   }
+   nbins = jj;
+   delete [] xraw;
+   delete [] jidx;
+
+   // Create the global histograms
+   Int_t nbin = nbins - 1;
+   TObject *o = 0;
+   if ((o = gDirectory->FindObject("gEvtRate"))) delete o;
+   fEvtRate = new TH1F("gEvtRate", "Total event processing rate (evt/s)", nbin, xbins);
+   fEvtRate->SetMinimum(0.);
+   fEvtRate->SetStats(kFALSE);
+   fEvtRate->SetFillColor(kCyan-8);
+   fEvtRate->GetXaxis()->SetTitle("Query Processing Time (s)");
+   if ((o = gDirectory->FindObject("gEvtRateAvg"))) delete o;
+   fEvtRateRun = new TH1F("gEvtRateAvg", "Event processing rate running average (evt/s)", nbin, xbins);
+   fEvtRateRun->SetMinimum(0.);
+   fEvtRateRun->SetStats(kFALSE);
+   fEvtRateRun->SetLineColor(kBlue);
+   fEvtRateRun->GetXaxis()->SetTitle("Query Processing Time (s)");
+   if ((o = gDirectory->FindObject("gMBRate"))) delete o;
+   fMBRate = new TH1F("gMBRate", "Total processing rate (MB/s)", nbin, xbins);
+   fMBRate->SetMinimum(0.);
+   fMBRate->SetStats(kFALSE);
+   fMBRate->SetFillColor(kCyan-8);
+   fMBRate->GetXaxis()->SetTitle("Query Processing Time (s)");
+   if ((o = gDirectory->FindObject("gMBRateAvg"))) delete o;
+   fMBRateRun = new TH1F("gMBRateAvg", "Processing rate running average (MB/s)", nbin, xbins);
+   fMBRateRun->SetMinimum(0.);
+   fMBRateRun->SetStats(kFALSE);
+   fMBRateRun->SetLineColor(kBlue);
+   fMBRateRun->GetXaxis()->SetTitle("Query Processing Time (s)");
+   // Not needed any longer
+   delete [] xbins;
+
+   THashList gBins;
+   TList *gwl = 0, *gbl = 0;
+
+   // Extract the worker info now
    TWrkInfo *wi = 0;
    for (Long64_t k=0; k<entries; k++) {
       fTree->GetEntry(k);
       // Analyse only packets
       if (pe.fType == TVirtualPerfStats::kPacket) {
          // Find out the worker instance
-         wi = (TWrkInfo *) wl->FindObject(pe.fSlave.Data());
-         if (!wi) {
+         if (!(wi = (TWrkInfo *) wl->FindObject(pe.fSlave.Data()))) {
             wi = new TWrkInfo(pe.fSlave.Data(), pe.fSlaveName.Data());
             wl->Add(wi);
             wi->fRateT = new TGraph(100);
@@ -746,20 +992,22 @@ void TProofPerfAnalysis::FillWrkInfo(Bool_t force)
             wi->fLatencyT = new TGraph(100);
          }
          // Add Info now
+         Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         Float_t start = stop - pe.fProcTime;
          if (wi->fPackets <= 0) {
-            wi->fStart = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec() - pe.fProcTime;
+            wi->fStart = start;
          } else {
-            wi->fStop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+            wi->fStop = stop;
          }
          TUrl uf(pe.fFileName), uw(pe.fSlaveName);
-         fMaxTime = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         fMaxTime = stop;
          wi->fEventsProcessed += pe.fEventsProcessed;
          wi->fBytesRead += pe.fBytesRead;
          wi->fLatency += pe.fLatency;
          wi->fProcTime += pe.fProcTime;
          wi->fCpuTime += pe.fCpuTime;
          // Fill graphs
-         Double_t tt = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         Double_t tt = stop;
          Double_t ert = pe.fEventsProcessed / pe.fProcTime ;
          Double_t brt = pe.fBytesRead / pe.fProcTime / 1024. / 1024. ;
          wi->fRateT->SetPoint(wi->fPackets, tt, ert);
@@ -774,8 +1022,35 @@ void TProofPerfAnalysis::FillWrkInfo(Bool_t force)
          if (ert > fEvtRateMax) fEvtRateMax = ert;
          if (brt > fMBRateMax) fMBRateMax = brt;
          if (pe.fLatency > fLatencyMax) fLatencyMax = pe.fLatency;
+
+         // Fill global rate histos
+         for (kk = 1; kk <= nbins; kk++) {
+            Double_t mi = fEvtRate->GetBinLowEdge(kk);
+            if (mi > stop) break;
+            Double_t wd = fEvtRate->GetBinWidth(kk);
+            Double_t mx = mi + wd;
+            Double_t xx = fEvtRate->GetBinCenter(kk);
+            // Overlap length
+            Double_t olap = stop - mi;
+            if (start > mi) olap = mx - start;
+            if (olap >= 0) {
+               TString sb = TString::Format("%d", kk);
+               if (!(gbl = (TList *) gBins.FindObject(sb))) {
+                  gbl = new TList;
+                  gbl->SetName(sb);
+                  gBins.Add(gbl);
+               }
+               if (!(gwl = (TList *) gbl->FindObject(pe.fSlave))) {
+                  gwl = new TList;
+                  gwl->SetName(pe.fSlave);
+                  gbl->Add(gwl);
+               }
+               gwl->Add(new TWrkEntry(xx, ert, brt, pe.fProcTime));
+            }
+         }
+
          // Notify
-         if (fgDebug > 1) {
+         if (fDebug > 1) {
             if (pe.fProcTime > 0.) {
                Printf(" +++ %s #:%d at:%fs lat:%fs proc:%fs evts:%lld bytes:%lld (rates:%f evt/s, %f MB/s)",
                      wi->GetName(), wi->fPackets, fMaxTime - pe.fProcTime,
@@ -788,21 +1063,75 @@ void TProofPerfAnalysis::FillWrkInfo(Bool_t force)
          }
       } else if (pe.fType == TVirtualPerfStats::kStart) {
          Float_t start = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
-         if (fgDebug > 1) Printf(" +++ %s Start: %f s", pe.fEvtNode.Data(), start);
+         if (fDebug > 1) Printf(" +++ %s Start: %f s", pe.fEvtNode.Data(), start);
       } else if (pe.fType == TVirtualPerfStats::kStop) {
          Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
-         if (fgDebug > 1) Printf(" +++ %s Stop: %f s", pe.fEvtNode.Data(), stop);
+         if (fDebug > 1) Printf(" +++ %s Stop: %f s", pe.fEvtNode.Data(), stop);
       } else {
-         if (fgDebug > 2) Printf(" +++ Event type: %d", pe.fType);
+         if (fDebug > 2) Printf(" +++ Event type: %d", pe.fType);
       }
    }
+
+   TIter nxb(&gBins);
+   gbl = 0;
+   while ((gbl = (TList *) nxb())) {
+      gwl = 0;
+      TIter nxw(gbl);
+      while ((gwl = (TList *) nxw())) {
+         Double_t er = 0, br = 0, pt = 0, xx = 0;
+         TIter nxp(gwl);
+         TWrkEntry *we = 0;
+         while ((we = (TWrkEntry *) nxp())) {
+            er += we->fEvtRate * we->fProcTime;
+            br += we->fMBRate * we->fProcTime;
+            pt += we->fProcTime;
+            xx = we->fXx;
+         }
+         if (pt > 0.) {
+            er /= pt;
+            br /= pt;
+            fEvtRate->Fill(xx, er);
+            if (br > 0.) fMBRate->Fill(xx, br);
+         }
+      }
+   }
+
+   // Running averages
+   Double_t er = 0, br = 0, pt = 0;
+   for (kk = 1; kk < nbins; kk++) {
+      Double_t wd = fEvtRate->GetBinWidth(kk);
+      Double_t wx = fEvtRate->GetBinCenter(kk);
+      Double_t wer = fEvtRate->GetBinContent(kk);
+      Double_t wbr = fMBRate->GetBinContent(kk);
+
+      if (kk == 1) {
+         er = wer;
+         br = wbr;
+         pt = wd; 
+      } else {
+         er *= pt;  
+         br *= pt;  
+         pt += wd;
+         er += wer * wd;
+         br += wbr * wd;
+         er /= pt;
+         br /= pt;
+      }
+      if (er > fEvtRateAvgMax) fEvtRateAvgMax = er;
+      if (br > fMBRateAvgMax) fMBRateAvgMax = br;
+      fEvtRateAvg = er;
+      fMBRateAvg = br;
+      // Fill
+      fEvtRateRun->Fill(wx, er);
+      fMBRateRun->Fill(wx, br);
+   }
+
+
    // Final analysis to find relevant times
-   fMergeTime = fMaxTime;
    TIter nxw(wl);
    while ((wi = (TWrkInfo *) nxw())) {
       fWrksInfo.Add(wi);
       if (wi->fStart > fInitTime) fInitTime = wi->fStart;
-      if (wi->fStop < fMergeTime || fMergeTime < 0.) fMergeTime = wi->fStop;
       // Resize the graphs
       wi->fRateT->Set(wi->fPackets);
       wi->fRateRemoteT->Set(wi->fRemotePackets);
@@ -813,6 +1142,16 @@ void TProofPerfAnalysis::FillWrkInfo(Bool_t force)
    wl->SetOwner(kFALSE);
    delete wl;
 
+   // Final analysis to find relevant times
+   fMergeTime = fMaxTime;
+   Int_t rsw = (fWrksInfo.GetSize() > 1) ? 2 : 2, ksw = 0;
+   TIter nxsw(&fWrksInfo);
+   while ((wi = (TWrkInfo *) nxsw())) {
+      if (wi->fStop > 0.) ksw++;
+      if (ksw == rsw) break;
+   }
+   if (wi) fMergeTime = wi->fStop;
+
    // (Re-)create the event and packet distribution histograms
    SafeDelete(fEvents);
    SafeDelete(fPackets);
@@ -838,9 +1177,162 @@ void TProofPerfAnalysis::FillWrkInfo(Bool_t force)
    fPackets->GetXaxis()->SetTitle("Worker");
    
    // Print summary
-   Printf(" +++ %d workers were active during this query", fWrksInfo.GetSize());
-   Printf(" +++ Total query time: %f secs (init: %f secs, merge: %f secs)",
-          fMaxTime, fInitTime, fMaxTime - fMergeTime);
+   if (fgDebug) Summary();
+}
+
+//________________________________________________________________________
+void TProofPerfAnalysis::Summary(Option_t *opt, const char *out)
+{
+   // Print summary of query. Use opt = 'S' for compact version.
+   // Output to 'out' or to screen.
+   
+   TString o(out);
+   RedirectHandle_t rh;
+   if (!o.IsNull()) {
+      const char *m = (o.BeginsWith("+")) ? "a" : "w";
+      o.Remove(TString::kLeading, '+');
+      gSystem->RedirectOutput(o, m, &rh);
+   }
+
+   // Print summary
+   if (!strcmp(opt, "S")) {
+      // Short version
+      Printf("%d %f %f %f %f %f %f %f",
+              fWrksInfo.GetSize(), fMaxTime, fInitTime, fMaxTime - fMergeTime,
+              fEvtRateAvg, fEvtRateAvgMax, fMBRateAvg, fMBRateAvgMax);
+   } else {
+      // Long version
+      Printf(" +++ %d workers were active during this query", fWrksInfo.GetSize());
+      Printf(" +++ Total query time: %f secs (init: %f secs, merge: %f secs)",
+             fMaxTime, fInitTime, fMaxTime - fMergeTime);
+      Printf(" +++ Avg processing rates: %.4f evts/s, %.4f MB/s", fEvtRateAvg, fMBRateAvg);
+      Printf(" +++ Max processing rates: %.4f evts/s, %.4f MB/s", fEvtRateAvgMax, fMBRateAvgMax);
+   }
+
+   if (!o.IsNull()) gSystem->RedirectOutput(0, 0, &rh);
+}
+
+//________________________________________________________________________
+void TProofPerfAnalysis::FillFileInfo(Bool_t force)
+{
+   // Fill basic worker info; if 'force' rescan the TTree even already done
+
+   // Nothing to do if already called
+   if (fFilesInfo.GetSize() > 0 && !force) return;
+
+   // Cleanup existing information
+   fFilesInfo.SetOwner(kTRUE);
+   fFilesInfo.Clear();
+   
+   TList *fl = new TList;
+   // Extract worker information
+   TPerfEvent pe;
+   TPerfEvent* pep = &pe;
+   fTree->SetBranchAddress("PerfEvents",&pep);
+   Long64_t entries = fTree->GetEntries();
+   TFileInfo *fi = 0;
+   for (Long64_t k=0; k<entries; k++) {
+      fTree->GetEntry(k);
+      // Analyse only packets
+      if (pe.fType == TVirtualPerfStats::kPacket) {
+         TUrl uf(pe.fFileName);
+         TString srv(uf.GetUrl());
+         Int_t ifn = srv.Index(uf.GetFile());
+         if (ifn != kNPOS) srv.Remove(ifn);
+         // Find out the file instance
+         fi = (TFileInfo *) fl->FindObject(uf.GetFile());
+         if (!fi) {
+            fi = new TFileInfo(uf.GetFile(), srv.Data());
+            fl->Add(fi);
+            fi->fSizeP = new TGraph(10);
+            fi->fRateP = new TGraph(10);
+            fi->fRatePRemote = new TGraph(10);
+            fi->fMBRateP = new TGraph(10);
+            fi->fMBRatePRemote = new TGraph(10);
+         }
+         // Add Info now
+         Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         Float_t start = stop - pe.fProcTime;
+         if (fi->fPackets <= 0) {
+            fi->fStart = start;
+         } else {
+            fi->fStop = stop;
+         }
+         TUrl uw(pe.fSlaveName);
+
+         // Fill size graphs
+         fi->fSizeP->SetPoint(fi->fPackets, (Double_t) fi->fPackets, (Double_t) pe.fEventsProcessed);
+         fi->fSizeAvg += pe.fEventsProcessed;
+         if (pe.fEventsProcessed > fi->fSizeMax || fi->fSizeMax < 0.) fi->fSizeMax = pe.fEventsProcessed;
+         if (pe.fEventsProcessed < fi->fSizeMin || fi->fSizeMin < 0.) fi->fSizeMin = pe.fEventsProcessed;
+
+         // Fill rate graphs
+         Double_t tt = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         Double_t ert = pe.fEventsProcessed / pe.fProcTime ;
+         Double_t brt = pe.fBytesRead / pe.fProcTime / 1024. / 1024. ;
+         fi->fRateP->SetPoint(fi->fPackets, tt, ert);
+         if (brt > 0.) fi->fMBRateP->SetPoint(fi->fPackets, tt, brt);
+         if (!pe.fFileName.IsNull() && strcmp(uf.GetHostFQDN(), uw.GetHostFQDN())) {
+            if (!(fi->fRWrkList.FindObject(pe.fSlave))) fi->fRWrkList.Add(new TNamed(pe.fSlave, pe.fSlaveName));
+            fi->fRatePRemote->SetPoint(fi->fRPackets, tt, ert);
+            fi->fMBRatePRemote->SetPoint(fi->fRPackets, tt, brt);
+            fi->fRPackets++;
+         }
+         fi->fPackets++;
+         if (brt > 0) {
+            fi->fMBRateAvg += brt;
+            if (brt > fi->fMBRateMax || fi->fMBRateMax < 0.) fi->fMBRateMax = brt;
+            if (brt < fi->fMBRateMin || fi->fMBRateMin < 0.) fi->fMBRateMin = brt;
+         }
+
+         // Packet info
+         TPackInfo *pi = new TPackInfo(pe.fSlave, pe.fSlaveName, start, stop, pe.fEventsProcessed, brt);
+         fi->fPackList.Add(pi);
+         TWrkInfoFile *wif = 0;
+         if (!(wif = (TWrkInfoFile *) fi->fWrkList.FindObject(pe.fSlave))) {
+            wif = new TWrkInfoFile(pe.fSlave, uf.GetFile());
+            fi->fWrkList.Add(wif);
+         }
+         wif->fPackets.Add(pi);
+
+         // Notify
+         if (fDebug > 1) {
+            if (pe.fProcTime > 0.) {
+               Printf(" +++ %s #:%d at:%fs lat:%fs proc:%fs evts:%lld bytes:%lld (rates:%f evt/s, %f MB/s)",
+                     fi->GetName(), fi->fPackets, fMaxTime - pe.fProcTime,
+                     pe.fLatency, pe.fProcTime, pe.fEventsProcessed, pe.fBytesRead,
+                     ert, brt);
+            } else {
+               Printf(" +++ %s #:%d at:%fs lat:%fs proc:%fs rate:-- evt/s (-- bytes/s)",
+                     fi->GetName(), fi->fPackets, fMaxTime, pe.fLatency, pe.fProcTime);
+            }
+         }
+      } else if (pe.fType == TVirtualPerfStats::kStart) {
+         Float_t start = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         if (fDebug > 1) Printf(" +++ %s Start: %f s", pe.fEvtNode.Data(), start);
+      } else if (pe.fType == TVirtualPerfStats::kStop) {
+         Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
+         if (fDebug > 1) Printf(" +++ %s Stop: %f s", pe.fEvtNode.Data(), stop);
+      } else {
+         if (fDebug > 2) Printf(" +++ Event type: %d", pe.fType);
+      }
+   }
+   // Final analysis to find relevant times
+   TIter nxf(fl);
+   while ((fi = (TFileInfo *) nxf())) {
+      fFilesInfo.Add(fi);
+      // Resize the graphs
+      fi->fRateP->Set(fi->fPackets);
+      fi->fRatePRemote->Set(fi->fRPackets);
+      fi->fMBRateP->Set(fi->fPackets);
+      fi->fMBRatePRemote->Set(fi->fRPackets);
+   }
+   fl->SetOwner(kFALSE);
+   delete fl;
+   
+   // Print summary
+   if (fgDebug)
+      Printf(" +++ %d files were processed during this query", fFilesInfo.GetSize());
 }
 
 //________________________________________________________________________
@@ -848,9 +1340,17 @@ void TProofPerfAnalysis::SetDebug(Int_t d)
 {
    // Static setter for the verbosity level
    
-   fgDebug = d;
+   fDebug = d;
 }
 
+
+//________________________________________________________________________
+void TProofPerfAnalysis::SetgDebug(Bool_t on)
+{
+   // Static setter for the verbosity level
+   
+   fgDebug = on;
+}
 //________________________________________________________________________
 void TProofPerfAnalysis::EventDist()
 {
@@ -881,20 +1381,28 @@ void TProofPerfAnalysis::RatePlot(const char *wrks)
 {
    // Show event processing or MB processing rate plot vs time
 
-   // Create the histograms
-   TObject *o = 0;
-   if ((o = gDirectory->FindObject("rt1"))) delete o;
-   TH1F *hrt1 = new TH1F("rt1", "Evt processing rate (evt/s)", 100, 0., fMaxTime);
-   hrt1->SetMinimum(0.);
-   hrt1->SetMaximum(1.05*fEvtRateMax);
-   hrt1->SetStats(kFALSE);
-   hrt1->GetXaxis()->SetTitle("Query Processing Time (s)");
-   if ((o = gDirectory->FindObject("rt2"))) delete o;
-   TH1F *hrt2 = new TH1F("rt2", "MB processing rate (MB/s)", 100, 0., fMaxTime);
-   hrt2->SetMinimum(0.);
-   hrt2->SetMaximum(1.05*fMBRateMax);
-   hrt2->SetStats(kFALSE);
-   hrt2->GetXaxis()->SetTitle("Query Processing Time (s)");
+   Bool_t global = (wrks && !strcmp(wrks, "global")) ? kTRUE : kFALSE;
+
+   TH1F *hrt1 = 0, *hrt2 = 0;
+   if (global) {
+      hrt1 = fEvtRate;
+      hrt2 = fMBRate;
+   } else {
+      // Create the histograms
+      TObject *o = 0;
+      if ((o = gDirectory->FindObject("rt1"))) delete o;
+      hrt1 = new TH1F("rt1", "Evt processing rate (evt/s)", 100, 0., fMaxTime);
+      hrt1->SetMinimum(0.);
+      hrt1->SetMaximum(1.05*fEvtRateMax);
+      hrt1->SetStats(kFALSE);
+      hrt1->GetXaxis()->SetTitle("Query Processing Time (s)");
+      if ((o = gDirectory->FindObject("rt2"))) delete o;
+      hrt2 = new TH1F("rt2", "MB processing rate (MB/s)", 100, 0., fMaxTime);
+      hrt2->SetMinimum(0.);
+      hrt2->SetMaximum(1.05*fMBRateMax);
+      hrt2->SetStats(kFALSE);
+      hrt2->GetXaxis()->SetTitle("Query Processing Time (s)");
+   }
 
    // Display histo frames
    TCanvas *c1 = new TCanvas("rates", GetCanvasTitle("Processing rates"), 800,10,700,780);
@@ -902,12 +1410,17 @@ void TProofPerfAnalysis::RatePlot(const char *wrks)
    TPad *pad1 = (TPad *) c1->GetPad(1);
    pad1->cd();
    hrt1->Draw();
+   if (global) fEvtRateRun->Draw("SAME");
    TPad *pad2 = (TPad *) c1->GetPad(2);
    pad2->cd();
    hrt2->Draw();
+   if (global) fMBRateRun->Draw("SAME");
    c1->cd();
    c1->Update();
 
+   // Done if global
+   if (global) return;
+
    // Which workers?
    THashList *wl = 0;
    TString ww(wrks);
@@ -921,6 +1434,7 @@ void TProofPerfAnalysis::RatePlot(const char *wrks)
    }
       
    // Now plot the graphs per worker
+   Int_t ci = 40, cir = 30, ic = 0;
    TIter nxw(&fWrksInfo);
    TWrkInfo *wi = 0;
    while ((wi = (TWrkInfo *) nxw())) {
@@ -928,25 +1442,30 @@ void TProofPerfAnalysis::RatePlot(const char *wrks)
       if (wi->fRateT && wi->fRateT->GetN() > 0) {
          wi->fRateT->SetNameTitle(wi->GetName(), wi->GetTitle());
          pad1->cd();
+         wi->fRateT->SetLineColor(ci);
          wi->fRateT->Draw("L");
       }
       if (wi->fRateRemoteT && wi->fRateRemoteT->GetN() > 0) {
          wi->fRateRemoteT->SetNameTitle(wi->GetName(), wi->GetTitle());
          pad1->cd();
-         wi->fRateRemoteT->SetLineColor(kRed);
+         wi->fRateRemoteT->SetLineColor(cir);
          wi->fRateRemoteT->Draw("L");
       }
       if (wi->fMBRateT && wi->fMBRateT->GetN() > 0) {
          wi->fMBRateT->SetNameTitle(wi->GetName(), wi->GetTitle());
          pad2->cd();
+         wi->fMBRateT->SetLineColor(ci);
          wi->fMBRateT->Draw("L");
       }
       if (wi->fMBRateRemoteT && wi->fMBRateRemoteT->GetN() > 0) {
          wi->fMBRateRemoteT->SetNameTitle(wi->GetName(), wi->GetTitle());
          pad2->cd();
-         wi->fMBRateRemoteT->SetLineColor(kRed);
+         wi->fMBRateRemoteT->SetLineColor(cir);
          wi->fMBRateRemoteT->Draw("L");
       }
+      ic++;
+      ci = ic%10 + 40;
+      cir = ic%10 + 30;
       c1->cd();
       c1->Update();
    }
@@ -992,14 +1511,18 @@ void TProofPerfAnalysis::LatencyPlot(const char *wrks)
    }
       
    // Now plot the graphs per worker
+   Int_t ci = 40, ic = 0;
    TIter nxw(&fWrksInfo);
    TWrkInfo *wi = 0;
    while ((wi = (TWrkInfo *) nxw())) {
       if (wl && !wl->FindObject(wi->GetName())) continue;
       if (wi->fLatencyT) {
          wi->fLatencyT->SetNameTitle(wi->GetName(), wi->GetTitle());
+         wi->fLatencyT->SetLineColor(ci);
          wi->fLatencyT->Draw("L");
       }
+      ic++;
+      ci = ic%10 + 40;
       c1->cd();
       c1->Update();
    }
@@ -1010,3 +1533,210 @@ void TProofPerfAnalysis::LatencyPlot(const char *wrks)
       delete wl;
    }
 }
+
+//________________________________________________________________________
+void TProofPerfAnalysis::FileProcPlot(const char *fn, const char *out)
+{
+   // Show event processing or MB processing rate plot vs time
+
+   if (!fn || strlen(fn) <= 0) {
+      Error("FileRatePlot", "file name is mandatory!");
+      return;
+   }
+   // Get the file info object
+   TFileInfo *fi = (TFileInfo *) fFilesInfo.FindObject(fn);
+   if (!fi) {
+      Error("FileRatePlot", "TFileInfo object for '%s' not found!", fn);
+      return;
+   }
+
+   // Output text file, if required
+   FILE *fo = stdout;
+   if (out && strlen(out) > 0) {
+      if (!(fo = fopen(out, "w"))) {
+         Warning("FileRatePlot", "problems creating '%s': logging to stdout", out);
+         fo = stdout;
+      } else {
+         Printf(" Details logged to %s", out);
+      }
+   }
+
+   // Get bins
+   Int_t nbins = fi->fPackList.GetSize() * 2;
+   Double_t *xraw = new Double_t[nbins];
+   Int_t jj = 0;
+   TPackInfo *pi = 0;
+   TIter nxp(&(fi->fPackList));
+   while ((pi = (TPackInfo *) nxp())) {
+      // Bins
+      xraw[jj++] = pi->fStart;
+      xraw[jj++] = pi->fStop;
+   }
+   Int_t *jidx = new Int_t[nbins];
+   memset(jidx, 0, nbins * sizeof(Int_t));
+   TMath::Sort(nbins, xraw, jidx, kFALSE);
+   Double_t *xbins = new Double_t[nbins];
+   Int_t kk =0;
+   for (kk = 0; kk < nbins; kk++) {
+      xbins[kk] = xraw[jidx[kk]];
+   }
+   delete [] xraw;
+   delete [] jidx;
+
+   // Create the histograms
+   Int_t nbin = nbins - 1;
+   TObject *o = 0;
+   if ((o = gDirectory->FindObject("rt1"))) delete o;
+   TH1F *hrt1 = new TH1F("rt1", "Total processing rate (MB/s)", nbins - 1, xbins);
+   hrt1->SetMinimum(0.);
+   hrt1->SetStats(kFALSE);
+   hrt1->GetXaxis()->SetTitle("Query Processing Time (s)");
+   if ((o = gDirectory->FindObject("rt2"))) delete o;
+   TH1F *hrt2 = new TH1F("rt2", "Number of processing workers", nbins - 1, xbins);
+   hrt2->SetMinimum(0.);
+   hrt2->SetMaximum(1.2*fWrksInfo.GetSize());
+   hrt2->SetStats(kFALSE);
+   hrt2->GetXaxis()->SetTitle("Query Processing Time (s)");
+   if ((o = gDirectory->FindObject("rt3"))) delete o;
+   TH1F *hrt3 = new TH1F("rt3", "Total processing events", nbins - 1, xbins);
+   hrt3->SetMinimum(0.);
+   hrt3->SetStats(kFALSE);
+   hrt3->GetXaxis()->SetTitle("Query Processing Time (s)");
+   if ((o = gDirectory->FindObject("rt4"))) delete o;
+   TH1F *hrt4 = new TH1F("rt4", "Weighted processing rate (MB/s)", nbins - 1, xbins);
+   hrt4->SetMinimum(0.);
+   hrt4->SetStats(kFALSE);
+   hrt4->GetXaxis()->SetTitle("Query Processing Time (s)");
+   // Not needed any longer
+   delete [] xbins;
+
+   // Fill histos now
+   Int_t ii = 0;
+   for (ii = 1; ii <= nbin; ii++) {
+      Double_t mi = hrt1->GetBinLowEdge(ii);
+      Double_t wd = hrt1->GetBinWidth(ii);
+      Double_t mx = mi + wd;
+      Double_t xx = hrt1->GetBinCenter(ii);
+      fprintf(fo, " Bin: %d/%d [%f, %f]\n", ii, nbin, mi, mx);
+      pi = 0;
+      kk = 0;
+      nxp.Reset();
+      while ((pi = (TPackInfo *) nxp())) {
+         // Overlap length
+         Double_t olap = pi->fStop - mi;
+         if (pi->fStart > mi) olap = mx - pi->fStart;
+         if (olap >= 0) {
+            hrt1->Fill(xx, pi->fMBRate);
+            hrt2->Fill(xx, 1.);
+            hrt3->Fill(xx, pi->fSize);
+            hrt4->Fill(xx, pi->fMBRate * pi->fSize);
+            fprintf(fo, "    %d: %s \t%lld \tevts \t%f \tMB/s\n", kk++, pi->GetName(), pi->fSize, pi->fMBRate);
+         }
+      }
+   }
+   if (fo != stdout) fclose(fo);
+
+   // Display histo frames
+   TCanvas *c1 = new TCanvas("rates", GetCanvasTitle("File processing info"), 800,10,700,780);
+   c1->Divide(1,3);
+   TPad *pad1 = (TPad *) c1->GetPad(1);
+   pad1->cd();
+   hrt1->Draw();
+   TPad *pad2 = (TPad *) c1->GetPad(2);
+   pad2->cd();
+   hrt2->Draw();
+   TPad *pad4 = (TPad *) c1->GetPad(3);
+   pad4->cd();
+   hrt4->Divide(hrt3);
+   hrt4->Draw();
+   c1->cd();
+   c1->Update();
+}
+
+//________________________________________________________________________
+void TProofPerfAnalysis::FileRatePlot(const char *fns)
+{
+   // Show MB processing rate plot per file vs time
+
+   // Create the histograms
+   TObject *o = 0;
+   if ((o = gDirectory->FindObject("rt1"))) delete o;
+   TH1F *hrt1 = new TH1F("rt1", "Event processing rate per packet (evt/s)", 100, 0., fMaxTime);
+   hrt1->SetMinimum(0.);
+   hrt1->SetMaximum(1.05*fEvtRateMax);
+   hrt1->SetStats(kFALSE);
+   hrt1->GetXaxis()->SetTitle("Query Processing Time (s)");
+   if ((o = gDirectory->FindObject("rt2"))) delete o;
+   TH1F *hrt2 = new TH1F("rt2", "I/O processing rate per packet (MB/s)", 100, 0., fMaxTime);
+   hrt2->SetMinimum(0.);
+   hrt2->SetMaximum(1.05*fMBRateMax);
+   hrt2->SetStats(kFALSE);
+   hrt2->GetXaxis()->SetTitle("Query Processing Time (s)");
+
+   // Display histo frames
+   TCanvas *c1 = new TCanvas("rates", GetCanvasTitle("Processing rates"), 800,10,700,780);
+   c1->Divide(1,2);
+   TPad *pad1 = (TPad *) c1->GetPad(1);
+   pad1->cd();
+   hrt1->Draw();
+   TPad *pad2 = (TPad *) c1->GetPad(2);
+   pad2->cd();
+   hrt2->Draw();
+   c1->cd();
+   c1->Update();
+
+   // Which workers?
+   THashList *fl = 0;
+   TString fw(fns);
+   if (!fw.IsNull() && fw != "*" && fw != "all") {
+      TString w;
+      Ssiz_t from = 0;
+      while ((fw.Tokenize(w, from, ","))) {
+         if (!fl) fl = new THashList();
+         fl->Add(new TObjString(w.Data()));
+      }
+   }
+      
+   // Now plot the graphs per worker
+   Int_t ci = 40, cir = 30, ic = 0;
+   TIter nxf(&fFilesInfo);
+   TFileInfo *fi = 0;
+   while ((fi = (TFileInfo *) nxf())) {
+      if (fl && !fl->FindObject(fi->GetName())) continue;
+      if (fi->fRateP && fi->fRateP->GetN() > 0) {
+         fi->fRateP->SetNameTitle(fi->GetName(), fi->GetTitle());
+         pad1->cd();
+         fi->fRateP->SetLineColor(ci);
+         fi->fRateP->Draw("L");
+      }
+      if (fi->fRatePRemote && fi->fRatePRemote->GetN() > 0) {
+         fi->fRatePRemote->SetNameTitle(fi->GetName(), fi->GetTitle());
+         pad1->cd();
+         fi->fRatePRemote->SetLineColor(cir);
+         fi->fRatePRemote->Draw("L");
+      }
+      if (fi->fMBRateP && fi->fMBRateP->GetN() > 0) {
+         fi->fMBRateP->SetNameTitle(fi->GetName(), fi->GetTitle());
+         pad2->cd();
+         fi->fMBRateP->SetLineColor(ci);
+         fi->fMBRateP->Draw("L");
+      }
+      if (fi->fMBRatePRemote && fi->fMBRatePRemote->GetN() > 0) {
+         fi->fMBRatePRemote->SetNameTitle(fi->GetName(), fi->GetTitle());
+         pad2->cd();
+         fi->fMBRatePRemote->SetLineColor(cir);
+         fi->fMBRatePRemote->Draw("L");
+      }
+      ic++;
+      ci = ic%10 + 40;
+      cir = ic%10 + 30;
+      c1->cd();
+      c1->Update();
+   }
+
+   // Cleanup
+   if (fl) {
+      fl->SetOwner(kTRUE);
+      delete fl;
+   }
+}
diff --git a/proof/proofd/inc/XrdProofdProofServMgr.h b/proof/proofd/inc/XrdProofdProofServMgr.h
index 4cf8107..de1c44a 100644
--- a/proof/proofd/inc/XrdProofdProofServMgr.h
+++ b/proof/proofd/inc/XrdProofdProofServMgr.h
@@ -267,8 +267,12 @@ public:
 
    int               CleanupProofServ(bool all = 0, const char *usr = 0);
 
-   void              GetLogFile(XrdProofdProtocol *p, XrdProofdProofServ *xps,
-                                XrdOucString &sessiondir, XrdOucString &logfile);
+   void              FormFileNameInSessionDir(XrdProofdProtocol *p,
+                                              XrdProofdProofServ *xps,
+                                              const char *sessiondir,
+                                              const char *extension,
+                                              XrdOucString &outfn);
+
    void              GetTagDirs(int opt, XrdProofdProtocol *p, XrdProofdProofServ *xps,
                                 XrdOucString &sesstag, XrdOucString &topsesstag,
                                 XrdOucString &sessiondir, XrdOucString &sesswrkdir);
diff --git a/proof/proofd/src/XrdProofSched.cxx b/proof/proofd/src/XrdProofSched.cxx
index 7aeb4df..b61ec9c 100644
--- a/proof/proofd/src/XrdProofSched.cxx
+++ b/proof/proofd/src/XrdProofSched.cxx
@@ -516,7 +516,7 @@ int XrdProofSched::GetWorkers(XrdProofdProofServ *xps,
       }
    } else {
       if (maxnum > 0) {
-         // This is over-conservative for sub-selectiob (random, or round-robin options)
+         // This is over-conservative for sub-selection (random, or round-robin options)
          // A better solution should be implemented for that.
          int nactsess = mst->GetNActiveSessions();
          TRACE(REQ, "act sess ... " << nactsess);
@@ -549,8 +549,8 @@ int XrdProofSched::GetWorkers(XrdProofdProofServ *xps,
       }
    }
 
-   // If the session has already assigned workers just return
-   if (xps->Workers()->Num() > 0) {
+   // If a non-dynamic session already has assigned workers just return
+   if (!isDynamic && (xps->Workers()->Num() > 0)) {
       // Current assignement is valid
       SafeDel(acwseff);
       return 1;
diff --git a/proof/proofd/src/XrdProofdAdmin.cxx b/proof/proofd/src/XrdProofdAdmin.cxx
index 90c20d8..48702e5 100644
--- a/proof/proofd/src/XrdProofdAdmin.cxx
+++ b/proof/proofd/src/XrdProofdAdmin.cxx
@@ -779,14 +779,27 @@ int XrdProofdAdmin::QueryLogPaths(XrdProofdProtocol *p)
    bool ismaster = (access(wfile.c_str(), F_OK) == 0) ? 1 : 0;
    
    // Scan the directory to add the top master (only if top master)
-   XrdOucString xo;
-   int ilog, idas;
+   XrdOucString xo, logtag;
+   int ilog, idas, iund1, iund2;
    struct dirent *ent = 0;
    while ((ent = (struct dirent *)readdir(dir))) {         
       xo = ent->d_name;
       bool recordinfo = 0;
       if ((ilog = xo.find(".log")) != STR_NPOS) {
          xo.replace(".log", "");
+
+         // If it is an "additional" logfile, extract a "tag" identifying it
+         // from the filename. Tag is in format: __<tag>__
+         iund1 = xo.find("__");
+         if (iund1 != STR_NPOS) {
+            iund2 = xo.rfind("__");
+            if ((iund2 != STR_NPOS) && (iund2 != iund1)) {
+               logtag = xo;
+               logtag.erase(iund2);
+               logtag.erase(0, iund1+2);
+            }
+         }
+
          if ((idas = xo.find('-')) != STR_NPOS) xo.erase(0, idas + 1);
          if ((idas = xo.find('-')) != STR_NPOS) xo.erase(idas);
          if (ord.length() > 0 && (ord == xo)) {
@@ -800,6 +813,7 @@ int XrdProofdAdmin::QueryLogPaths(XrdProofdProtocol *p)
          }
          if (recordinfo) {
             rmsg += "|"; rmsg += xo;
+            if (logtag != "") { rmsg += '('; rmsg += logtag; rmsg += ')'; }
             rmsg += " proof://"; rmsg += fMgr->Host(); rmsg += ':';
             rmsg += fMgr->Port(); rmsg += '/';
             rmsg += sdir; rmsg += '/'; rmsg += ent->d_name;
diff --git a/proof/proofd/src/XrdProofdNetMgr.cxx b/proof/proofd/src/XrdProofdNetMgr.cxx
index c18bf07..3170d03 100644
--- a/proof/proofd/src/XrdProofdNetMgr.cxx
+++ b/proof/proofd/src/XrdProofdNetMgr.cxx
@@ -1390,10 +1390,14 @@ char *XrdProofdNetMgr::ReadBufferLocal(const char *path,
    if (pat && strlen(pat) > 0) {
       lcmd = strlen(pat) + strlen(file) + 20;
       cmd = new char[lcmd];
-      if (opt == 2) {
-         snprintf(cmd, lcmd, "grep -v %s %s", pat, file);
-      } else {
+      if (opt == 1) {
          snprintf(cmd, lcmd, "grep %s %s", pat, file);
+      } else if (opt == 2) {
+         snprintf(cmd, lcmd, "grep -v %s %s", pat, file);
+      } else if (opt == 3) {
+         snprintf(cmd, lcmd, "cat %s | %s", file, pat);
+      } else { // should not be here
+         snprintf(cmd, lcmd, "cat %s", file);
       }
    } else {
       lcmd = strlen(file) + 10;
diff --git a/proof/proofd/src/XrdProofdProofServMgr.cxx b/proof/proofd/src/XrdProofdProofServMgr.cxx
index 484c462..504ce68 100644
--- a/proof/proofd/src/XrdProofdProofServMgr.cxx
+++ b/proof/proofd/src/XrdProofdProofServMgr.cxx
@@ -1821,7 +1821,7 @@ int XrdProofdProofServMgr::CreateFork(XrdProofdProtocol *p)
                  p, xps, in.fSessionTag, in.fTopSessionTag, in.fSessionDir, in.fWrkDir);
 
       // Create log file path
-      GetLogFile(p, xps, in.fSessionDir, in.fLogFile);
+      FormFileNameInSessionDir(p, xps, in.fSessionDir.c_str(), "log", in.fLogFile);
 
       // Log to the session log file from now on
       if (fLogger) fLogger->Bind(in.fLogFile.c_str());
@@ -1992,9 +1992,12 @@ int XrdProofdProofServMgr::CreateFork(XrdProofdProtocol *p)
    TRACEP(p, FORK,"Parent process: child is "<<pid);
    XrdOucString emsg;
 
-   // Finalize unique tag and relevant dirs for this session and create log file path
+   // Finalize unique tag and relevant dirs for this session
    GetTagDirs((int)pid, p, xps, in.fSessionTag, in.fTopSessionTag, in.fSessionDir, in.fWrkDir);
-   XPDFORM(in.fLogFile, "%s.log", in.fWrkDir.c_str());
+
+   // Create log file path
+   FormFileNameInSessionDir(p, xps, in.fSessionDir.c_str(), "log", in.fLogFile);
+
    TRACEP(p, FORK, "log file: "<<in.fLogFile);
 
    // Log prefix
@@ -2395,7 +2398,7 @@ int XrdProofdProofServMgr::Create(XrdProofdProtocol *p)
       return 0;
    }
 
-   // Create the RC-file and env-file paths for this session: for masters this will be temporary
+   // Create the RC-file and env-file paths for this session: for masters this will be temporarily
    // located in the sandbox
    XrdOucString rcfile, envfile;
    if (p->ConnType() == kXPD_ClientMaster) {
@@ -3109,7 +3112,6 @@ int XrdProofdProofServMgr::SetProofServEnvOld(XrdProofdProtocol *p, void *input)
                return -1;
             }
          }
-         fclose(fenv);
       }
    }
 
@@ -3311,8 +3313,11 @@ int XrdProofdProofServMgr::SetProofServEnv(XrdProofdManager *mgr, XrdROOT *r)
 }
 
 //______________________________________________________________________________
-void XrdProofdProofServMgr::GetLogFile(XrdProofdProtocol *p, XrdProofdProofServ *xps,
-                                       XrdOucString &sessiondir, XrdOucString &logfile)
+void XrdProofdProofServMgr::FormFileNameInSessionDir(XrdProofdProtocol *p,
+                                                     XrdProofdProofServ *xps,
+                                                     const char *sessiondir,
+                                                     const char *extension,
+                                                     XrdOucString &outfn)
 {
    XrdOucString host   = fMgr->Host();
    XrdOucString ord    = xps->Ordinal();
@@ -3325,14 +3330,15 @@ void XrdProofdProofServMgr::GetLogFile(XrdProofdProtocol *p, XrdProofdProofServ
    if (p->ConnType() == kXPD_MasterWorker) role = "worker";
    else role = "master";
 
-   // Log file name format:
-   // <sessiondir>/[master|worker]-<ordinal>-<host>.log
+   // File name format:
+   // <sessiondir>/[master|worker]-<ordinal>-<host>.<ext>
    // No PID is contained
-   XPDFORM(logfile, "%s/%s-%s-%s.log",
-      sessiondir.c_str(),
+   XPDFORM(outfn, "%s/%s-%s-%s.%s",
+      sessiondir,
       role.c_str(),
       ord.c_str(),
-      host.c_str()
+      host.c_str(),
+      extension
    );
 }
 
@@ -3487,18 +3493,16 @@ int XrdProofdProofServMgr::SetProofServEnv(XrdProofdProtocol *p, void *input)
       return -1;
    }
 
-   // Create the rootrc and env files
-   TRACE(DBG, "creating env file");
-   XrdOucString rcfile = in->fWrkDir;
-   rcfile += ".rootrc";
+   // Create .rootrc and .env files
+   TRACE(DBG, "creating rc and env files");
+   XrdOucString rcfile, envfile;
+   FormFileNameInSessionDir(p, xps, in->fSessionDir.c_str(), "rootrc", rcfile);
    if (CreateProofServRootRc(p, in, rcfile.c_str()) != 0) {
       TRACE(XERR, "problems creating RC file "<<rcfile.c_str());
       return -1;
    }
 
-   // Now save the exported env variables, for the record
-   XrdOucString envfile = in->fWrkDir;
-   envfile += ".env";
+   FormFileNameInSessionDir(p, xps, in->fSessionDir.c_str(), "env", envfile);
    if (CreateProofServEnvFile(p, in, envfile.c_str(), rcfile.c_str()) != 0) {
       TRACE(XERR, "problems creating environment file "<<envfile.c_str());
       return -1;
@@ -3604,7 +3608,6 @@ int XrdProofdProofServMgr::CreateProofServEnvFile(XrdProofdProtocol *p, void *in
                return -1;
             }
          }
-         fclose(fenv);
       }
    }
 
diff --git a/proof/proofplayer/inc/TPacketizerUnit.h b/proof/proofplayer/inc/TPacketizerUnit.h
index 6bda197..120103e 100644
--- a/proof/proofplayer/inc/TPacketizerUnit.h
+++ b/proof/proofplayer/inc/TPacketizerUnit.h
@@ -49,23 +49,28 @@ public:              // public because of Sun CC bug
 private:
    TList      *fPackets;         // All processed packets
    TMap       *fWrkStats;        // Worker status, keyed by correspondig TSlave
+   TList      *fWrkExcluded;     // List of nodes excluded from distribution
+                                 // (submasters with no active workers)
    TStopwatch *fStopwatch;       // For measuring the start time of each packet
    Long64_t    fProcessing;      // Event being processed
    Long64_t    fAssigned;        // Entries processed or being processed.
    Double_t    fCalibFrac;       // Size of the calibrating packet as fraction of Ntot/Nwrk
    Long64_t    fNumPerWorker;    // Number of cycles per worker, if this option
                                  // is chosen
+   Bool_t      fFixedNum;        // Whether we must assign a fixed number of cycles per worker
 
    Long64_t    fPacketSeq;       // Sequential number of the last packet assigned
+   TList      *fInput;           // Input list
 
    TPacketizerUnit();
    TPacketizerUnit(const TPacketizerUnit&);     // no implementation, will generate
-   void operator=(const TPacketizerUnit&);  // error on accidental usage
+   void operator=(const TPacketizerUnit&);      // error on accidental usage
 
 public:
    TPacketizerUnit(TList *slaves, Long64_t num, TList *input, TProofProgressStatus *st = 0);
    virtual ~TPacketizerUnit();
 
+   Int_t         AssignWork(TDSet * /*dset*/, Long64_t /*first*/, Long64_t num);
    TDSetElement *GetNextPacket(TSlave *sl, TMessage *r);
 
    Double_t      GetCurrentTime();
@@ -73,6 +78,8 @@ public:
    Float_t       GetCurrentRate(Bool_t &all);
    Int_t         GetActiveWorkers() { return fWrkStats->GetSize(); }
 
+   Int_t         AddWorkers(TList *workers);
+
    ClassDef(TPacketizerUnit,0)  //Generate work packets for parallel processing
 };
 
diff --git a/proof/proofplayer/inc/TProofPlayer.h b/proof/proofplayer/inc/TProofPlayer.h
index 8a9ffe3..12dc343 100644
--- a/proof/proofplayer/inc/TProofPlayer.h
+++ b/proof/proofplayer/inc/TProofPlayer.h
@@ -70,6 +70,7 @@ class TTimer;
 class THashList;
 class TH1;
 class TFile;
+class TStopwatch;
 
 //------------------------------------------------------------------------
 
@@ -107,6 +108,9 @@ protected:
 
    TTimer       *fDispatchTimer;    //Dispatch pending events while processing
 
+   TTimer       *fProcTimeTimer;    //Notifies reaching of allowed max proc time 
+   TStopwatch   *fProcTime;         //Packet proc time
+
    TString       fOutputFilePath;   //Path to file with (partial) results of the query
    TFile        *fOutputFile;       //TFile object attached to fOutputFilePath
    Long_t        fSaveMemThreshold; //Threshold for saving output to file
@@ -141,7 +145,8 @@ protected:
    void MapOutputListToDataMembers() const;
 
 public:
-   enum EStatusBits { kDispatchOneEvent = BIT(15), kIsProcessing = BIT(16) };
+   enum EStatusBits { kDispatchOneEvent = BIT(15), kIsProcessing = BIT(16),
+                      kMaxProcTimeReached = BIT(17), kMaxProcTimeExtended = BIT(18) };
 
    TProofPlayer(TProof *proof = 0);
    virtual ~TProofPlayer();
@@ -152,6 +157,7 @@ public:
    Long64_t  Process(TDSet *set,
                      TSelector *selector, Option_t *option = "",
                      Long64_t nentries = -1, Long64_t firstentry = 0);
+   virtual Bool_t JoinProcess(TList *workers);
    TVirtualPacketizer *GetPacketizer() const { return 0; }
    Long64_t  Finalize(Bool_t force = kFALSE, Bool_t sync = kFALSE);
    Long64_t  Finalize(TQueryResult *qr);
@@ -297,6 +303,8 @@ protected:
    ErrorHandlerFunc_t  fErrorHandler;  // Store previous handler when redirecting output
    Bool_t              fMergeTH1OneByOne;  // If kTRUE forces TH1 merge one-by-one [kTRUE]
    TH1                *fProcPackets;    //!Histogram with packets being processed (owned by TPerfStats)
+   TMessage           *fProcessMessage;  // Process message to replay when adding new workers dynamically
+   TString             fSelectorFileName;  // Current Selector's name, set by Process()
 
    virtual Bool_t  HandleTimer(TTimer *timer);
    Int_t           InitPacketizer(TDSet *dset, Long64_t nentries,
@@ -316,7 +324,8 @@ public:
    TProofPlayerRemote(TProof *proof = 0) : fProof(proof), fOutputLists(0), fFeedback(0),
                                            fFeedbackLists(0), fPacketizer(0),
                                            fMergeFiles(kFALSE), fDSet(0), fErrorHandler(0),
-                                           fMergeTH1OneByOne(kTRUE), fProcPackets(0)
+                                           fMergeTH1OneByOne(kTRUE), fProcPackets(0),
+                                           fProcessMessage(0)
                                            { fProgressStatus = new TProofProgressStatus(); }
    virtual ~TProofPlayerRemote();   // Owns the fOutput list
    virtual Long64_t Process(TDSet *set, const char *selector,
@@ -325,6 +334,7 @@ public:
    virtual Long64_t Process(TDSet *set, TSelector *selector,
                             Option_t *option = "", Long64_t nentries = -1,
                             Long64_t firstentry = 0);
+   virtual Bool_t JoinProcess(TList *workers);
    virtual Long64_t Finalize(Bool_t force = kFALSE, Bool_t sync = kFALSE);
    virtual Long64_t Finalize(TQueryResult *qr);
    Long64_t       DrawSelect(TDSet *set, const char *varexp,
diff --git a/proof/proofplayer/inc/TVirtualPacketizer.h b/proof/proofplayer/inc/TVirtualPacketizer.h
index 5e45945..a9c72f8 100644
--- a/proof/proofplayer/inc/TVirtualPacketizer.h
+++ b/proof/proofplayer/inc/TVirtualPacketizer.h
@@ -132,6 +132,7 @@ public:
    virtual void            StopProcess(Bool_t abort, Bool_t stoptimer = kFALSE);
    TList                  *GetFailedPackets() { return fFailedPackets; }
    void                    SetFailedPackets(TList *list) { fFailedPackets = list; }
+   virtual Int_t           AddWorkers(TList *workers);
 
    Long64_t      GetBytesRead() const { return (fProgressStatus? fProgressStatus->GetBytesRead() : 0); }
    Long64_t      GetReadCalls() const { return (fProgressStatus? fProgressStatus->GetReadCalls() : 0); }
diff --git a/proof/proofplayer/src/TPacketizerUnit.cxx b/proof/proofplayer/src/TPacketizerUnit.cxx
index 0d6f823..ed9f8ef 100644
--- a/proof/proofplayer/src/TPacketizerUnit.cxx
+++ b/proof/proofplayer/src/TPacketizerUnit.cxx
@@ -179,12 +179,16 @@ TPacketizerUnit::TPacketizerUnit(TList *slaves, Long64_t num, TList *input,
    // Init pointer members
    fWrkStats = 0;
    fPackets = 0;
+   fInput = input;
 
+   fFixedNum = kFALSE;
    Int_t fixednum = -1;
-   if (TProof::GetParameter(input, "PROOF_PacketizerFixedNum", fixednum) != 0 || fixednum <= 0)
-      fixednum = 0;
-   if (fixednum == 1)
+   if (TProof::GetParameter(input, "PROOF_PacketizerFixedNum", fixednum) != 0 || fixednum <= 0) {
+      fFixedNum = kFALSE;
+   } else {
       Info("TPacketizerUnit", "forcing the same cycles on each worker");
+      fFixedNum = kTRUE;
+   }
 
    fCalibFrac = 0.01; 
    if (TProof::GetParameter(input, "PROOF_PacketizerCalibFrac", fCalibFrac) != 0 || fCalibFrac <= 0)
@@ -223,23 +227,31 @@ TPacketizerUnit::TPacketizerUnit(TList *slaves, Long64_t num, TList *input,
 
    fWrkStats = new TMap;
    fWrkStats->SetOwner(kFALSE);
+   fWrkExcluded = 0;
 
    TSlave *slave;
    TIter si(slaves);
-   while ((slave = (TSlave*) si.Next()))
-      fWrkStats->Add(slave, new TSlaveStat(slave, input));
+   while ((slave = (TSlave*) si.Next())) {
+      if (slave->GetParallel() > 0) {
+         fWrkStats->Add(slave, new TSlaveStat(slave, input));
+      } else {
+         if (!fWrkExcluded) {
+            fWrkExcluded = new TList;
+            fWrkExcluded->SetOwner(kFALSE);
+         }
+         PDB(kPacketizer,2)
+            Info("TPacketizerUnit", "node '%s' has NO active worker: excluded from work distribution", slave->GetOrdinal());
+         fWrkExcluded->Add(slave);
+      }
+   }
 
-   fTotalEntries = num;
+   fTotalEntries = 0;
    fNumPerWorker = -1;
-   if (fixednum == 1 && fWrkStats->GetSize() > 0) {
-      // Approximate number: the exact number is determined in GetNextPacket
-      fNumPerWorker = fTotalEntries / fWrkStats->GetSize();
-      if (fNumPerWorker == 0) fNumPerWorker = 1;
-   }
+   if (num > 0 && AssignWork(0,0,num) != 0)
+      Warning("TPacketizerUnit", "some problems assigning work");
 
    // Save the config parameters in the dedicated list so that they will be saved
    // in the outputlist and therefore in the relevant TQueryResult
-   fConfigParams->Add(new TParameter<Long64_t>("PROOF_PacketizerFixedNum", fNumPerWorker));
    fConfigParams->Add(new TParameter<Float_t>("PROOF_PacketizerCalibFrac", fCalibFrac));
 
    fStopwatch->Start();
@@ -247,6 +259,41 @@ TPacketizerUnit::TPacketizerUnit(TList *slaves, Long64_t num, TList *input,
 }
 
 //______________________________________________________________________________
+Int_t TPacketizerUnit::AssignWork(TDSet *, Long64_t, Long64_t num)
+{
+   // Assign work to be done to this packetizer
+
+   if (num < 0) {
+      Error("AssignWork", "assigned a negative number (%lld) of cycles - protocol error?", num);
+      return -1;
+   }
+
+   fTotalEntries += num;
+   PDB(kPacketizer,1)
+      Info("AssignWork", "assigned %lld additional cycles (new total: %lld)", num, fTotalEntries);
+
+   // Update fixed number counter
+   if (fFixedNum && fWrkStats->GetSize() > 0) {
+      // Approximate number: the exact number is determined in GetNextPacket
+      fNumPerWorker = fTotalEntries / fWrkStats->GetSize();
+      if (fNumPerWorker == 0) fNumPerWorker = 1;
+   }
+
+   // Update/Save the config parameters in the dedicated list so that they will be saved
+   // in the outputlist and therefore in the relevant TQueryResult
+   TParameter<Long64_t> *fn =
+      (TParameter<Long64_t> *) fConfigParams->FindObject("PROOF_PacketizerFixedNum");
+   if (fn) {
+      fn->SetVal(fNumPerWorker);
+   } else {
+      fConfigParams->Add(new TParameter<Long64_t>("PROOF_PacketizerFixedNum", fNumPerWorker));
+   }
+
+   // Done
+   return 0;
+}
+
+//______________________________________________________________________________
 TPacketizerUnit::~TPacketizerUnit()
 {
    // Destructor.
@@ -254,6 +301,7 @@ TPacketizerUnit::~TPacketizerUnit()
    if (fWrkStats)
       fWrkStats->DeleteValues();
    SafeDelete(fWrkStats);
+   SafeDelete(fWrkExcluded);
    SafeDelete(fPackets);
    SafeDelete(fStopwatch);
 }
@@ -304,7 +352,15 @@ TDSetElement *TPacketizerUnit::GetNextPacket(TSlave *sl, TMessage *r)
 
    // Find slave
    TSlaveStat *slstat = (TSlaveStat*) fWrkStats->GetValue(sl);
-   R__ASSERT(slstat != 0);
+   if (!slstat) {
+      // If the worker is none of the known lists, we issue a warning
+      if (!fWrkExcluded->FindObject(sl)) {
+         Warning("GetNextPacket", "Received a packet request from an unknown slave: %s:%s",
+                                  sl->GetName(), sl->GetOrdinal());
+      }
+      // Just return, this worker node is not active
+      return 0;
+   }
 
    PDB(kPacketizer,2)
       Info("GetNextPacket","worker-%s: fAssigned %lld\t", sl->GetOrdinal(), fAssigned);
@@ -324,7 +380,7 @@ TDSetElement *TPacketizerUnit::GetNextPacket(TSlave *sl, TMessage *r)
       // Calculate the progress made in the last packet
       TProofProgressStatus *progress = 0;
       if (status) {
-         // upadte the worker status
+         // update the worker status
          numev = status->GetEntries() - slstat->GetEntriesProcessed();
          progress = slstat->AddProcessed(status);
          if (progress) {
@@ -375,9 +431,24 @@ TDSetElement *TPacketizerUnit::GetNextPacket(TSlave *sl, TMessage *r)
    }
 
    if (fAssigned == fTotalEntries) {
-      // Send last timer message
-      HandleTimer(0);
-      return 0;
+      Bool_t done = kTRUE;
+      // If we are on a submaster, check if there is something else to do
+      if (gProofServ && gProofServ->IsMaster() && !gProofServ->IsTopMaster()) {
+         TDSetElement *nxe = gProofServ->GetNextPacket();
+         if (nxe) {
+            if (AssignWork(0,0,nxe->GetNum()) == 0) {
+               if (fAssigned < fTotalEntries) done = kFALSE;
+            } else {
+               Error("GetNextPacket", "problems assigning additional work: stop");
+            }
+            SafeDelete(nxe);
+         }
+      }
+      if (done) {
+         // Send last timer message
+         HandleTimer(0);
+         return 0;
+      }
    }
 
    if (fStop) {
@@ -431,10 +502,10 @@ TDSetElement *TPacketizerUnit::GetNextPacket(TSlave *sl, TMessage *r)
                if (wrkStat->fRate > 0) {
                   nrm++;
                   sumRate += wrkStat->fRate;
-                  PDB(kPacketizer,3)
-                     Info("GetNextPacket", "%d: worker-%s: rate %lf /s (sum: %lf /s)",
-                                           nrm, tmpWrk->GetOrdinal(), wrkStat->fRate, sumRate);
                }
+               PDB(kPacketizer,3)
+                  Info("GetNextPacket", "%d: worker-%s: rate %lf /s (sum: %lf /s)",
+                                          nrm, tmpWrk->GetOrdinal(), wrkStat->fRate, sumRate);
             } else {
                Warning("GetNextPacket", "dynamic_cast<TSlaveStat *> failing on value for '%s (%s)'! Skipping",
                                         tmpWrk->GetName(), tmpWrk->GetOrdinal());
@@ -512,3 +583,32 @@ TDSetElement *TPacketizerUnit::GetNextPacket(TSlave *sl, TMessage *r)
 
    return elem;
 }
+
+//______________________________________________________________________________
+Int_t TPacketizerUnit::AddWorkers(TList *workers)
+{
+   // Adds new workers. Returns the number of workers added, or -1 on failure.
+
+   if (!workers) {
+      Error("AddWorkers", "Null list of new workers!");
+      return -1;
+   }
+
+   Int_t curNumOfWrks = fWrkStats->GetEntries();
+
+   TSlave *sl;
+   TIter next(workers);
+   while (( sl = dynamic_cast<TSlave*>(next()) ))
+      fWrkStats->Add(sl, new TSlaveStat(sl, fInput));
+
+   fNumPerWorker = -1;
+   if (fFixedNum && fWrkStats->GetSize() > 0) {
+      // Approximate number: the exact number is determined in GetNextPacket
+      fNumPerWorker = (fNumPerWorker * curNumOfWrks) / fWrkStats->GetSize();
+      if (fNumPerWorker == 0) fNumPerWorker = 1;
+   }
+
+   fConfigParams->Add(new TParameter<Long64_t>("PROOF_PacketizerFixedNum", fNumPerWorker));
+
+   return fWrkStats->GetEntries();
+}
diff --git a/proof/proofplayer/src/TProofDraw.cxx b/proof/proofplayer/src/TProofDraw.cxx
index 3cbb5ee..071b954 100644
--- a/proof/proofplayer/src/TProofDraw.cxx
+++ b/proof/proofplayer/src/TProofDraw.cxx
@@ -159,7 +159,10 @@ Bool_t TProofDraw::Notify()
          return kFALSE;
    }
    if (!fStatus->IsOk()) return kFALSE;
-   if (!fManager) return kFALSE;
+   if (!fManager) {
+      fAbort = TSelector::kAbortProcess;
+      return kFALSE;
+   }
    fManager->UpdateFormulaLeaves();
    return kTRUE;
 }
diff --git a/proof/proofplayer/src/TProofPlayer.cxx b/proof/proofplayer/src/TProofPlayer.cxx
index 1a9b037..94197fa 100644
--- a/proof/proofplayer/src/TProofPlayer.cxx
+++ b/proof/proofplayer/src/TProofPlayer.cxx
@@ -75,6 +75,7 @@
 #include "TVirtualMonitoring.h"
 #include "TParameter.h"
 #include "TOutputListSelectorDataMap.h"
+#include "TStopwatch.h"
 
 // Timeout exception
 #define kPEX_STOPPED  1001
@@ -135,6 +136,33 @@ Bool_t TDispatchTimer::Notify()
 }
 
 //
+// Special timer to notify reach of max packet proc time
+//______________________________________________________________________________
+class TProctimeTimer : public TTimer {
+private:
+   TProofPlayer    *fPlayer;
+
+public:
+   TProctimeTimer(TProofPlayer *p, Long_t to) : TTimer(to, kFALSE), fPlayer(p) { }
+
+   Bool_t Notify();
+};
+//______________________________________________________________________________
+Bool_t TProctimeTimer::Notify()
+{
+   // Handle expiration of the timer associated with dispatching pending
+   // events while processing. We must act as fast as possible here, so
+   // we just set a flag submitting a request for dispatching pending events
+
+   if (gDebug > 0) printf("TProctimeTimer::Notify: called!\n");
+
+   fPlayer->SetBit(TProofPlayer::kMaxProcTimeReached);
+
+   // One shot only
+   return kTRUE;
+}
+
+//
 // Special timer to handle stop/abort request via exception raising
 //______________________________________________________________________________
 class TStopTimer : public TTimer {
@@ -199,6 +227,7 @@ TProofPlayer::TProofPlayer(TProof *)
      fTotalEvents(0), fReadBytesRun(0), fReadCallsRun(0), fProcessedRun(0),
      fQueryResults(0), fQuery(0), fPreviousQuery(0), fDrawQueries(0),
      fMaxDrawQueries(1), fStopTimer(0), fStopTimerMtx(0), fDispatchTimer(0),
+     fProcTimeTimer(0), fProcTime(0),
      fOutputFile(0),
      fSaveMemThreshold(-1), fSavePartialResults(kFALSE), fSaveResultsPerPacket(kFALSE)
 {
@@ -207,7 +236,10 @@ TProofPlayer::TProofPlayer(TProof *)
    fInput         = new TList;
    fExitStatus    = kFinished;
    fProgressStatus = new TProofProgressStatus();
+   ResetBit(TProofPlayer::kDispatchOneEvent);
    ResetBit(TProofPlayer::kIsProcessing);
+   ResetBit(TProofPlayer::kMaxProcTimeReached);
+   ResetBit(TProofPlayer::kMaxProcTimeExtended);
 
    static Bool_t initLimitsFinder = kFALSE;
    if (!initLimitsFinder && gProofServ && !gProofServ->IsMaster()) {
@@ -230,6 +262,8 @@ TProofPlayer::~TProofPlayer()
    SafeDelete(fEvIter);
    SafeDelete(fQueryResults);
    SafeDelete(fDispatchTimer);
+   SafeDelete(fProcTimeTimer);
+   SafeDelete(fProcTime);
    SafeDelete(fStopTimer);
 }
 
@@ -1167,6 +1201,8 @@ Long64_t TProofPlayer::Process(TDSet *dset, const char *selector_file,
       Long64_t fst = -1, num;
       TEntryList *enl = 0;
       TEventList *evl = 0;
+      Long_t maxproctime = -1;
+      Bool_t newrun = kFALSE;
       while ((fEvIter->GetNextPacket(fst, num, &enl, &evl) != -1) &&
               !fSelStatus->TestBit(TStatus::kNotOk) &&
               fSelector->GetAbort() == TSelector::kContinue) {
@@ -1199,9 +1235,58 @@ Long64_t TProofPlayer::Process(TDSet *dset, const char *selector_file,
                }
                TProofServ::SetLastMsg(lastMsg);
             }
+            // Set the max proc time, if any
+            if (dset->Current()->GetMaxProcTime() >= 0.)
+               maxproctime = (Long_t) (1000 * dset->Current()->GetMaxProcTime());
+            newrun = (dset->Current()->TestBit(TDSetElement::kNewPacket)) ? kTRUE : kFALSE;
          }
 
-         while (num--) {
+         ResetBit(TProofPlayer::kMaxProcTimeReached);
+         ResetBit(TProofPlayer::kMaxProcTimeExtended);
+         // Setup packet proc time measurement
+         if (maxproctime > 0) {
+            if (!fProcTimeTimer) fProcTimeTimer = new TProctimeTimer(this, maxproctime);
+            fProcTimeTimer->Start(maxproctime, kTRUE); // One shot
+            if (!fProcTime) fProcTime = new TStopwatch();
+            fProcTime->Reset();                        // Reset counters
+         }
+         Long64_t refnum = num;
+         if (refnum < 0 && maxproctime <= 0) {
+            wmsg.Form("neither entries nor max proc time specified:"
+                      " risk of infinite loop: processing aborted");
+            Error("Process", "%s", wmsg.Data());
+            if (gProofServ) {
+               wmsg.Insert(0, TString::Format("ERROR:%s, entry:%lld, ",
+                                             gProofServ->GetOrdinal(), fProcessedRun));
+               gProofServ->SendAsynMessage(wmsg.Data());
+            }
+            fExitStatus = kAborted;
+            ResetBit(TProofPlayer::kIsProcessing);
+            break;
+         }
+         while (refnum < 0 || num--) {
+
+            // Did we use all our time? 
+            if (TestBit(TProofPlayer::kMaxProcTimeReached)) {
+               fProcTime->Stop();
+               if (!newrun && !TestBit(TProofPlayer::kMaxProcTimeExtended) && refnum > 0) {
+                  // How much are we left with?
+                  Float_t xleft = (refnum > num) ? (Float_t) num / (Float_t) (refnum) : 1.;
+                  if (xleft < 0.2) {
+                     // Give another try, 1.5 times the remaining measured expected time
+                     Long_t mpt = (Long_t) (1500 * num / ((Double_t)(refnum - num) / fProcTime->RealTime())); 
+                     SetBit(TProofPlayer::kMaxProcTimeExtended);
+                     fProcTimeTimer->Start(mpt, kTRUE); // One shot
+                     ResetBit(TProofPlayer::kMaxProcTimeReached);
+                  }
+               }
+               if (TestBit(TProofPlayer::kMaxProcTimeReached)) {
+                  Info("Process", "max proc time reached (%ld msecs): packet processing stopped:\n%s",
+                                  maxproctime, lastMsg.Data());
+                 
+                  break;
+               }
+            }
             
             if (!(!fSelStatus->TestBit(TStatus::kNotOk) &&
                    fSelector->GetAbort() == TSelector::kContinue)) break;
@@ -1418,6 +1503,14 @@ Long64_t TProofPlayer::Process(TDSet *dset, TSelector *selector,
 }
 
 //______________________________________________________________________________
+Bool_t TProofPlayer::JoinProcess(TList *)
+{
+   // Not implemented: meaningful only in the remote player. Returns kFALSE.
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
 Bool_t TProofPlayer::CheckMemUsage(Long64_t &mfreq, Bool_t &w80r,
                                    Bool_t &w80v, TString &wmsg)
 {
@@ -1786,6 +1879,9 @@ TProofPlayerRemote::~TProofPlayerRemote()
    // Objects stored in maps are already deleted when merging the feedback
    SafeDelete(fFeedbackLists);
    SafeDelete(fPacketizer);
+
+   if (fProcessMessage)
+      SafeDelete(fProcessMessage);
 }
 
 //______________________________________________________________________________
@@ -2055,7 +2151,8 @@ Long64_t TProofPlayerRemote::Process(TDSet *dset, const char *selector_file,
    // The return value is -1 in case of an error and TSelector::GetStatus() in
    // in case of success.
 
-   PDB(kGlobal,1) Info("Process","Enter");
+   PDB(kGlobal,1) Info("Process", "Enter");
+
    fDSet = dset;
    fExitStatus = kFinished;
 
@@ -2081,6 +2178,7 @@ Long64_t TProofPlayerRemote::Process(TDSet *dset, const char *selector_file,
 
    // Define filename
    TString fn;
+   fSelectorFileName = selector_file;
 
    if (fCreateSelObj) {
       if(!SendSelector(selector_file)) return -1;
@@ -2240,7 +2338,10 @@ Long64_t TProofPlayerRemote::Process(TDSet *dset, const char *selector_file,
    TEventList *evl = (!fProof->IsMaster() && !enl) ? dynamic_cast<TEventList *>(set->GetEntryList())
                                            : (TEventList *)0;
    if (fProof->fProtocol > 14) {
+      if (fProcessMessage) delete fProcessMessage;
+      fProcessMessage = new TMessage(kPROOF_PROCESS);
       mesg << set << fn << fInput << opt << num << fst << evl << sync << enl;
+      (*fProcessMessage) << set << fn << fInput << opt << num << fst << evl << sync << enl;
    } else {
       mesg << set << fn << fInput << opt << num << fst << evl << sync;
       if (enl)
@@ -2383,6 +2484,55 @@ Long64_t TProofPlayerRemote::Process(TDSet *dset, TSelector *selector,
 
    return Process(dset, selector->ClassName(), option, nentries, first);
 }
+
+//______________________________________________________________________________
+Bool_t TProofPlayerRemote::JoinProcess(TList *workers)
+{
+   // Prepares the given list of new workers to join a progressing process.
+   // Returns kTRUE on success, kFALSE otherwise.
+
+   if (!fProcessMessage || !fProof || !fPacketizer) {
+      Error("Process", "Should not happen: fProcessMessage=%p fProof=%p fPacketizer=%p",
+         fProcessMessage, fProof, fPacketizer);
+      return kFALSE;
+   }
+
+   if (!workers || !fProof->IsMaster()) {
+      Error("Process", "Invalid call");
+      return kFALSE;
+   }
+
+   PDB(kGlobal, 1)
+      Info("Process", "Preparing %d new worker(s) to process", workers->GetEntries());
+
+   // Sends the file associated to the TSelector, if necessary
+   if (fCreateSelObj) {
+      PDB(kGlobal, 2)
+         Info("Process", "Sending selector file %s", fSelectorFileName.Data());
+      if(!SendSelector(fSelectorFileName.Data())) {
+         Error("Process", "Problems in sending selector file %s", fSelectorFileName.Data());
+         return kFALSE;
+      }
+   }
+
+   PDB(kGlobal, 2)
+      Info("Process", "Adding new workers to the packetizer");
+   if (fPacketizer->AddWorkers(workers) == -1) {
+      Error("Process", "Cannot add new workers to the packetizer!");
+      return kFALSE;  // TODO: make new wrks inactive
+   }
+
+   PDB(kGlobal, 2)
+      Info("Process", "Broadcasting process message to new workers");
+   fProof->Broadcast(*fProcessMessage, workers);
+
+   // Don't call Collect(): we came here from a global Collect() already which
+   // will take care of new workers as well
+
+   return kTRUE;
+
+}
+
 //______________________________________________________________________________
 Bool_t TProofPlayerRemote::MergeOutputFiles()
 {
diff --git a/proof/proofplayer/src/TVirtualPacketizer.cxx b/proof/proofplayer/src/TVirtualPacketizer.cxx
index b93bf1c..5a2529d 100644
--- a/proof/proofplayer/src/TVirtualPacketizer.cxx
+++ b/proof/proofplayer/src/TVirtualPacketizer.cxx
@@ -434,3 +434,14 @@ void TVirtualPacketizer::SetInitTime()
          Info("SetInitTime","fInitTime set to %f s", fInitTime);
    }
 }
+
+//______________________________________________________________________________
+Int_t TVirtualPacketizer::AddWorkers(TList *)
+{
+   // Adds new workers. Must be implemented by each real packetizer properly.
+   // Returns the number of workers added, or -1 on failure.
+
+   Warning("AddWorkers", "Not implemented for this packetizer");
+
+   return -1;
+}
diff --git a/proof/proofx/src/TXProofMgr.cxx b/proof/proofx/src/TXProofMgr.cxx
index 22d1f90..cc4f703 100644
--- a/proof/proofx/src/TXProofMgr.cxx
+++ b/proof/proofx/src/TXProofMgr.cxx
@@ -685,25 +685,37 @@ TObjString *TXProofMgr::ReadBuffer(const char *fin, Long64_t ofs, Int_t len)
 //______________________________________________________________________________
 TObjString *TXProofMgr::ReadBuffer(const char *fin, const char *pattern)
 {
-   // Read, via the coordinator, lines containing 'pattern' in 'file'.
-   // Returns a TObjString with the content or 0, in case of failure
+   // Read, via the coordinator, 'fin' filtered. If 'pattern' starts with '|',
+   // it represents a command filtering the output. Elsewhere, it is a grep
+   // pattern. Returns a TObjString with the content or 0 in case of failure
 
    // Nothing to do if not in contact with proofserv
    if (!IsValid()) {
-      Warning("ReadBuffer","invalid TXProofMgr - do nothing");
+      Warning("ReadBuffer", "invalid TXProofMgr - do nothing");
       return (TObjString *)0;
    }
 
+   const char *ptr;
+   Int_t type;  // 1 = grep, 2 = grep -v, 3 = pipe through cmd
+   if (*pattern == '|') {
+      ptr = &pattern[1];  // strip first char if it is a command
+      type = 3;
+   }
+   else {
+      ptr = pattern;
+      type = 1;
+   }
+
    // Prepare the buffer
-   Int_t plen = strlen(pattern);
+   Int_t plen = strlen(ptr);
    Int_t lfi = strlen(fin);
    char *buf = new char[lfi + plen + 1];
    memcpy(buf, fin, lfi);
-   memcpy(buf+lfi, pattern, plen);
+   memcpy(buf+lfi, ptr, plen);
    buf[lfi+plen] = 0;
 
    // Send the request
-   return fSocket->SendCoordinator(kReadBuffer, buf, plen, 0, 1);
+   return fSocket->SendCoordinator(kReadBuffer, buf, plen, 0, type);
 }
 
 //______________________________________________________________________________
diff --git a/proof/proofx/src/TXProofServ.cxx b/proof/proofx/src/TXProofServ.cxx
index 4234e95..4bc1316 100644
--- a/proof/proofx/src/TXProofServ.cxx
+++ b/proof/proofx/src/TXProofServ.cxx
@@ -765,11 +765,10 @@ TProofServ::EQueryAction TXProofServ::GetWorkers(TList *workers,
 
    TProofServ::EQueryAction rc = kQueryStop;
 
-   // If user config files are enabled, check them first
+   // User config files, when enabled, override cluster-wide configuration
    if (gEnv->GetValue("ProofServ.UseUserCfg", 0) != 0) {
       Int_t pc = 1;
-      if ((rc = TProofServ::GetWorkers(workers, pc)) == kQueryOK)
-         return rc;
+      return TProofServ::GetWorkers(workers, pc);
    }
 
    // seqnum of the query for which we call getworkers
@@ -807,8 +806,8 @@ TProofServ::EQueryAction TXProofServ::GetWorkers(TList *workers,
          }
          if (s.IsDigit()) {
             nwrks = s.Atoi();
-            if (nwrks > 0) {
-               // Notify
+            if (!dynamicStartup && (nwrks > 0)) {
+               // Notify, except in dynamic workers mode to avoid flooding
                TString msg;
                if (pernode) {
                   msg.Form("+++ Starting max %d workers per node following the setting of PROOF_NWORKERS", nwrks);
diff --git a/roofit/CMakeLists.txt b/roofit/CMakeLists.txt
index a921698..4de9437 100644
--- a/roofit/CMakeLists.txt
+++ b/roofit/CMakeLists.txt
@@ -8,6 +8,7 @@ endif()
 ROOT_USE_PACKAGE(math/mathcore)
 ROOT_USE_PACKAGE(math/foam)
 ROOT_USE_PACKAGE(math/minuit)
+ROOT_USE_PACKAGE(math/smatrix)
 ROOT_USE_PACKAGE(proof/proof)
 
 if(mathmore OR ROOT_mathmore_FOUND)
diff --git a/roofit/histfactory/inc/LinkDef.h b/roofit/histfactory/inc/LinkDef.h
index b9203f3..27aada9 100644
--- a/roofit/histfactory/inc/LinkDef.h
+++ b/roofit/histfactory/inc/LinkDef.h
@@ -5,6 +5,7 @@
 #pragma link off all classes;
 #pragma link off all functions;
 
+
 #pragma link C++ namespace RooStats;
 #pragma link C++ namespace RooStats::HistFactory;
 
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/Channel.h b/roofit/histfactory/inc/RooStats/HistFactory/Channel.h
index d536810..2e781bd 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/Channel.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/Channel.h
@@ -31,32 +31,42 @@ public:
 
   Channel();
   Channel(std::string Name, std::string InputFile="");
-  
 
+  // set name of channel
   void SetName( const std::string& Name ) { fName = Name; }
+  // get name of channel
   std::string GetName() { return fName; }
-
+  // set name of input file containing histograms
   void SetInputFile( const std::string& file ) { fInputFile = file; }
+  // get name of input file
   std::string GetInputFile() { return fInputFile; }
-
+  // set path for histograms in input file
   void SetHistoPath( const std::string& file ) { fHistoPath = file; }
+  // get path to histograms in input file
   std::string GetHistoPath() { return fHistoPath; }
 
+  // set data object
   void SetData( const RooStats::HistFactory::Data& data ) { fData = data; }
   void SetData( std::string HistoName, std::string InputFile, std::string HistoPath="" );
   void SetData( double Val );
   void SetData( TH1* hData );
+  // get data object
   RooStats::HistFactory::Data& GetData() { return fData; }
 
-  void AddAdditionalData( const RooStats::HistFactory::Data& data ) { fAdditionalData.push_back(data); } 
+  // add additional data object
+  void AddAdditionalData( const RooStats::HistFactory::Data& data ) { fAdditionalData.push_back(data); }
+  // retrieve vector of additional data objects
   std::vector<RooStats::HistFactory::Data>& GetAdditionalData() { return fAdditionalData; }
 
   void SetStatErrorConfig( double RelErrorThreshold, Constraint::Type ConstraintType );
   void SetStatErrorConfig( double RelErrorThreshold, std::string ConstraintType );
+  // define treatment of statistical uncertainties
   void SetStatErrorConfig( RooStats::HistFactory::StatErrorConfig Config ) { fStatErrorConfig = Config; }
+  // get information about threshold for statistical uncertainties and constraint term
   HistFactory::StatErrorConfig& GetStatErrorConfig() { return fStatErrorConfig; }
 
   void AddSample( RooStats::HistFactory::Sample sample );
+  // get vector of samples for this channel
   std::vector< RooStats::HistFactory::Sample >& GetSamples() { return fSamples; }
 
   void Print(std::ostream& = std::cout);  
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/Data.h b/roofit/histfactory/inc/RooStats/HistFactory/Data.h
index 6eab0c7..6cfb488 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/Data.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/Data.h
@@ -41,8 +41,8 @@ public:
   void SetHistoPath(const std::string& HistoPath) { fHistoPath = HistoPath; }
   std::string GetHistoPath() { return fHistoPath; }
 
-
   void Print(std::ostream& = std::cout);
+  void PrintXML( std::ostream& );
   void writeToFile( std::string FileName, std::string DirName );
 
   TH1* GetHisto();
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/HistFactoryNavigation.h b/roofit/histfactory/inc/RooStats/HistFactory/HistFactoryNavigation.h
index 65d9778..806eaeb 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/HistFactoryNavigation.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/HistFactoryNavigation.h
@@ -1,24 +1,13 @@
 
 #include <map>
 
-#include "TFile.h"
 #include "TH1.h"
-#include "TROOT.h"
-#include "TMath.h"
-
-#include "TCanvas.h"
 #include "THStack.h"
-#include "TLegend.h"
 
 #include "RooDataSet.h"
 #include "RooRealVar.h"
-#include "RooWorkspace.h"
-#include "RooSimultaneous.h"
-#include "RooCategory.h"
 #include "RooProduct.h"
-#include "RooRealSumPdf.h"
 #include "RooStats/HistFactory/Measurement.h"
-
 #include "RooStats/ModelConfig.h"
 
 
@@ -60,7 +49,7 @@ namespace RooStats {
       void PrintSampleComponents(const std::string& channel, const std::string& sample);
 
       // Print a "HistFactory style" RooDataSet in a readable way
-      static void PrintDataSet(RooDataSet* data, const std::string& channel="", int max=-1);
+      void PrintDataSet(RooDataSet* data, const std::string& channel="");
 
       // Print the model and the data, comparing channel by channel
       void PrintModelAndData(RooDataSet* data);
@@ -78,6 +67,15 @@ namespace RooStats {
       // Get the total channel histogram for this channel
       TH1* GetChannelHist(const std::string& channel, const std::string& name="");
 
+      // Get a histogram from the dataset for this channel
+      TH1* GetDataHist(RooDataSet* data, const std::string& channel, const std::string& name="");
+
+      // Get a stack of all samples in a channel
+      THStack* GetChannelStack(const std::string& channel, const std::string& name="");
+
+      // Draw a stack of the channel, and include data if the pointer is supplied
+      void DrawChannel(const std::string& channel, RooDataSet* data=NULL);
+
       // Get the RooAbsReal function for a given sample in a given channel
       RooAbsReal* SampleFunction(const std::string& channel, const std::string& sample);
 
@@ -95,20 +93,24 @@ namespace RooStats {
       // Will do minimial checking to make sure the replacement makes sense
       void ReplaceNode(const std::string& ToReplace, RooAbsArg* ReplaceWith);
 
-
       // Set any RooRealVar's const (or not const) if they match
       // the supplied regular expression
       void SetConstant(const std::string& regExpr=".*", bool constant=true);
 
-      void SetNumBinsToPrint(int num) { _numBinsToPrint = num; }
-      int GetNumBinsToPrint() const { return _numBinsToPrint; }
+      void SetMaxBinToPrint(int max) { _maxBinToPrint = max; }
+      int GetMaxBinToPrint() const { return _maxBinToPrint; }
+
+      void SetMinBinToPrint(int min) { _minBinToPrint = min; }
+      int GetMinBinToPrint() const { return _minBinToPrint; }
 
       // Get the model for this channel
       RooAbsPdf* GetModel() const { return fModel; }
 
       //
       RooAbsPdf* GetChannelPdf(const std::string& channel);
-      
+
+
+      std::vector< std::string > GetChannelSampleList(const std::string& channel);
 
       // Return the RooRealVar by the same name used in the model
       // If not found, return NULL
@@ -133,6 +135,9 @@ namespace RooStats {
 
     protected:
 
+      // Set the title and bin widths
+      void SetPrintWidths(const std::string& channel);
+
       // Fetch the node information for the pdf in question, and
       // save it in the varous collections in this class
       void _GetNodes(ModelConfig* mc);
@@ -140,6 +145,7 @@ namespace RooStats {
 
       // Print a histogram's contents to the screen
       // void PrettyPrintHistogram(TH1* hist);
+      void PrintMultiDimHist(TH1* hist, int bin_print_width);
 
       // Make a histogram from a funciton
       // Edit so it can take a RooArgSet of parameters
@@ -156,7 +162,11 @@ namespace RooStats {
       // The observables
       RooArgSet* fObservables;
 
-      int _numBinsToPrint;
+      int _minBinToPrint;
+      int _maxBinToPrint;
+
+      int _label_print_width;
+      int _bin_print_width;
 
       // The list of channels
       std::vector<std::string> fChannelNameVec;
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/MakeModelAndMeasurementsFast.h b/roofit/histfactory/inc/RooStats/HistFactory/MakeModelAndMeasurementsFast.h
index ddcbd79..c4ae64e 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/MakeModelAndMeasurementsFast.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/MakeModelAndMeasurementsFast.h
@@ -13,11 +13,12 @@
 #include "RooPlot.h"
 #include "TFile.h"
 
-void fastDriver(std::string input);
+
 
 namespace RooStats{
   namespace HistFactory{
 
+    //void fastDriver(std::string input);
 
     RooWorkspace* MakeModelAndMeasurementFast( RooStats::HistFactory::Measurement& measurement );
     //RooWorkspace* MakeModelFast( RooStats::HistFactory::Measurement& measurement );
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/Measurement.h b/roofit/histfactory/inc/RooStats/HistFactory/Measurement.h
index 19253bc..27b6816 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/Measurement.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/Measurement.h
@@ -36,43 +36,57 @@ public:
   //  Measurement( const Measurement& other ); // Copy
   Measurement(const char* Name, const char* Title="");
 
-  //  std::string Name;
-
-
+  //  set output prefix
   void SetOutputFilePrefix( const std::string& prefix ) { fOutputFilePrefix = prefix; }
+  // retrieve prefix for output files
   std::string GetOutputFilePrefix() { return fOutputFilePrefix; }
 
+  // insert PoI at beginning of vector of PoIs
   void SetPOI( const std::string& POI ) { fPOI.insert( fPOI.begin(), POI ); }
+  // append parameter to vector of PoIs
   void AddPOI( const std::string& POI ) { fPOI.push_back(POI); }
+  // get name of PoI at given index
   std::string GetPOI(unsigned int i=0) { return fPOI.at(i); }
+  // get vector of PoI names
   std::vector<std::string>& GetPOIList() { return fPOI; }
 
 
   // Add a parameter to be set as constant
   // (Similar to ParamSetting method below)
   void AddConstantParam( const std::string& param );
+  // empty vector of constant parameters
   void ClearConstantParams() { fConstantParams.clear(); }
+  // get vector of all constant parameters
   std::vector< std::string >& GetConstantParams() { return fConstantParams; }
 
   // Set a parameter to a specific value
   // (And optionally fix it)
   void SetParamValue( const std::string& param, double value);
+  // get map: parameter name <--> parameter value
   std::map<std::string, double>& GetParamValues() { return fParamValues; }
+  // clear map of parameter values
   void ClearParamValues() { fParamValues.clear(); }
 
   void AddPreprocessFunction( std::string name, std::string expression, std::string dependencies );
+  // add a preprocess function object
   void AddFunctionObject( const RooStats::HistFactory::PreprocessFunction function) { fFunctionObjects.push_back( function ); }
   void SetFunctionObjects( std::vector< RooStats::HistFactory::PreprocessFunction > objects ) { fFunctionObjects = objects; }
+  // get vector of defined function objects
   std::vector< RooStats::HistFactory::PreprocessFunction >& GetFunctionObjects() { return fFunctionObjects; }
   std::vector< std::string > GetPreprocessFunctions();
 
-  // Get and set Asimov Datasets
+  // get vector of defined Asimov Datasets
   std::vector< RooStats::HistFactory::Asimov >& GetAsimovDatasets() { return fAsimovDatasets; }
+  // add an Asimov Dataset
   void AddAsimovDataset( RooStats::HistFactory::Asimov dataset ) { fAsimovDatasets.push_back(dataset); }
 
+  // set integrated luminosity used to normalise histograms (if NormalizeByTheory is true for this sample)
   void SetLumi(double Lumi ) { fLumi = Lumi; }
+  // set relative uncertainty on luminosity
   void SetLumiRelErr( double RelErr ) { fLumiRelErr = RelErr; }
+  // retrieve integrated luminosity
   double GetLumi() { return fLumi; }
+  // retrieve relative uncertainty on luminosity
   double GetLumiRelErr() { return fLumiRelErr; }
   
   void SetBinLow( int BinLow ) { fBinLow = BinLow; }
@@ -80,6 +94,7 @@ public:
   int GetBinLow() { return fBinLow; }
   int GetBinHigh() { return fBinHigh; } 
 
+  // do not produce any plots or tables, just save the model
   void SetExportOnly( bool ExportOnly ) { fExportOnly = ExportOnly; }
   bool GetExportOnly() { return fExportOnly; }
 
@@ -89,6 +104,7 @@ public:
 
   std::vector< RooStats::HistFactory::Channel >& GetChannels() { return fChannels; }
   RooStats::HistFactory::Channel& GetChannel( std::string );
+  // add a completely configured channel
   void AddChannel( RooStats::HistFactory::Channel chan ) { fChannels.push_back( chan ); }
 
   bool HasChannel( std::string );
@@ -135,7 +151,6 @@ private:
   // List of Asimov datasets to generate
   std::vector< RooStats::HistFactory::Asimov > fAsimovDatasets;
 
-
   // List of Alternate constraint terms
   std::map< std::string, double > fGammaSyst;
   std::map< std::string, double > fUniformSyst;
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/ParamHistFunc.h b/roofit/histfactory/inc/RooStats/HistFactory/ParamHistFunc.h
index a7101da..55c78f0 100755
--- a/roofit/histfactory/inc/RooStats/HistFactory/ParamHistFunc.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/ParamHistFunc.h
@@ -31,22 +31,19 @@ public:
   ParamHistFunc() ;
   ParamHistFunc(const char *name, const char *title, const RooArgList& vars, const RooArgList& paramSet );
   ParamHistFunc(const char *name, const char *title, const RooArgList& vars, const RooArgList& paramSet, const TH1* hist );
-  // Not yet fully implemented:
-  //ParamHistFunc(const char *name, const char *title, const RooRealVar& var, const RooArgList& paramSet, const RooAbsReal& nominal );
   virtual ~ParamHistFunc() ;
 
-
   ParamHistFunc(const ParamHistFunc& other, const char* name = 0);
   virtual TObject* clone(const char* newname) const { return new ParamHistFunc(*this, newname); }
 
-  //  void printMetaArgs(std::ostream& os) const ;
-
   const RooArgList& paramList() const { return _paramSet ; }
 
-
   Int_t numBins() const { return _dataSet.numEntries(); } // Number of bins (called numEntries in RooDataHist)
 
   void setParamConst( Int_t, Bool_t=kTRUE );
+  void setConstant(bool constant);
+
+  void setShape(TH1* shape);
 
   RooRealVar& getParameter() const ;
   RooRealVar& getParameter( Int_t masterIdx ) const ;
@@ -61,8 +58,6 @@ public:
   Int_t getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, const RooArgSet* normSet,const char* rangeName=0) const ;
   Double_t analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName=0) const ;
 
-
-
   static RooArgList createParamSet(RooWorkspace& w, const std::string&, const RooArgList& Vars);
   static RooArgList createParamSet(RooWorkspace& w, const std::string&, const RooArgList& Vars, Double_t, Double_t);
   static RooArgList createParamSet(const std::string&, Int_t, Double_t, Double_t);
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/PreprocessFunction.h b/roofit/histfactory/inc/RooStats/HistFactory/PreprocessFunction.h
index 483113b..17f5c3e 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/PreprocessFunction.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/PreprocessFunction.h
@@ -19,6 +19,7 @@ namespace HistFactory {
 			   
 
     void Print(std::ostream& = std::cout);  
+    void PrintXML(std::ostream& );  
 
     void SetName( const std::string& Name) { fName = Name; }
     std::string GetName() { return fName; }
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/Sample.h b/roofit/histfactory/inc/RooStats/HistFactory/Sample.h
index c971e2d..542f325 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/Sample.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/Sample.h
@@ -17,6 +17,7 @@
 #include <iostream>
 
 #include "TRef.h"
+class TH1;
 #include "RooStats/HistFactory/Systematics.h"
 
 namespace RooStats{
@@ -30,13 +31,14 @@ public:
   Sample();
   Sample(std::string Name);
   Sample(std::string Name, std::string HistoName, std::string InputFile, std::string HistoPath="");
-
+  ~Sample();
 
   void Print(std::ostream& = std::cout);  
   void PrintXML( std::ofstream& xml );
   void writeToFile( std::string FileName, std::string DirName );
 
   TH1* GetHisto();
+  // set histogram for this sample
   void SetHisto( TH1* histo ) { fhNominal = histo; fHistoName=histo->GetName(); }
   void SetValue( Double_t Val );
 
@@ -65,25 +67,35 @@ public:
   void AddShapeSys(    std::string Name, Constraint::Type ConstraintType, std::string HistoName, std::string HistoFile, std::string HistoPath="" );
   void AddShapeSys( const ShapeSys& Sys );
 
+  // defines whether the normalization scale with luminosity
   void SetNormalizeByTheory( bool norm ) { fNormalizeByTheory = norm; }
+  // does the normalization scale with luminosity
   bool GetNormalizeByTheory() { return fNormalizeByTheory; }
 
 
-
+  // get name of sample
   std::string GetName() { return fName; }
+  // set name of sample
   void SetName(const std::string& Name) { fName = Name; }
-  
 
+  // get input ROOT file
   std::string GetInputFile() { return fInputFile; }
+  // set input ROOT file
   void SetInputFile(const std::string& InputFile) { fInputFile = InputFile; }
 
+  // get histogram name
   std::string GetHistoName() { return fHistoName; }
+  // set histogram name
   void SetHistoName(const std::string& HistoName) { fHistoName = HistoName; }
 
+  // get histogram path
   std::string GetHistoPath() { return fHistoPath; }
+  // set histogram path
   void SetHistoPath(const std::string& HistoPath) { fHistoPath = HistoPath; }
 
+  // get name of associated channel
   std::string GetChannelName() { return fChannelName; }
+  // set name of associated channel
   void SetChannelName(const std::string& ChannelName) { fChannelName = ChannelName; }
 
 
@@ -134,6 +146,7 @@ protected:
 
   // The Nominal Shape
   TRef fhNominal;
+  TH1* fhCountingHist;
 
 };
 
diff --git a/roofit/histfactory/inc/RooStats/HistFactory/Systematics.h b/roofit/histfactory/inc/RooStats/HistFactory/Systematics.h
index a273acd..1422832 100644
--- a/roofit/histfactory/inc/RooStats/HistFactory/Systematics.h
+++ b/roofit/histfactory/inc/RooStats/HistFactory/Systematics.h
@@ -11,7 +11,6 @@
 #ifndef HISTFACTORY_SYSTEMATICS_H
 #define HISTFACTORY_SYSTEMATICS_H
 
-
 #include <string>
 #include <fstream>
 #include <iostream>
@@ -19,24 +18,33 @@
 #include "TH1.h"
 #include "TRef.h"
 
-//#include "RooStats/HistFactory/HistCollector.h"
-
 namespace RooStats{
 namespace HistFactory {
 
-
   namespace Constraint {
     enum Type{ Gaussian, Poisson };            
     std::string Name( Type type ); 
-    Type GetType( std::string Name );
+    Type GetType( const std::string& Name );
   }
 
 
+  // Base class for common functions
+  /*
+  class Systematic {
+    
+  public:
+
+    virtual void Print(std::ostream& = std::cout);
+    virtual void writeToFile(const std::string& FileName, 
+			     const std::string& Directory);
+    
+    
+  };
+  */
 
   class OverallSys {
 
   public:
-    //friend class Channel;
 
     void SetName( const std::string& Name ) { fName = Name; }
     std::string GetName() { return fName; }
@@ -47,6 +55,7 @@ namespace HistFactory {
     double GetHigh() { return fHigh; }
 
     void Print(std::ostream& = std::cout);  
+    void PrintXML(std::ostream&);
 
   protected:
     std::string fName;
@@ -59,7 +68,6 @@ namespace HistFactory {
   class NormFactor {
 
   public:
-    //friend class Channel;
 
     NormFactor();
 
@@ -78,6 +86,7 @@ namespace HistFactory {
     double GetHigh() { return fHigh; }
 
     void Print(std::ostream& = std::cout);      
+    void PrintXML(std::ostream&);
 
   protected:
 
@@ -93,21 +102,19 @@ namespace HistFactory {
   class HistoSys {
 
   public:
-    //friend class Channel;
-
 
     HistoSys() : fhLow(NULL), fhHigh(NULL) {;}
     HistoSys(const std::string& Name) : fName(Name), fhLow(NULL), fhHigh(NULL) {;}
 
     void Print(std::ostream& = std::cout);  
-    void writeToFile( std::string FileName, std::string DirName );
+    void PrintXML(std::ostream&);
+    void writeToFile( const std::string& FileName, const std::string& DirName );
 
     void SetHistoLow( TH1* Low ) { fhLow = Low; }
     void SetHistoHigh( TH1* High ) { fhHigh = High; }
     
     TH1* GetHistoLow();
     TH1* GetHistoHigh();
-
     
     void SetName( const std::string& Name ) { fName = Name; }
     std::string GetName() { return fName; }
@@ -130,7 +137,6 @@ namespace HistFactory {
     std::string GetHistoPathLow() { return fHistoPathLow; }
     std::string GetHistoPathHigh() { return fHistoPathHigh; }
 
-
   protected:
 
     std::string fName;
@@ -153,13 +159,10 @@ namespace HistFactory {
   class HistoFactor {
 
   public:
-    //friend class Channel;  
-
-
 
     void SetName( const std::string& Name ) { fName = Name; }
     std::string GetName() { return fName; }
-
+    
     void SetInputFileLow( const std::string& InputFileLow ) { fInputFileLow = InputFileLow; }
     void SetInputFileHigh( const std::string& InputFileHigh ) { fInputFileHigh = InputFileHigh; }
     
@@ -179,16 +182,14 @@ namespace HistFactory {
     std::string GetHistoPathHigh() { return fHistoPathHigh; }
 
     void Print(std::ostream& = std::cout);  
-    void writeToFile( std::string FileName, std::string DirName );
-
+    void writeToFile( const std::string& FileName, const std::string& DirName );
+    void PrintXML(std::ostream&);
 
     TH1* GetHistoLow();
     TH1* GetHistoHigh();
     void SetHistoLow( TH1* Low ) { fhLow = Low; }
     void SetHistoHigh( TH1* High ) { fhHigh = High; }
 
-
-
   protected:
 
     std::string fName;
@@ -211,8 +212,6 @@ namespace HistFactory {
   class ShapeSys {
 
   public:
-    //friend class Channel;
-
 
     void SetName( const std::string& Name ) { fName = Name; }
     std::string GetName() { return fName; }
@@ -226,19 +225,16 @@ namespace HistFactory {
     void SetHistoPath( const std::string& HistoPath ) { fHistoPath = HistoPath; }
     std::string GetHistoPath() { return fHistoPath; }
 
-
     void Print(std::ostream& = std::cout);  
-    void writeToFile( std::string FileName, std::string DirName );
+    void PrintXML(std::ostream&);
+    void writeToFile( const std::string& FileName, const std::string& DirName );
 
     TH1* GetErrorHist();
     void SetErrorHist(TH1* hError) { fhError = hError; }
 
-
-
     void SetConstraintType( Constraint::Type ConstrType ) { fConstraintType = ConstrType; }
     Constraint::Type GetConstraintType() { return fConstraintType; }
 
-
   protected:
 
     std::string fName;
@@ -256,29 +252,67 @@ namespace HistFactory {
   class ShapeFactor {
 
   public:
-    //friend class Channel;  
 
+    ShapeFactor();
+    
     void SetName( const std::string& Name ) { fName = Name; }
     std::string GetName() { return fName; }
 
-
     void Print(std::ostream& = std::cout);  
+    void PrintXML(std::ostream&);
+    void writeToFile( const std::string& FileName, const std::string& DirName);
+
+    void SetInitialShape(TH1* shape) { fhInitialShape = shape; }
+    TH1* GetInitialShape() { return fhInitialShape; }
+
+    void SetConstant(bool constant) { fConstant = constant; }
+    bool IsConstant() { return fConstant; }
+    
+    bool HasInitialShape() { return fHasInitialShape; }
+
+    void SetInputFile( const std::string& InputFile ) { 
+      fInputFile = InputFile; 
+      fHasInitialShape=true;
+    }
+    std::string GetInputFile() { return fInputFile; }
+
+    void SetHistoName( const std::string& HistoName ) { 
+      fHistoName = HistoName; 
+      fHasInitialShape=true; 
+    }
+    std::string GetHistoName() { return fHistoName; }
+
+    void SetHistoPath( const std::string& HistoPath ) { 
+      fHistoPath = HistoPath; 
+      fHasInitialShape=true;
+    }
+    std::string GetHistoPath() { return fHistoPath; }
 
   protected:
     std::string fName;
 
+    bool fConstant;
+
+    // A histogram representing
+    // the initial shape
+    bool fHasInitialShape;
+    std::string fHistoName;
+    std::string fHistoPath;
+    std::string fInputFile;
+    TH1* fhInitialShape;
+
   };
 
 
   class StatError {
 
   public:
-    //friend class Channel;
 
     StatError() : fActivate(false), fUseHisto(false), fhError(NULL) {;}
 
     void Print(std::ostream& = std::cout);  
-    void writeToFile( std::string FileName, std::string DirName );
+    void PrintXML(std::ostream&);
+    void writeToFile( const std::string& FileName, const std::string& DirName );
 
     void Activate( bool IsActive=true ) { fActivate = IsActive; }
     bool GetActivate() { return fActivate; }
@@ -299,7 +333,6 @@ namespace HistFactory {
     TH1* GetErrorHist();
     void SetErrorHist(TH1* Error) { fhError = Error; }
 
-
   protected:
 
     bool fActivate;
@@ -316,11 +349,10 @@ namespace HistFactory {
   class StatErrorConfig {
 
   public:
-    //friend class Channel;
-
 
     StatErrorConfig() : fRelErrorThreshold( .05 ), fConstraintType( Constraint::Gaussian ) {;}
     void Print(std::ostream& = std::cout);  
+    void PrintXML(std::ostream&);
 
     void SetRelErrorThreshold( double Threshold ) { fRelErrorThreshold = Threshold; }
     double GetRelErrorThreshold() { return fRelErrorThreshold; }
@@ -328,7 +360,6 @@ namespace HistFactory {
     void SetConstraintType( Constraint::Type ConstrType ) { fConstraintType = ConstrType; }
     Constraint::Type GetConstraintType() { return fConstraintType; }
 
-
   protected:
 
     double fRelErrorThreshold;
diff --git a/roofit/histfactory/src/Asimov.cxx b/roofit/histfactory/src/Asimov.cxx
index 9710971..874d66a 100644
--- a/roofit/histfactory/src/Asimov.cxx
+++ b/roofit/histfactory/src/Asimov.cxx
@@ -1,3 +1,21 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+</p>
+END_HTML
+*/
+//
 
 #include "RooRealVar.h"
 #include "RooStats/HistFactory/HistFactoryException.h"
diff --git a/roofit/histfactory/src/Channel.cxx b/roofit/histfactory/src/Channel.cxx
index ab1c367..4346566 100644
--- a/roofit/histfactory/src/Channel.cxx
+++ b/roofit/histfactory/src/Channel.cxx
@@ -1,3 +1,29 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+This class encapsulates all information for the statistical interpretation of one experiment.
+It can be combined with other channels (e.g. for the combination of multiple experiments, or
+to constrain nuisance parameters with information obtained in a control region).
+A channel contains one or more samples which describe the contribution from different processes
+to this measurement.
+</p>
+END_HTML
+*/
+//
+
+
+
 #include "RooStats/HistFactory/Channel.h"
 #include <stdlib.h>
 
@@ -9,10 +35,16 @@
 using namespace std;
 
 RooStats::HistFactory::Channel::Channel() :
-  fName( "" ) { ; }
+  fName( "" )
+{
+  // standard constructor
+}
 
 RooStats::HistFactory::Channel::Channel(std::string ChanName, std::string ChanInputFile) :
-  fName( ChanName ), fInputFile( ChanInputFile ) { ; }
+  fName( ChanName ), fInputFile( ChanInputFile )
+{
+  // create channel with given name and input file
+}
 
 namespace RooStats{
   namespace HistFactory{
@@ -23,13 +55,16 @@ namespace RooStats{
 }
 
 
-void RooStats::HistFactory::Channel::AddSample( RooStats::HistFactory::Sample sample ) { 
+void RooStats::HistFactory::Channel::AddSample( RooStats::HistFactory::Sample sample )
+{
+  // add fully configured sample to channel
+  
   sample.SetChannelName( GetName() );
   fSamples.push_back( sample ); 
 }
 
 void RooStats::HistFactory::Channel::Print( std::ostream& stream ) {
-
+  // print information of channel to given stream
 
   stream << "\t Channel Name: " << fName
 	 << "\t InputFile: " << fInputFile
@@ -61,7 +96,6 @@ void RooStats::HistFactory::Channel::Print( std::ostream& stream ) {
 void RooStats::HistFactory::Channel::PrintXML( std::string Directory, std::string Prefix ) {
 
   // Create an XML file for this channel
-
   std::cout << "Printing XML Files for channel: " << GetName() << std::endl;
   
   std::string XMLName = Prefix + fName + ".xml";
@@ -69,19 +103,10 @@ void RooStats::HistFactory::Channel::PrintXML( std::string Directory, std::strin
   
   ofstream xml( XMLName.c_str() );
 
-
   // Add the time
   xml << "<!--" << std::endl;
   xml << "This xml file created automatically on: " << std::endl;
-/*
-  time_t t = time(0);   // get time now
-  struct tm * now = localtime( &t );
-  xml << (now->tm_year + 1900) << '-'
-      << (now->tm_mon + 1) << '-'
-      << now->tm_mday
-      << std::endl;
-*/
-// LM: use TTimeStamp since time_t does not work on Windows
+  // LM: use TTimeStamp since time_t does not work on Windows
   TTimeStamp t; 
   UInt_t year = 0; 
   UInt_t month = 0; 
@@ -91,9 +116,7 @@ void RooStats::HistFactory::Channel::PrintXML( std::string Directory, std::strin
       << month << '-'
       << day
       << std::endl;
-
   xml << "-->" << std::endl;
-  
 
   // Add the DOCTYPE
   xml << "<!DOCTYPE Channel  SYSTEM 'HistFactorySchema.dtd'>  " << std::endl << std::endl;
@@ -101,16 +124,20 @@ void RooStats::HistFactory::Channel::PrintXML( std::string Directory, std::strin
   // Add the Channel
   xml << "  <Channel Name=\"" << fName << "\" InputFile=\"" << fInputFile << "\" >" << std::endl << std::endl;
 
+  fData.PrintXML( xml );
+  /*
   xml << "    <Data HistoName=\"" << fData.GetHistoName() << "\" "
       << "InputFile=\"" << fData.GetInputFile() << "\" "
       << "HistoPath=\"" << fData.GetHistoPath() << "\" "
       << " /> " << std::endl << std::endl;  
+  */
 
-
+  fStatErrorConfig.PrintXML( xml );
+  /*
   xml << "    <StatErrorConfig RelErrorThreshold=\"" << fStatErrorConfig.GetRelErrorThreshold() << "\" "
       << "ConstraintType=\"" << Constraint::Name( fStatErrorConfig.GetConstraintType() ) << "\" "
       << "/> " << std::endl << std::endl;            
-
+  */
 
   for( unsigned int i = 0; i < fSamples.size(); ++i ) {
     fSamples.at(i).PrintXML( xml );
@@ -118,20 +145,18 @@ void RooStats::HistFactory::Channel::PrintXML( std::string Directory, std::strin
   }
 
   xml << std::endl;
-
   xml << "  </Channel>  " << std::endl;
-
   xml.close();
 
   std::cout << "Finished printing XML files" << std::endl;
 
-
-
 }
 
 
 
 void RooStats::HistFactory::Channel::SetData( std::string DataHistoName, std::string DataInputFile, std::string DataHistoPath ) {
+  // set data for this channel by specifying the name of the histogram,
+  // the external ROOT file and the path to the histogram inside the ROOT file
 
   fData.SetHistoName( DataHistoName );
   fData.SetInputFile( DataInputFile );
@@ -141,7 +166,8 @@ void RooStats::HistFactory::Channel::SetData( std::string DataHistoName, std::st
 
 
 
-void RooStats::HistFactory::Channel::SetData( TH1* hData ) { 
+void RooStats::HistFactory::Channel::SetData( TH1* hData ) {
+  // set data directly to some histogram
   fData.SetHisto( hData ); 
 }
 
@@ -218,9 +244,7 @@ void RooStats::HistFactory::Channel::CollectHistograms() {
 
 
     // Get the StatError Histogram (if necessary)
-
     if( sample.GetStatError().GetUseHisto() ) {
-
       sample.GetStatError().SetErrorHist( GetHistogram(sample.GetStatError().GetInputFile(),
 						       sample.GetStatError().GetHistoPath(),
 						       sample.GetStatError().GetHistoName()) );
@@ -267,6 +291,20 @@ void RooStats::HistFactory::Channel::CollectHistograms() {
 					  shapeSys.GetHistoName()) );
     } // End Loop over ShapeSys
 
+    
+    // Get any initial shape for a ShapeFactor
+    for( unsigned int shapeFactorItr = 0; shapeFactorItr < sample.GetShapeFactorList().size(); ++shapeFactorItr ) {
+
+      RooStats::HistFactory::ShapeFactor& shapeFactor = sample.GetShapeFactorList().at( shapeFactorItr );
+
+      // Check if we need an InitialShape
+      if( shapeFactor.HasInitialShape() ) {
+	TH1* hist = GetHistogram( shapeFactor.GetInputFile(), shapeFactor.GetHistoPath(), 
+				  shapeFactor.GetHistoName() );
+	shapeFactor.SetInitialShape( hist );
+      }
+
+    } // End Loop over ShapeFactor
 
   } // End Loop over Samples
 
diff --git a/roofit/histfactory/src/ConfigParser.cxx b/roofit/histfactory/src/ConfigParser.cxx
index 4a08f56..f41a8b3 100644
--- a/roofit/histfactory/src/ConfigParser.cxx
+++ b/roofit/histfactory/src/ConfigParser.cxx
@@ -51,6 +51,7 @@ std::vector< RooStats::HistFactory::Measurement > ConfigParser::GetMeasurementsF
     if( parseError ) { 
       std::cerr << "Loading of xml document \"" << input
 		<< "\" failed" << std::endl;
+      throw hf_exc();
     } 
 
 
@@ -334,7 +335,7 @@ HistFactory::Measurement ConfigParser::CreateMeasurementFromDriverNode( TXMLNode
 	throw hf_exc();
       }
       //poi// measurement.SetPOI( child->GetText() );
-      measurement.AddPOI( child->GetText() );
+     AddSubStrings( measurement.GetPOIList(), child->GetText() );
     }
 
     else if( child->GetNodeName() == TString( "ParamSetting" ) ) {
@@ -551,6 +552,7 @@ HistFactory::Channel ConfigParser::ParseChannelXMLFile( string filen ) {
   if( parseError ) { 
     std::cout << "Loading of xml document \"" << filen
 	      << "\" failed" << std::endl;
+    throw hf_exc();
   } 
 
   TXMLDocument* xmldoc = xmlparser.GetXMLDocument();
@@ -1024,6 +1026,24 @@ HistFactory::NormFactor ConfigParser::MakeNormFactor( TXMLNode* node ) {
     throw hf_exc();
   }
 
+  if( norm.GetLow() >= norm.GetHigh() ) {
+    std::cout << "Error: NormFactor: " << norm.GetName()
+	      << " has lower limit >= its upper limit: " 
+	      << " Lower: " << norm.GetLow()
+	      << " Upper: " << norm.GetHigh()
+	      << ". Please Fix" << std::endl;
+    throw hf_exc();
+  }
+  if( norm.GetVal() > norm.GetHigh() || norm.GetVal() < norm.GetLow() ) {
+    std::cout << "Error: NormFactor: " << norm.GetName()
+	      << " has initial value not within its range: "
+	      << " Val: " << norm.GetVal()
+	      << " Lower: " << norm.GetLow()
+	      << " Upper: " << norm.GetHigh()
+	      << ". Please Fix" << std::endl;
+    throw hf_exc();
+  }
+
   norm.Print();
 
   return norm;
@@ -1203,7 +1223,14 @@ HistFactory::ShapeFactor ConfigParser::MakeShapeFactor( TXMLNode* node ) {
 
   TListIter attribIt = node->GetAttributes();
   TXMLAttr* curAttr = 0;
-  string Name="";
+
+  // A Shape Factor may or may not include an initial shape
+  // This will be set by strings pointing to a histogram
+  // If we don't see a 'HistoName' attribute, we assume
+  // that an initial shape is not being set
+  std::string ShapeInputFile = m_currentInputFile;
+  std::string ShapeInputPath = m_currentHistoPath;
+
   while( ( curAttr = dynamic_cast< TXMLAttr* >( attribIt() ) ) != 0 ) {
 
     // Get the Name, Val of this node
@@ -1218,6 +1245,21 @@ HistFactory::ShapeFactor ConfigParser::MakeShapeFactor( TXMLNode* node ) {
     else if( attrName == TString( "Name" ) ) {
       shapeFactor.SetName( attrVal );
     }
+    else if( attrName == TString( "Const" ) ) {
+      shapeFactor.SetConstant( CheckTrueFalse(attrVal, "ShapeFactor" ) );
+    }
+    
+    else if( attrName == TString( "HistoName" ) ) {
+      shapeFactor.SetHistoName( attrVal );
+    }
+    
+    else if( attrName == TString( "InputFile" ) ) {
+      ShapeInputFile = attrVal;
+    }
+    
+    else if( attrName == TString( "HistoPath" ) ) {
+      ShapeInputPath = attrVal;
+    }
 
     else {
       std::cout << "Error: Encountered Element in ShapeFactor with unknown name: " 
@@ -1232,6 +1274,20 @@ HistFactory::ShapeFactor ConfigParser::MakeShapeFactor( TXMLNode* node ) {
     throw hf_exc();
   }
 
+  // Set the Histogram name, path, and file
+  // if an InitialHist is set
+  if( shapeFactor.HasInitialShape() ) {
+    if( shapeFactor.GetHistoName() == "" ) {
+      std::cout << "Error: ShapeFactor: " << shapeFactor.GetName()
+		<< " is configured to have an initial shape, but "
+		<< "its histogram doesn't have a name"
+		<< std::endl;
+      throw hf_exc();
+    }
+    shapeFactor.SetHistoPath( ShapeInputPath );
+    shapeFactor.SetInputFile( ShapeInputFile );
+  }
+  
   shapeFactor.Print();
 
   return shapeFactor;
diff --git a/roofit/histfactory/src/Data.cxx b/roofit/histfactory/src/Data.cxx
index 6237605..5351512 100644
--- a/roofit/histfactory/src/Data.cxx
+++ b/roofit/histfactory/src/Data.cxx
@@ -1,3 +1,21 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+</p>
+END_HTML
+*/
+//
  
 
 #include "RooStats/HistFactory/Data.h"
@@ -44,3 +62,13 @@ void RooStats::HistFactory::Data::writeToFile( std::string OutputFileName, std::
   }
 
 }
+
+
+void RooStats::HistFactory::Data::PrintXML( std::ostream& xml ) {
+
+  xml << "    <Data HistoName=\"" << GetHistoName() << "\" "
+      << "InputFile=\"" << GetInputFile() << "\" "
+      << "HistoPath=\"" << GetHistoPath() << "\" "
+      << " /> " << std::endl << std::endl;  
+  
+}
diff --git a/roofit/histfactory/src/HistFactoryNavigation.cxx b/roofit/histfactory/src/HistFactoryNavigation.cxx
index f88d3af..629f9e0 100644
--- a/roofit/histfactory/src/HistFactoryNavigation.cxx
+++ b/roofit/histfactory/src/HistFactoryNavigation.cxx
@@ -2,11 +2,18 @@
 #include <iomanip>
 #include <sstream>
 
+#include "TFile.h"
 #include "TRegexp.h"
+#include "TCanvas.h"
+#include "TLegend.h"
+#include "TMath.h"
 
+#include "RooRealSumPdf.h"
 #include "RooProduct.h"
 #include "RooMsgService.h"
-
+#include "RooCategory.h"
+#include "RooSimultaneous.h"
+#include "RooWorkspace.h"
 
 #include "RooStats/HistFactory/HistFactoryNavigation.h"
 #include "RooStats/HistFactory/HistFactoryException.h"
@@ -19,7 +26,10 @@ namespace RooStats {
   namespace HistFactory {
 
 
-    HistFactoryNavigation::HistFactoryNavigation(ModelConfig* mc) : _numBinsToPrint(-1) {
+    // CONSTRUCTOR
+    HistFactoryNavigation::HistFactoryNavigation(ModelConfig* mc) 
+      : _minBinToPrint(-1), _maxBinToPrint(-1), 
+	_label_print_width(20), _bin_print_width(12) {
 
       if( !mc ) {
 	std::cout << "Error: The supplied ModelConfig is NULL " << std::endl;
@@ -60,10 +70,12 @@ namespace RooStats {
     }
 
 
+    // CONSTRUCTOR
     HistFactoryNavigation::HistFactoryNavigation(const std::string& FileName,
 						 const std::string& WorkspaceName,
 						 const std::string& ModelConfigName) :
-      _numBinsToPrint(-1) {
+      _minBinToPrint(-1), _maxBinToPrint(-1), 
+      _label_print_width(20), _bin_print_width(12) {
       
       // Open the File
       TFile* file = new TFile(FileName.c_str());
@@ -124,7 +136,10 @@ namespace RooStats {
     }
 
 
-    HistFactoryNavigation::HistFactoryNavigation(RooAbsPdf* model, RooArgSet* observables) {
+    // CONSTRUCTOR
+    HistFactoryNavigation::HistFactoryNavigation(RooAbsPdf* model, RooArgSet* observables) :
+      _minBinToPrint(-1), _maxBinToPrint(-1), 
+      _label_print_width(20), _bin_print_width(12) {
 
       // Save the model pointer
       if( !model ) {
@@ -151,6 +166,30 @@ namespace RooStats {
 
     }
 
+
+    void HistFactoryNavigation::PrintMultiDimHist(TH1* hist, int bin_print_width) {
+
+      // This is how ROOT makes us loop over histograms :(
+      int current_bin = 0;
+      int num_bins = hist->GetNbinsX()*hist->GetNbinsY()*hist->GetNbinsZ();
+      for(int i = 0; i < num_bins; ++i) {
+	// Avoid the overflow/underflow
+	current_bin++;
+	while( hist->IsBinUnderflow(current_bin) ||
+	       hist->IsBinOverflow(current_bin) ) {
+	  current_bin++;
+	}
+	// Check that we should print this bin
+	if( _minBinToPrint != -1 && i < _minBinToPrint) continue;
+	if( _maxBinToPrint != -1 && i > _maxBinToPrint) break;
+	std::cout << std::setw(bin_print_width) << hist->GetBinContent(current_bin);
+      }
+      std::cout << std::endl;
+
+    }
+
+
+
     RooAbsPdf* HistFactoryNavigation::GetChannelPdf(const std::string& channel) {
 
       std::map< std::string, RooAbsPdf* >::iterator itr;
@@ -175,19 +214,21 @@ namespace RooStats {
 
     void HistFactoryNavigation::PrintState(const std::string& channel) {
 
-      int label_print_width = 20;
-      int bin_print_width = 12;
+      //int label_print_width = 20;
+      //int bin_print_width = 12;
       std::cout << std::endl << channel << ":" << std::endl;
 
       // Get the map of Samples for this channel
       std::map< std::string, RooAbsReal*> SampleFunctionMap = GetSampleFunctionMap(channel);      
 
       // Set the size of the print width if necessary
+      /*
       for( std::map< std::string, RooAbsReal*>::iterator itr = SampleFunctionMap.begin(); 
 	   itr != SampleFunctionMap.end(); ++itr) {
 	std::string sample_name = itr->first;
 	label_print_width = TMath::Max(label_print_width, (int)sample_name.size()+2);
       }
+      */
 
       // Loop over the SampleFunctionMap and print the individual histograms
       // to get the total histogram for the channel
@@ -195,29 +236,24 @@ namespace RooStats {
       std::map< std::string, RooAbsReal*>::iterator itr = SampleFunctionMap.begin();
       for( ; itr != SampleFunctionMap.end(); ++itr) {
 
-
 	std::string sample_name = itr->first;
 	std::string tmp_name = sample_name + channel + "_pretty_tmp";
 	TH1* sample_hist = GetSampleHist(channel, sample_name, tmp_name);
-	num_bins = sample_hist->GetNbinsX();
-	std::cout << std::setw(label_print_width) << sample_name;
+	num_bins = sample_hist->GetNbinsX()*sample_hist->GetNbinsY()*sample_hist->GetNbinsZ();
+	std::cout << std::setw(_label_print_width) << sample_name;
 
-	// Check that we should print this bin
-
-	for(int i = 0; i < num_bins; ++i) {
-	  if( _numBinsToPrint != -1 && i >= _numBinsToPrint) break;
-	  std::cout << std::setw(bin_print_width) << sample_hist->GetBinContent(i+1);
-	}
-	std::cout << std::endl;
+	// Print the content of the histogram
+	PrintMultiDimHist(sample_hist, _bin_print_width);
 	delete sample_hist;
+
       }
 
       // Make the line break as a set of "===============" ...
       std::string line_break;
-      int break_length = _numBinsToPrint == -1 ? 
-	num_bins : TMath::Min(_numBinsToPrint, (int)num_bins);
-      break_length *= bin_print_width;
-      break_length += label_print_width;
+      int high_bin = _maxBinToPrint==-1 ? num_bins : TMath::Min(_maxBinToPrint, (int)num_bins);
+      int low_bin = _minBinToPrint==-1 ? 1 : _minBinToPrint;
+      int break_length = (high_bin - low_bin + 1) * _bin_print_width;
+      break_length += _label_print_width;
       for(int i = 0; i < break_length; ++i) {
 	line_break += "=";
       }
@@ -225,12 +261,10 @@ namespace RooStats {
 
       std::string tmp_name = channel + "_pretty_tmp";
       TH1* channel_hist = GetChannelHist(channel, tmp_name);
-      std::cout << std::setw(label_print_width) << "TOTAL:";
-      for(int i = 0; i < channel_hist->GetNbinsX(); ++i) {
-	if( _numBinsToPrint != -1 && i >= _numBinsToPrint) break;
-	std::cout << std::setw(bin_print_width) << channel_hist->GetBinContent(i+1);
-      }
-      std::cout << std::endl;
+      std::cout << std::setw(_label_print_width) << "TOTAL:";
+
+      // Print the Histogram
+      PrintMultiDimHist(channel_hist, _bin_print_width);
       delete channel_hist;
 
       return;
@@ -245,11 +279,26 @@ namespace RooStats {
       }
     }
 
+    
+    void HistFactoryNavigation::SetPrintWidths(const std::string& channel) {
 
-    void HistFactoryNavigation::PrintDataSet(RooDataSet* data, 
-					     const std::string& channel_to_print,
-					     int max_bins) {
+      // Get the map of Samples for this channel
+      std::map< std::string, RooAbsReal*> SampleFunctionMap = GetSampleFunctionMap(channel);      
 
+      // Get the max of the samples
+      for( std::map< std::string, RooAbsReal*>::iterator itr = SampleFunctionMap.begin(); 
+	   itr != SampleFunctionMap.end(); ++itr) {
+	std::string sample_name = itr->first;
+	_label_print_width = TMath::Max(_label_print_width, (int)sample_name.size()+2);
+      }
+
+      _label_print_width = TMath::Max( _label_print_width, (int)channel.size() + 7); 
+    }
+
+
+    void HistFactoryNavigation::PrintDataSet(RooDataSet* data, 
+					     const std::string& channel_to_print) {
+      
       // Print the contents of a 'HistFactory' RooDataset
       // These are stored in a somewhat odd way that makes
       // them difficult to inspect for humans.
@@ -264,52 +313,23 @@ namespace RooStats {
       //                        ...etc...
       // =====================================================
 
-      // Create a map of channel names to the channel's bin values
-      std::map< std::string, std::vector<double> > ChannelBinsMap;
-
-      int label_print_width = 20;
-      int bin_print_width = 12;
-
-      // Then loop and fill these vectors for each channel      
-      for(int i = 0; i < data->numEntries(); ++i) {
+      // int label_print_width = 20;
+      // int bin_print_width = 12;
 
-	// Get the row
-	const RooArgSet* row = data->get(i);
+      // Get the Data Histogram for this channel
+      for( unsigned int i_chan=0; i_chan < fChannelNameVec.size(); ++i_chan) {
 
-	// The current bin height is the weight
-	// of this row.
-	double bin_height = data->weight();
-
-	// Let's figure out the channel
-	// For now, the variable 'channelCat' is magic, but
-	// we should change this to be a bit smarter...
-	std::string channel = row->getCatLabel("channelCat");
-
-	// Get the vector of bin heights (creating if necessary)
-	// and append
-	std::vector<double>& bins = ChannelBinsMap[channel];
-	bins.push_back(bin_height);
-
-      }
-
-      // Now that we have the information, we loop over
-      // our newly created object and pretty print the info
-      std::map< std::string, std::vector<double> >::iterator itr = ChannelBinsMap.begin();
-      for( ; itr != ChannelBinsMap.end(); ++itr) {
-
-	std::string channel_name = itr->first;
+	std::string channel_name = fChannelNameVec.at(i_chan);
 
 	// If we pass a channel string, we only print that one channel
 	if( channel_to_print != "" && channel_name != channel_to_print) continue;
 
-	std::cout << std::setw(label_print_width) << channel_name + " (data)";
-	std::vector<double>& bins = itr->second;
-	for(unsigned int i = 0; i < bins.size(); ++i) {
-	  if( max_bins != -1 && (int)i >= max_bins) break;
-	  std::cout << std::setw(bin_print_width) << bins.at(i);
-	}
-	std::cout << std::endl;
+	TH1* data_hist = GetDataHist(data, channel_name, channel_name+"_tmp");
+	std::cout << std::setw(_label_print_width) << channel_name + " (data)";
 
+	// Print the Histogram
+	PrintMultiDimHist(data_hist, _bin_print_width);
+	delete data_hist;
       }
     }
 
@@ -321,8 +341,9 @@ namespace RooStats {
 
       for( unsigned int i = 0; i < fChannelNameVec.size(); ++i) {
 	std::string channel = fChannelNameVec.at(i);
+	SetPrintWidths(channel);
 	PrintState(channel);
-	PrintDataSet(data, channel, _numBinsToPrint);
+	PrintDataSet(data, channel);
       }
       
       std::cout << std::endl;
@@ -553,7 +574,7 @@ namespace RooStats {
       // Give a name, or a default one will be used
 
       RooArgList observable_list( *GetObservableSet(channel) );
-
+      
       std::map< std::string, RooAbsReal*> SampleFunctionMap = GetSampleFunctionMap(channel);
 
       // Okay, 'loop' once 
@@ -563,7 +584,8 @@ namespace RooStats {
 	std::string sample_name = itr->first;
 	std::string tmp_hist_name = sample_name + "_hist_tmp";
 	RooAbsReal* sample_function = itr->second;
-	TH1* sample_hist = MakeHistFromRooFunction(sample_function, observable_list, tmp_hist_name);
+	TH1* sample_hist = MakeHistFromRooFunction(sample_function, observable_list, 
+						   tmp_hist_name);
 	total_hist = (TH1*) sample_hist->Clone("TotalHist");
 	delete sample_hist;
 	break;
@@ -577,7 +599,8 @@ namespace RooStats {
 	std::string sample_name = itr->first;
 	std::string tmp_hist_name = sample_name + "_hist_tmp";
 	RooAbsReal* sample_function = itr->second;
-	TH1* sample_hist = MakeHistFromRooFunction(sample_function, observable_list, tmp_hist_name);
+	TH1* sample_hist = MakeHistFromRooFunction(sample_function, observable_list, 
+						   tmp_hist_name);
 	total_hist->Add(sample_hist);
 	delete sample_hist;
       }
@@ -589,6 +612,117 @@ namespace RooStats {
 
     }
 
+
+    std::vector< std::string > HistFactoryNavigation::GetChannelSampleList(const std::string& channel) {
+      
+      std::vector<std::string> sample_list;
+
+      std::map< std::string, RooAbsReal*> sample_map = fChannelSampleFunctionMap[channel];
+      std::map< std::string, RooAbsReal*>::iterator itr = sample_map.begin();;
+      for( ; itr != sample_map.end(); ++itr) {
+	sample_list.push_back( itr->first );
+      }
+
+      return sample_list;
+
+    }
+
+    
+    THStack* HistFactoryNavigation::GetChannelStack(const std::string& channel, 
+						    const std::string& name) {
+    
+      THStack* stack = new THStack(name.c_str(), "");
+
+      std::vector< std::string > samples = GetChannelSampleList(channel);
+
+      // Add the histograms
+      for( unsigned int i=0; i < samples.size(); ++i) {
+	std::string sample_name = samples.at(i);
+	TH1* hist = GetSampleHist(channel, sample_name, sample_name+"_tmp");
+	hist->SetLineColor(2+i);
+	hist->SetFillColor(2+i);
+	stack->Add(hist);
+      }
+
+      return stack;
+
+    }
+
+  
+    TH1* HistFactoryNavigation::GetDataHist(RooDataSet* data, const std::string& channel, 
+					    const std::string& name) {
+					    
+      // TO DO:
+      // MAINTAIN THE ACTUAL RANGE, USING THE OBSERVABLES
+      // MAKE IT WORK FOR MULTI-DIMENSIONAL
+      // 
+
+      // If the dataset covers multiple categories,
+      // Split the dataset based on the categories
+      if(strcmp(fModel->ClassName(),"RooSimultaneous")==0){
+
+	// If so, get a list of the component pdf's:
+	RooSimultaneous* simPdf = (RooSimultaneous*) fModel;
+	RooCategory* channelCat = (RooCategory*) (&simPdf->indexCat());
+
+	TList* dataset_list = data->split(*channelCat);
+
+	data = dynamic_cast<RooDataSet*>( dataset_list->FindObject(channel.c_str()) );
+	
+      }
+
+      RooArgList vars( *GetObservableSet(channel) );
+
+      int dim = vars.getSize();
+
+      TH1* hist = NULL;
+
+      if( dim==1 ) {
+	RooRealVar* varX = (RooRealVar*) vars.at(0);
+	hist = data->createHistogram( name.c_str(),*varX, RooFit::Binning(varX->getBinning()) );
+      }
+      else if( dim==2 ) {
+	RooRealVar* varX = (RooRealVar*) vars.at(0);
+	RooRealVar* varY = (RooRealVar*) vars.at(1);
+	hist = data->createHistogram( name.c_str(),*varX, RooFit::Binning(varX->getBinning()),
+				      RooFit::YVar(*varY, RooFit::Binning(varY->getBinning())) );
+      }
+      else if( dim==3 ) {
+	RooRealVar* varX = (RooRealVar*) vars.at(0);
+	RooRealVar* varY = (RooRealVar*) vars.at(1);
+	RooRealVar* varZ = (RooRealVar*) vars.at(2);
+	hist = data->createHistogram( name.c_str(),*varX, RooFit::Binning(varX->getBinning()), 
+				      RooFit::YVar(*varY, RooFit::Binning(varY->getBinning())),
+				      RooFit::YVar(*varZ, RooFit::Binning(varZ->getBinning())) );
+      }
+      else {
+	std::cout << "Error: To Create Histogram from RooDataSet, Dimension must be 1, 2, or 3" << std::endl;
+	std::cout << "Observables: " << std::endl;
+	vars.Print("V");
+	throw hf_exc();
+      }
+
+      return hist;
+
+    }
+
+
+    void HistFactoryNavigation::DrawChannel(const std::string& channel, RooDataSet* data) {
+    
+      // Get the stack
+      THStack* stack = GetChannelStack(channel, channel+"_stack_tmp");
+
+      stack->Draw();
+      
+      if( data!=NULL ) {
+	TH1* data_hist = GetDataHist(data, channel, channel+"_data_tmp");
+	data_hist->Draw("SAME");
+      }
+
+    }
+  
+
+
     RooArgSet HistFactoryNavigation::_GetAllProducts(RooProduct* node) {
 
       // An internal method to recursively get all products,
@@ -644,7 +778,7 @@ namespace RooStats {
 	// If so, get a list of the component pdf's:
 	RooSimultaneous* simPdf = (RooSimultaneous*) modelPdf;
 	RooCategory* channelCat = (RooCategory*) (&simPdf->indexCat());
-	
+
 	// Iterate over the categories and get the
 	// pdf and observables for each category
 	TIterator* iter = channelCat->typeIterator() ;
@@ -776,7 +910,6 @@ namespace RooStats {
       // Check if it's a Parameter
       // (ie a RooRealVar)
       RooArgSet* args = new RooArgSet();
-      //RooArgSet* paramSet = fModel->getParameters(args);
       RooArgSet* paramSet = parent->getParameters(args);
       TIterator* paramItr = paramSet->createIterator();
       RooAbsArg* param = NULL;
@@ -796,11 +929,11 @@ namespace RooStats {
 	 I think it's the user's job to do checks on it.
 	 A dereference will always cause a crash, so it won't
 	 be silent for long...
-      if( term==NULL ) {
-	std::cout << "Error: Failed to find node: " << name
-		  << " as a child of: " << parent->GetName()
-		  << std::endl;
-      }
+	 if( term==NULL ) {
+	 std::cout << "Error: Failed to find node: " << name
+	 << " as a child of: " << parent->GetName()
+	 << std::endl;
+	 }
       */
 
       return term;
@@ -825,9 +958,8 @@ namespace RooStats {
       if( parameter.find("gamma_stat_") != std::string::npos ) { 
 	ConstraintTermName = parameter + "_constraint";
       }
-      // RooAbsReal* term = NULL;
-      // RooAbsReal* term = dynamic_cast<RooAbsReal*>(fModel->findServer(ConstraintTermName.c_str()));
 
+      // Now, get the constraint itself
       RooAbsReal* term = dynamic_cast<RooAbsReal*>(findChild(ConstraintTermName, fModel));
 
       if( term==NULL ) {
@@ -838,88 +970,6 @@ namespace RooStats {
 
       return term;
 
-      /*
-      // Get the set of all variables
-      RooArgSet all_vars = wspace->allVars();
-
-      // Loop over all variables (boilerplate...)
-      TIterator* iter = all_vars.createIterator() ;
-      RooAbsArg* arg ;
-      while((arg=(RooAbsArg*)iter->Next())) {
-
-	// Get the variable, ensuring that it's valid
-	RooRealVar* var = dynamic_cast<RooRealVar*>(arg) ;
-	if( !var ) {
-	  std::cout << "Error: Failed to obtain pointer to variable: " << arg->GetName() << std::endl;
-	  throw runtime_error("fixStatError");
-	}
-
-	std::string VarName = var->GetName();
-
-	if( VarName == "" ) {
-	  std::cout << "Error: Invalid variable name encountered" << std::endl;
-	  throw runtime_error("fixStatError");
-	}
-
-	// Skip if it's not a "gamma_stat_* variable"
-	if( string(VarName).find("gamma_stat_")==string::npos ) continue;
-
-	// Skip if it's not "nominal" parameter
-	if( string(VarName).find("nom_")!=string::npos ) continue;
-    
-
-
-	// Get the constraint and check its type:
-	RooAbsReal* constraint = (RooAbsReal*) wspace->obj( (VarName+"_constraint").c_str() );
-	std::string ConstraintType = constraint->IsA()->GetName();
-
-	double sigma = 0.0;
-
-	if( ConstraintType == "" ) {
-	  std::cout << "Error: Strange constraint type for Stat Uncertainties" << std::endl;
-	  throw runtime_error("fixStatError");
-	}
-	else if( ConstraintType == "RooGaussian" ){
-	  RooAbsReal* sigmaVar = (RooAbsReal*) wspace->obj( (VarName+"_sigma").c_str() );
-	  sigma = sigmaVar->getVal();
-	}
-	else if( ConstraintType == "RooPoisson" ){
-	  RooAbsReal* nom_gamma = (RooAbsReal*) wspace->obj( ("nom_" + VarName).c_str() );
-	  double nom_gamma_val = nom_gamma->getVal();
-	  sigma = 1.0 / TMath::Sqrt( nom_gamma_val );
-	} 
-	else {
-	  std::cout << "Error: Strange constraint type for Stat Uncertainties: " << ConstraintType << std::endl;
-	  throw runtime_error("fixStatError");
-	}
-
-	std::cout << "Encountered a statistical uncertainty variable: " << VarName
-		  << " Error is: " << sigma;
-
-	// Now, fix the parameter if it
-	// is less than some value
-	if( sigma < error_min ) {
-	  if( var->isConstant() ) std::cout << ". Keepting this variable Constant";
-	  else std::cout << ". Setting this variable Constant";
-
-	  var->setConstant(true);
-	}
-	else {
-	  if( var->isConstant() ) std::cout << ". Setting this variable NOT Constant";
-	  else std::cout << ". Keepting this variable NOT Constant";
-
-	  var->setConstant(false);
-	}
-
-	std::cout << std::endl;
-
-      }
-
-      // Done :)
-      return;
-
-*/
-
     }
 
 
@@ -961,7 +1011,6 @@ namespace RooStats {
 	}
 
 	// Get the sigma and its value
-	//RooAbsReal* sigmaVar = findChild(sigmaName, constraintTerm);
 	RooAbsReal* sigmaVar = dynamic_cast<RooAbsReal*>(constraintTerm->findServer(sigmaName.c_str()));
 	if( sigmaVar==NULL ) {
 	  std::cout << "Error: Failed to find the 'sigma' node: " << sigmaName
@@ -1016,7 +1065,6 @@ namespace RooStats {
 	// Check if this client is a member of our pdf
 	// (We probably don't want to mess with clients
 	// if they aren't...)
-	//std::cout << "Checking Client: " << client->GetName() << std::endl; //
 	if( findChild(client->GetName(), fModel)==NULL ) continue;
 	
 	// Now, do the replacement:
@@ -1033,24 +1081,6 @@ namespace RooStats {
 
     }
 
-    /*
-    void AddConstraintTerm(RooAbsArg* constraintTerm) {
-      
-      // Add a constraint term to the pdf
-      // This method requires that the pdf NOT be simultaneous
-      
-      if(strcmp(modelPdf->ClassName(),"RooSimultaneous")==0){
-	std::cout << "Error: The pdf for this navigation is a RooSimultaneous, "
-		  << " to add a constraint term, you must supply an explicit channel"
-		  << std::endl;
-	throw hf_exc();
-      }
-      
-      // ADD CODE TO TAKE THE RooProdPdf term
-      // and add an additional constraint
-
-      }
-    */
 
     void HistFactoryNavigation::PrintSampleComponents(const std::string& channel, 
 						      const std::string& sample) {
@@ -1064,7 +1094,7 @@ namespace RooStats {
       // Make the total histogram for this sample
       std::string total_Name = sampleNode->GetName();
       TH1* total_hist= MakeHistFromRooFunction( sampleNode, observable_list, total_Name + "_tmp");
-      unsigned int num_bins = total_hist->GetNbinsX();
+      unsigned int num_bins = total_hist->GetNbinsX()*total_hist->GetNbinsY()*total_hist->GetNbinsZ();
 
       RooArgSet components;
       
@@ -1091,16 +1121,16 @@ namespace RooStats {
       }
 
       // Now, loop over the components and print them out:
-      
       std::cout << std::endl;
+      std::cout << "Channel: " << channel << " Sample: " << sample << std::endl;
       std::cout << std::setw(label_print_width) << "Factor";
+
       for(unsigned int i=0; i < num_bins; ++i) {
-	if( _numBinsToPrint != -1 && (int)i >= _numBinsToPrint) break;
+	if( _minBinToPrint != -1 && (int)i < _minBinToPrint) continue;
+	if( _maxBinToPrint != -1 && (int)i > _maxBinToPrint) break;
 	std::stringstream sstr;
 	sstr << "Bin" << i;
 	std::cout << std::setw(bin_print_width) << sstr.str();
-	//std::cout << std::setw(bin_print_width) << "Bin ";
-	//std::cout << std::setw(bin_print_width) << i;
       }
       std::cout << std::endl;
 
@@ -1126,35 +1156,32 @@ namespace RooStats {
 
 	// Print the hist
 	std::cout << std::setw(label_print_width) << NodeName;
-	for(unsigned int i = 0; i < num_bins; ++i) {
-	  if( _numBinsToPrint != -1 && (int)i >= _numBinsToPrint) break;
-	  std::cout << std::setw(bin_print_width) << hist->GetBinContent(i+1);
-	}
-	std::cout << std::endl;
+
+	// Print the Histogram
+	PrintMultiDimHist(hist, bin_print_width);
 	delete hist;
       }
       /////
       std::string line_break;
-      int break_length = _numBinsToPrint == -1 ? 
-	num_bins : TMath::Min(_numBinsToPrint, (int)num_bins);
-      break_length *= bin_print_width;
+      int high_bin = _maxBinToPrint==-1 ? num_bins : TMath::Min(_maxBinToPrint, (int)num_bins);
+      int low_bin = _minBinToPrint==-1 ? 1 : _minBinToPrint;
+      int break_length = (high_bin - low_bin + 1) * bin_print_width;
       break_length += label_print_width;
       for(int i = 0; i < break_length; ++i) {
 	line_break += "=";
       }
       std::cout << line_break << std::endl;
 
-      //for(unsigned int i=0; i<label_print_width + 15*num_bins; ++i) { 
-      //std::cout << "="; 
-      //}
-      //std::cout << std::endl << std::setw(label_print_width) << "TOTAL:";
       std::cout << std::setw(label_print_width) << "TOTAL:";
+      PrintMultiDimHist(total_hist, bin_print_width);
+      /*
       for(unsigned int i = 0; i < num_bins; ++i) {
-	if( _numBinsToPrint != -1 && (int)i >= _numBinsToPrint) break;
+	if( _minBinToPrint != -1 && (int)i < _minBinToPrint) continue;
+	if( _maxBinToPrint != -1 && (int)i > _maxBinToPrint) break;
 	std::cout << std::setw(bin_print_width) << total_hist->GetBinContent(i+1);
       }
       std::cout << std::endl << std::endl;
-
+      */
       delete total_hist;
       
       return;
@@ -1162,7 +1189,8 @@ namespace RooStats {
     }
 
 
-    TH1* HistFactoryNavigation::MakeHistFromRooFunction( RooAbsReal* func, RooArgList vars, std::string name ) {
+    TH1* HistFactoryNavigation::MakeHistFromRooFunction( RooAbsReal* func, RooArgList vars, 
+							 std::string name ) {
 
       // Turn a RooAbsReal* into a TH1* based 
       // on a template histogram.  
@@ -1267,10 +1295,10 @@ namespace RooStats {
     }
 
     /*
-    void HistFactoryNavigation::AddChannel(const std::string& channel, RooAbsPdf* pdf, 
-					   RooDataSet* data=NULL) {
+      void HistFactoryNavigation::AddChannel(const std::string& channel, RooAbsPdf* pdf, 
+      RooDataSet* data=NULL) {
 
-    }
+      }
     */
 
   } // namespace HistFactory
diff --git a/roofit/histfactory/src/HistoToWorkspaceFactoryFast.cxx b/roofit/histfactory/src/HistoToWorkspaceFactoryFast.cxx
index 0410216..67f9139 100644
--- a/roofit/histfactory/src/HistoToWorkspaceFactoryFast.cxx
+++ b/roofit/histfactory/src/HistoToWorkspaceFactoryFast.cxx
@@ -1086,9 +1086,8 @@ namespace HistFactory{
 
 
   ///////////////////////////////////////////////
-  RooWorkspace* HistoToWorkspaceFactoryFast::MakeSingleChannelWorkspace(Measurement& measurement, Channel& channel)
-  {
-
+  RooWorkspace* HistoToWorkspaceFactoryFast::MakeSingleChannelWorkspace(Measurement& measurement, Channel& channel) {
+    
     // Set these by hand inside the function
     vector<string> systToFix = measurement.GetConstantParams();
     bool doRatio=false;
@@ -1143,8 +1142,8 @@ namespace HistFactory{
     vector< pair<TH1*,TH1*> >       statHistPairs; // <nominal, error>
     std::string                     statFuncName; // the name of the ParamHistFunc
     std::string                     statNodeName; // the name of the McStat Node
-    Constraint::Type statConstraintType=Constraint::Gaussian;
-    Double_t                        statRelErrorThreshold=0.0;
+    // Constraint::Type statConstraintType=Constraint::Gaussian;
+    // Double_t                        statRelErrorThreshold=0.0;
 
     string prefix, range;
 
@@ -1208,7 +1207,7 @@ namespace HistFactory{
       //        - else, if the histo syst's don't match, return (we ignore this case)
       //        - finally, we take the syst's and apply the linear interpolation w/ constraint
 
-      if(sample.GetHistoSysList().size() == 0){
+      if(sample.GetHistoSysList().size() == 0) {
 
 	// If no HistoSys
         cout << sample.GetName() + "_" + channel_name + " has no variation histograms " << endl;
@@ -1220,7 +1219,8 @@ namespace HistFactory{
       } 
       else {
 	// If there ARE HistoSys(s)
-        string constraintPrefix = sample.GetName() + "_" + channel_name + "_Hist_alpha"; // name of source for variation
+	// name of source for variation
+        string constraintPrefix = sample.GetName() + "_" + channel_name + "_Hist_alpha"; 
 	syst_x_expectedPrefix = sample.GetName() + "_" + channel_name + "_overallSyst_x_HistSyst";
 	// constraintTermNames are passed by reference and appended to,
 	// overallSystName is a std::string for this sample
@@ -1237,7 +1237,8 @@ namespace HistFactory{
       if( sample.GetStatError().GetActivate() ) {
 
 	if( fObsNameVec.size() > 3 ) {
-	  std::cout << "Cannot include Stat Error for histograms of more than 3 dimensions." << std::endl; 
+	  std::cout << "Cannot include Stat Error for histograms of more than 3 dimensions." 
+		    << std::endl; 
 	  throw hf_exc();
 	} else {
 
@@ -1249,12 +1250,8 @@ namespace HistFactory{
 		    << "for channel " << channel_name
 		    << std::endl;
 
-	  // Get the type of StatError constraint from the channel
+	  /*
 	  Constraint::Type type = channel.GetStatErrorConfig().GetConstraintType();
-
-	  // For now, convert it to an EstimateSummary constraint
-	  // Will remove this intermediate step later
-	  // EstimateSummary::ConstraintType:
 	  statConstraintType = Constraint::Gaussian;
 	  if( type == Constraint::Gaussian) {
 	    std::cout << "Using Gaussian StatErrors" << std::endl;
@@ -1264,22 +1261,26 @@ namespace HistFactory{
 	    std::cout << "Using Poisson StatErrors" << std::endl;
 	    statConstraintType = Constraint::Poisson;
 	  }
+	  */
 
-	  statRelErrorThreshold = channel.GetStatErrorConfig().GetRelErrorThreshold();
-
+	  //statRelErrorThreshold = channel.GetStatErrorConfig().GetRelErrorThreshold();
 
 	  // First, get the uncertainty histogram
 	  // and push it back to our vectors
 	
-	  // And get the Relative Error histogram for this sample, if there is one
+	  //if( sample.GetStatError().GetErrorHist() ) {
+	  //statErrorHist = (TH1*) sample.GetStatError().GetErrorHist()->Clone();
+	  //}
+	  //if( statErrorHist == NULL ) {
+
+	  // We need to get the *ABSOLUTE* uncertainty for use in Stat Uncertainties
+	  // This can be done in one of two ways:
+	  //   - Use the built-in Errors in the TH1 itself (they are aboslute)
+	  //   - Take the supplied *RELATIVE* error and multiply by the nominal  
+	  string UncertName  = syst_x_expectedPrefix + "_StatAbsolUncert";
 	  TH1* statErrorHist = NULL;
-	  if( sample.GetStatError().GetErrorHist() ) {
-	    statErrorHist = (TH1*) sample.GetStatError().GetErrorHist()->Clone();
-	  }
 
-	  string UncertName  = syst_x_expectedPrefix + "_StatAbsolUncert";
-	
-	  if( statErrorHist == NULL ) {
+	  if( sample.GetStatError().GetErrorHist() == NULL ) {
 	    // Make the absolute stat error
 	    std::cout << "Making Statistical Uncertainty Hist for "
 		      << " Channel: " << channel_name
@@ -1287,6 +1288,7 @@ namespace HistFactory{
 		      << std::endl;
 	    statErrorHist = MakeAbsolUncertaintyHist( UncertName, nominal );
 	  } else {
+	    statErrorHist = (TH1*) sample.GetStatError().GetErrorHist()->Clone();
 	    // We assume the (relative) error is provided.
 	    // We must turn it into an absolute error
 	    // using the nominal histogram
@@ -1303,33 +1305,47 @@ namespace HistFactory{
 	
 	  // Save the nominal and error hists
 	  // for the building of constraint terms
-	  statHistPairs.push_back( pair<TH1*,TH1*>(nominal,statErrorHist) );
-
-	  // Next, try to get the flexible ParamHistFunc/
+	  statHistPairs.push_back( pair<TH1*,TH1*>(nominal, statErrorHist) );
+
+	  // To do the 'conservative' version, we would need to do some
+	  // intervention here.  We would probably need to create a different
+	  // ParamHistFunc for each sample in the channel.  The would nominally
+	  // use the same gamma's, so we haven't increased the number of parameters
+	  // However, if a bin in the 'nominal' histogram is 0, we simply need to
+	  // change the parameter in that bin in the ParamHistFunc for this sample.
+	  // We also need to add a constraint term.
+	  //  Actually, we'd probably not use the ParamHistFunc...?
+	  //  we could remove the dependence in this ParamHistFunc on the ith gamma
+	  //  and then create the poisson term: Pois(tau | n_exp)Pois(data | n_exp)
+
+
+	  // Next, try to get the ParamHistFunc (it may have been 
+	  // created by another sample in this channel)
 	  // or create it if it doesn't yet exist:
 	  statFuncName = "mc_stat_" + channel_name;
 	  ParamHistFunc* paramHist = (ParamHistFunc*) proto->function( statFuncName.c_str() );
 	  if( paramHist == NULL ) {
 
 	    // Get a RooArgSet of the observables:
-	    // Names in the lsit fObsNameVec:
+	    // Names in the list fObsNameVec:
 	    RooArgList observables;
 	    std::vector<std::string>::iterator itr = fObsNameVec.begin();
 	    for (int idx=0; itr!=fObsNameVec.end(); ++itr, ++idx ) {
 	      observables.add( *proto->var(itr->c_str()) );
 	    }
 	  
-	    //	    RooRealVar* var = (RooRealVar*) observables.first();
-	  
 	    // Create the list of terms to
 	    // control the bin heights:
 	    std::string ParamSetPrefix  = "gamma_stat_" + channel_name;
 	    Double_t gammaMin = 0.0;
 	    Double_t gammaMax = 10.0;
-	    RooArgList statFactorParams = ParamHistFunc::createParamSet(*proto, ParamSetPrefix.c_str(), observables, gammaMin, gammaMax);
+	    RooArgList statFactorParams = ParamHistFunc::createParamSet(*proto, 
+									ParamSetPrefix.c_str(), 
+									observables, 
+									gammaMin, gammaMax);
 
 	    ParamHistFunc statUncertFunc(statFuncName.c_str(), statFuncName.c_str(), 
-				       observables, statFactorParams );
+					 observables, statFactorParams );
 	  
 	    proto->import( statUncertFunc, RecycleConflictNodes() );
 
@@ -1337,7 +1353,6 @@ namespace HistFactory{
 
 	  } // END: If Statement: Create ParamHistFunc
 	
-
 	  // Create the node as a product
 	  // of this function and the 
 	  // expected value from MC
@@ -1362,18 +1377,11 @@ namespace HistFactory{
       // Create a ShapeFactor for this channel //
       ///////////////////////////////////////////
 
-      // GHL: I belive this is logically what we want
       if( sample.GetShapeFactorList().size() > 0 ) {
 
-	// // For now, only one shape factor per channel
-	// if( sample.GetShapeFactorList().size() > 1 ) {
-	//   std::cout << "Error: Only One Shape Factor currently supported" << std::endl;
-	//   throw hf_exc();
-	// }
-
 	if( fObsNameVec.size() > 3 ) {
-	  std::cout << "Cannot include Stat Error for histograms of more than 3 dimensions." << std::endl; 
-	  // We should probably stop execution here, instead of being silent
+	  std::cout << "Cannot include Stat Error for histograms of more than 3 dimensions." 
+		    << std::endl; 
 	  throw hf_exc();
 	} else {
 
@@ -1398,19 +1406,36 @@ namespace HistFactory{
 		observables.add( *proto->var(itr->c_str()) );
 	      }
 	      
-	      //	    RooRealVar* var = (RooRealVar*) observables.first();
-	      
 	      // Create the Parameters
 	      std::string funcParams = "gamma_" + shapeFactor.GetName();
 
 	      // GHL: Again, we are putting hard ranges on the gamma's
 	      //      We should change this to range from 0 to /inf
-	      RooArgList shapeFactorParams = ParamHistFunc::createParamSet(*proto, funcParams.c_str(), observables, 0, 1000);
+	      RooArgList shapeFactorParams = ParamHistFunc::createParamSet(*proto, 
+									   funcParams.c_str(), 
+									   observables, 0, 1000);
 	      
 	      // Create the Function
 	      ParamHistFunc shapeFactorFunc( funcName.c_str(), funcName.c_str(),
 					   observables, shapeFactorParams );
 	      
+	      // Set an initial shape, if requested
+	      if( shapeFactor.GetInitialShape() != NULL ) {
+		TH1* initialShape = shapeFactor.GetInitialShape();
+		std::cout << "Setting Shape Factor: " << shapeFactor.GetName()
+			  << " to have initial shape from hist: "
+			  << initialShape->GetName()
+			  << std::endl;
+		shapeFactorFunc.setShape( initialShape );
+	      }
+	      
+	      // Set the variables constant, if requested
+	      if( shapeFactor.IsConstant() ) {
+		std::cout << "Setting Shape Factor: " << shapeFactor.GetName()
+			  << " to be constant" << std::endl;
+		shapeFactorFunc.setConstant(true);
+	      }
+
 	      proto->import( shapeFactorFunc, RecycleConflictNodes() );
 	      paramHist = (ParamHistFunc*) proto->function( funcName.c_str() );
 	  
@@ -1461,7 +1486,8 @@ namespace HistFactory{
       if( sample.GetShapeSysList().size() != 0 ) {
 
 	if( fObsNameVec.size() > 3 ) {
-	  std::cout << "Cannot include Stat Error for histograms of more than 3 dimensions." << std::endl; 
+	  std::cout << "Cannot include Stat Error for histograms of more than 3 dimensions." 
+		    << std::endl; 
 	  throw hf_exc();
 	} else {
 
@@ -1498,11 +1524,10 @@ namespace HistFactory{
 		observables.add( *proto->var(itr->c_str()) );
 	      }
 
-	      //	      RooRealVar* var = (RooRealVar*) observables.first();
-
 	      // Create the Parameters
 	      std::string funcParams = "gamma_" + shapeSys.GetName();
-	      RooArgList shapeFactorParams = ParamHistFunc::createParamSet(*proto, funcParams.c_str(), 
+	      RooArgList shapeFactorParams = ParamHistFunc::createParamSet(*proto, 
+									   funcParams.c_str(), 
 									   observables, 0, 10);
 
 	      // Create the Function
@@ -1521,18 +1546,20 @@ namespace HistFactory{
 	    // The syst should be a fractional error
 	    TH1* shapeErrorHist = shapeSys.GetErrorHist();
 
-	    Constraint::Type shapeConstraintType = Constraint::Gaussian;
+	    // Constraint::Type shapeConstraintType = Constraint::Gaussian;
 	    Constraint::Type systype = shapeSys.GetConstraintType();
 	    if( systype == Constraint::Gaussian) {
-	      shapeConstraintType = Constraint::Gaussian;
+	      systype = Constraint::Gaussian;
 	    }
 	    if( systype == Constraint::Poisson ) {
-	      shapeConstraintType = Constraint::Poisson;
+	      systype = Constraint::Poisson;
 	    }
 
 	    Double_t minShapeUncertainty = 0.0;
-	    RooArgList shapeConstraints = createStatConstraintTerms(proto, constraintTermNames, *paramHist, shapeErrorHist, 
-								    shapeConstraintType, minShapeUncertainty);
+	    RooArgList shapeConstraints = createStatConstraintTerms(proto, constraintTermNames, 
+								    *paramHist, shapeErrorHist, 
+								    systype, 
+								    minShapeUncertainty);
 
 	  } // End: Loop over ShapeSys vector in this EstimateSummary
 	  
@@ -1561,7 +1588,7 @@ namespace HistFactory{
 
 	} // End: NumObsVar == 1
 
-      } // End: ShapeSysts Size != 0
+      } // End: GetShapeSysList.size() != 0
 
       // Append the name of the "node"
       // that is to be summed with the
@@ -1586,14 +1613,14 @@ namespace HistFactory{
 
     // If a non-zero number of samples call for
     // Stat Uncertainties, create the statFactor functions
-
     if( statHistPairs.size() > 0 ) {
       
       // Create the histogram of (binwise)
       // stat uncertainties:
       TH1* fracStatError = MakeScaledUncertaintyHist( statNodeName + "_RelErr", statHistPairs ); 
       if( fracStatError == NULL ) {
-	std::cout << "Error: Failed to make ScaledUncertaintyHist for: " << statNodeName << std::endl;
+	std::cout << "Error: Failed to make ScaledUncertaintyHist for: " 
+		  << statNodeName << std::endl;
 	throw hf_exc();
       }
       
@@ -1610,8 +1637,20 @@ namespace HistFactory{
       // EstimateSummary looped over (but all
       // should be the same)
 
-      RooArgList statConstraints = createStatConstraintTerms(proto, constraintTermNames, *chanStatUncertFunc, fracStatError, 
-							     statConstraintType, statRelErrorThreshold);
+      // Get the type of StatError constraint from the channel
+      Constraint::Type statConstraintType = channel.GetStatErrorConfig().GetConstraintType();
+      if( statConstraintType == Constraint::Gaussian) {
+	std::cout << "Using Gaussian StatErrors in channel: " << channel.GetName() << std::endl;
+      }
+      if( statConstraintType == Constraint::Poisson ) {
+	std::cout << "Using Poisson StatErrors in channel: " << channel.GetName()  << std::endl;
+      }
+
+      double statRelErrorThreshold = channel.GetStatErrorConfig().GetRelErrorThreshold();
+      RooArgList statConstraints = createStatConstraintTerms(proto, constraintTermNames, 
+							     *chanStatUncertFunc, fracStatError, 
+							     statConstraintType, 
+							     statRelErrorThreshold);
 
     } // END: Loop over stat Hist Pairs
     
@@ -1643,10 +1682,12 @@ namespace HistFactory{
 	if(auxMeas){
 	  const_cast<RooArgSet*>(proto->set("globalObservables"))->remove(*auxMeas);
 	} else{
-	  cout << "could not corresponding auxiliary measurement  " << Form("nom_%s",temp->GetName()) << endl;
+	  cout << "could not corresponding auxiliary measurement  " 
+	       << Form("nom_%s",temp->GetName()) << endl;
 	}
       } else {
-	cout << "could not find variable " << systToFix.at(i) << " could not set it to constant" << endl;
+	cout << "could not find variable " << systToFix.at(i) 
+	     << " could not set it to constant" << endl;
       }
     }
 
@@ -2362,9 +2403,10 @@ namespace HistFactory{
 
 
 
-  RooArgList HistoToWorkspaceFactoryFast::createStatConstraintTerms( RooWorkspace* proto, vector<string>& constraintTermNames,
-								     ParamHistFunc& paramHist, TH1* uncertHist, 
-								     Constraint::Type type, Double_t minSigma ) {
+  RooArgList HistoToWorkspaceFactoryFast::
+  createStatConstraintTerms( RooWorkspace* proto, vector<string>& constraintTermNames,
+			     ParamHistFunc& paramHist, TH1* uncertHist, 
+			     Constraint::Type type, Double_t minSigma ) {
 
 
   // Take a RooArgList of RooAbsReal's and
@@ -2384,7 +2426,6 @@ namespace HistFactory{
 
   RooArgList paramSet = paramHist.paramList();
 
-
   // Must get the full size of the TH1
   // (No direct method to do this...)
   Int_t numBins   = uncertHist->GetNbinsX()*uncertHist->GetNbinsY()*uncertHist->GetNbinsZ();
@@ -2394,10 +2435,10 @@ namespace HistFactory{
   // Check that there are N elements
   // in the RooArgList
   if( numBins != numParams ) {
-    std::cout << "createStatConstraintTerms: bad number of bins" << std::endl;
+    std::cout << "Error: In createStatConstraintTerms, encountered bad number of bins" << std::endl;
     std::cout << "Given histogram with " << numBins << " bins,"
 	      << " but require exactly " << numParams << std::endl;
-    return ConstraintTerms;
+    throw hf_exc();
   }
 
   Int_t TH1BinNumber = 0;
@@ -2438,7 +2479,6 @@ namespace HistFactory{
 
     // Make Constraint Term
     std::string constrName = string(gamma.GetName()) + "_constraint";
-
     std::string nomName = string("nom_") + gamma.GetName();
     std::string sigmaName = string(gamma.GetName()) + "_sigma";
     std::string poisMeanName = string(gamma.GetName()) + "_poisMean";
@@ -2491,6 +2531,7 @@ namespace HistFactory{
 
       std::cout << "Error: Did not recognize Stat Error constraint term type: "
 		<< type << " for : " << paramHist.GetName() << std::endl;
+      throw hf_exc();
     }
   
     // If the sigma value is less
diff --git a/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx b/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx
index 155d25d..2fef680 100644
--- a/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx
+++ b/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx
@@ -86,175 +86,90 @@
 
 // from this package
 #include "Helper.h"
-#include "RooStats/HistFactory/ConfigParser.h"
 #include "RooStats/HistFactory/EstimateSummary.h"
 #include "RooStats/HistFactory/Measurement.h"
 #include "RooStats/HistFactory/HistoToWorkspaceFactoryFast.h"
-//#include "RooStats/HistFactory/HistoToWorkspaceFactoryNew.h"
 #include "RooStats/HistFactory/HistFactoryException.h"
 
 #include "RooStats/HistFactory/MakeModelAndMeasurementsFast.h"
 
 using namespace RooFit;
-using namespace RooStats;
-using namespace HistFactory;
+//using namespace RooStats;
+//using namespace HistFactory;
 
-using namespace std;
-
-void fastDriver(string input){
-  // TO DO:
-  // would like to fully factorize the XML parsing.  
-  // No clear need to have some here and some in ConfigParser
-
-
-  // Make the list of measurements and channels
-  std::vector< HistFactory::Measurement > measurement_list;
-  std::vector< HistFactory::Channel >     channel_list;
-
-  HistFactory::ConfigParser xmlParser;
-
-  measurement_list = xmlParser.GetMeasurementsFromXML( input );
-
-  // Fill them using the XML parser
-  // xmlParser.FillMeasurementsAndChannelsFromXML( input, measurement_list, channel_list );
-
-  // At this point, we have all the information we need
-  // from the xml files.
-  
-
-  // We will make the measurements 1-by-1
-  // This part will be migrated to the
-  // MakeModelAndMeasurements function,
-  // but is here for now.
-
-  
-  /* Now setup the measurement */
-  // At this point, all we need
-  // is the list of measurements
-    
-  for(unsigned int i = 0; i < measurement_list.size(); ++i) {
-
-    HistFactory::Measurement measurement = measurement_list.at(i);
-
-    measurement.CollectHistograms();
-
-    MakeModelAndMeasurementFast( measurement );
-
-  }
-
-  return;
-
-}
-
-/*
-  Moved to HistoToWorkspaceFactoryFast
-std::vector<EstimateSummary> RooStats::HistFactory::GetChannelEstimateSummaries(RooStats::HistFactory::Measurement& measurement, RooStats::HistFactory::Channel& channel) {
-
-*/
-
-/*
-void RooStats::HistFactory::ConfigureWorkspaceForMeasurement( const std::string& ModelName, RooWorkspace* ws_single, RooStats::HistFactory::Measurement& measurement ) {
-
-*/
+//using namespace std;
 
 
 
 RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::HistFactory::Measurement& measurement ) {
-  
-  /*
-  // Add the channels to this measurement
-  for( unsigned int chanItr = 0; chanItr < channel_list.size(); ++chanItr ) {
-  measurement.channels.push_back( channel_list.at( chanItr ) );
-  }
-  */
 
   // This will be returned
   RooWorkspace* ws = NULL;
+  TFile* outFile = NULL;
+  FILE*  tableFile=NULL;
 
   try {
 
-
     std::cout << "Making Model and Measurements (Fast) for measurement: " << measurement.GetName() << std::endl;
 
     double lumiError = measurement.GetLumi()*measurement.GetLumiRelErr();
 
     std::cout << "using lumi = " << measurement.GetLumi() << " and lumiError = " << lumiError
-	 << " including bins between " << measurement.GetBinLow() << " and " << measurement.GetBinHigh() << std::endl;
+	      << " including bins between " << measurement.GetBinLow() << " and " << measurement.GetBinHigh() << std::endl;
     std::cout << "fixing the following parameters:"  << std::endl;
 
-    for(vector<string>::iterator itr=measurement.GetConstantParams().begin(); itr!=measurement.GetConstantParams().end(); ++itr){
-      cout << "   " << *itr << endl;
+    for(std::vector<std::string>::iterator itr=measurement.GetConstantParams().begin(); itr!=measurement.GetConstantParams().end(); ++itr){
+      std::cout << "   " << *itr << std::endl;
     }
 
     std::string rowTitle = measurement.GetName();
     
-    vector<RooWorkspace*> channel_workspaces;
-    vector<string>        channel_names;
-
+    std::vector<RooWorkspace*> channel_workspaces;
+    std::vector<std::string>        channel_names;
 
+    // Create the outFile
     // This holds the TGraphs that are created during the fit
     std::string outputFileName = measurement.GetOutputFilePrefix() + "_" + measurement.GetName() + ".root";
     std::cout << "Creating the output file: " << outputFileName << std::endl;
-    TFile* outFile = new TFile(outputFileName.c_str(), "recreate");
+    outFile = new TFile(outputFileName.c_str(), "recreate");
 
+    // Create the table file
     // This holds the table of fitted values and errors
     std::string tableFileName = measurement.GetOutputFilePrefix() + "_results.table";
     std::cout << "Creating the table file: " << tableFileName << std::endl;
-    FILE*  tableFile =  fopen( tableFileName.c_str(), "a"); 
+    tableFile =  fopen( tableFileName.c_str(), "a"); 
 
     std::cout << "Creating the HistoToWorkspaceFactoryFast factory" << std::endl;
-
     HistoToWorkspaceFactoryFast factory( measurement );
-
-    // USING OLD VERSION...
-    /*
-    TFile* dummyFile = NULL; // TEMPORARY !!!!!
-    HistoToWorkspaceFactoryFast factory(measurement.GetOutputFilePrefix(), rowTitle, measurement.GetConstantParams(), 
-					measurement.GetLumi(), lumiError, 
-					measurement.GetBinLow(), measurement.GetBinHigh(), dummyFile );
-    */
-
-    std::cout << "Setting preprocess functions" << std::endl;
-
+    
     // Make the factory, and do some preprocessing
     // HistoToWorkspaceFactoryFast factory(measurement, rowTitle, outFile);
+    std::cout << "Setting preprocess functions" << std::endl;
     factory.SetFunctionsToPreprocess( measurement.GetPreprocessFunctions() );
-
   
     // for results tables
     fprintf(tableFile, " %s &", rowTitle.c_str() );
   
-    /***
-	First: Loop to make the individual channels
-    ***/
-
-
+    // First: Loop to make the individual channels
     for( unsigned int chanItr = 0; chanItr < measurement.GetChannels().size(); ++chanItr ) {
     
       HistFactory::Channel& channel = measurement.GetChannels().at( chanItr );
-
       if( ! channel.CheckHistograms() ) {
 	std::cout << "MakeModelAndMeasurementsFast: Channel: " << channel.GetName()
 		  << " has uninitialized histogram pointers" << std::endl;
 	throw hf_exc();
-	return NULL;
       }
 
-      string ch_name = channel.GetName();
-      channel_names.push_back(ch_name);
-
+      // Make the workspace for this individual channel
+      std::string ch_name = channel.GetName();
       std::cout << "Starting to process channel: " << ch_name << std::endl;
-
+      channel_names.push_back(ch_name);
       RooWorkspace* ws_single = factory.MakeSingleChannelModel( measurement, channel );
-
       channel_workspaces.push_back(ws_single);
 
-      // Get the Paramater of Interest as a RooRealVar
-      RooRealVar* poi = (RooRealVar*) ws_single->var( (measurement.GetPOI()).c_str() );
-
-      
       // Make the output
-      std::string ChannelFileName = measurement.GetOutputFilePrefix() + "_" + ch_name + "_" + rowTitle + "_model.root";
+      std::string ChannelFileName = measurement.GetOutputFilePrefix() + "_" 
+	+ ch_name + "_" + rowTitle + "_model.root";
       ws_single->writeToFile( ChannelFileName.c_str() );
     
       // Now, write the measurement to the file
@@ -269,19 +184,25 @@ RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::Hist
       std::cout << "Successfully wrote channel to file" << std::endl;
       chanFile->Close();
 
+      // Get the Paramater of Interest as a RooRealVar
+      RooRealVar* poi = dynamic_cast<RooRealVar*>( ws_single->var( (measurement.GetPOI()).c_str() ) );
+
       // do fit unless exportOnly requested
       if(! measurement.GetExportOnly()){
-	if(!poi){
-	  cout <<"can't do fit for this channel, no parameter of interest"<<endl;
-	} else{
-	  if(ws_single->data("obsData")){
-	    FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws_single, ch_name, "obsData",    outFile, tableFile);
+	if(!poi) {
+	  std::cout << "Can't do fit for: " << measurement.GetName() 
+		    << ", no parameter of interest" << std::endl;
+	} else {
+	  if(ws_single->data("obsData")) {
+	    FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws_single, 
+			    ch_name, "obsData",    outFile, tableFile);
 	  } else {
-	    FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws_single, ch_name, "asimovData", outFile, tableFile);
+	    FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws_single, 
+			    ch_name, "asimovData", outFile, tableFile);
 	  }
 	}
       }
-
+      
       fprintf(tableFile, " & " );
     } // End loop over channels
   
@@ -291,7 +212,6 @@ RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::Hist
 	"combine" : will do the individual cross-section measurements plus combination	
     ***/
   
-
     // Use HistFactory to combine the individual channel workspaces
     ws = factory.MakeCombinedModel(channel_names, channel_workspaces);
 
@@ -299,13 +219,13 @@ RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::Hist
     HistoToWorkspaceFactoryFast::ConfigureWorkspaceForMeasurement( "simPdf", ws, measurement );
 
     // Get the Parameter of interest as a RooRealVar
-    RooRealVar* poi = (RooRealVar*) ws->var( (measurement.GetPOI()).c_str() );
-
-    //	  ws->writeToFile(("results/model_combined_edited.root").c_str());
-    //ws->writeToFile((measurement.OutputFilePrefix+"_combined_"+rowTitle+"_model.root").c_str());
-    std::string CombinedFileName = measurement.GetOutputFilePrefix()+"_combined_"+rowTitle+"_model.root";
+    RooRealVar* poi = dynamic_cast<RooRealVar*>( ws->var( (measurement.GetPOI()).c_str() ) );
+    
+    std::string CombinedFileName = measurement.GetOutputFilePrefix() + "_combined_"
+      + rowTitle + "_model.root";
+    std::cout << "Writing combined workspace to file: " << CombinedFileName << std::endl;
     ws->writeToFile( CombinedFileName.c_str() );
-    std::cout << "About to write combined measurement to file" << std::endl;
+    std::cout << "Writing combined measurement to file: " << CombinedFileName << std::endl;
     TFile* combFile = TFile::Open( CombinedFileName.c_str(), "UPDATE" );
     if( combFile == NULL ) {
       std::cout << "Error: Failed to open file " << CombinedFileName << std::endl;
@@ -313,17 +233,21 @@ RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::Hist
     }
     measurement.writeToFile( combFile );
     combFile->Close();
-
-    // TO DO:
-    // Totally factorize the statistical test in "fit Model" to a different area
+    
+    // Fit the combined model
     if(! measurement.GetExportOnly()){
-      if(!poi){
-	cout <<"can't do fit for this channel, no parameter of interest"<<endl;
-      } else{
+      if(!poi) {
+	std::cout << "Can't do fit for: " << measurement.GetName() 
+		  << ", no parameter of interest" << std::endl;
+      } 
+      else {
 	if(ws->data("obsData")){
-	  FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws, "combined", "obsData",    outFile, tableFile);
-	} else {
-	  FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws, "combined", "asimovData", outFile, tableFile);
+	  FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws,"combined", 
+			  "obsData",    outFile, tableFile);
+	} 
+	else {
+	  FitModelAndPlot(measurement.GetName(), measurement.GetOutputFilePrefix(), ws,"combined", 
+			  "asimovData", outFile, tableFile);
 	}
       }
     }
@@ -336,193 +260,213 @@ RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::Hist
     fclose( tableFile );
 
   }
-  catch(exception& e)
-    {
-      std::cout << e.what() << std::endl;
-      throw hf_exc();
-      return NULL;
-    }
-
+  catch(...) {
+    if( tableFile ) fclose(tableFile);
+    if(outFile) outFile->Close();
+    throw;
+  }
+  
   return ws;
 
-
 }
 
 
-  ///////////////////////////////////////////////
-void RooStats::HistFactory::FitModelAndPlot(const std::string& MeasurementName, const std::string& FileNamePrefix, RooWorkspace * combined, string channel, string data_name, TFile* outFile, FILE* tableFile  )
-  {
+///////////////////////////////////////////////
+void RooStats::HistFactory::FitModelAndPlot(const std::string& MeasurementName, 
+					    const std::string& FileNamePrefix, 
+					    RooWorkspace * combined, std::string channel, 
+					    std::string data_name, 
+					    TFile* outFile, FILE* tableFile  ) {
+    
+  if( outFile == NULL ) {
+    std::cout << "Error: Output File in FitModelAndPlot is NULL" << std::endl;
+    throw hf_exc();
+  }
 
-    cout << "In Fit Model"<<endl;
-    ModelConfig * combined_config = (ModelConfig *) combined->obj("ModelConfig");
-    if(!combined_config){
-      cout << "no model config " << "ModelConfig" << " exiting" << endl;
-      return;
-    }
-    //    RooDataSet * simData = (RooDataSet *) combined->obj(data_name.c_str());
-    RooAbsData* simData = combined->data(data_name.c_str());
-    if(!simData){
-      cout << "no data " << data_name << " exiting" << endl;
-      return;
-    }
-    //    const RooArgSet * constrainedParams=combined_config->GetNuisanceParameters();
-    const RooArgSet * POIs=combined_config->GetParametersOfInterest();
-    if(!POIs){
-      cout << "no poi " << data_name << " exiting" << endl;
-      return;
-    }
+  if( tableFile == NULL ) {
+    std::cout << "Error: tableFile in FitModelAndPlot is NULL" << std::endl;
+    throw hf_exc();
+  }
 
-    //RooAbsPdf* model=combined->pdf(model_name.c_str()); 
-    RooAbsPdf* model=combined_config->GetPdf();
-    //    RooArgSet* allParams = model->getParameters(*simData);
-
-    ///////////////////////////////////////
-    //Do combined fit
-    //RooMsgService::instance().setGlobalKillBelow(RooMsgService::INFO) ;
-    cout << "\n\n---------------" << endl;
-    cout << "---------------- Doing "<< channel << " Fit" << endl;
-    cout << "---------------\n\n" << endl;
-    //    RooFitResult* result = model->fitTo(*simData, Minos(kTRUE), Save(kTRUE), PrintLevel(1));
-    model->fitTo(*simData, Minos(kTRUE), PrintLevel(1));
-    //    PrintCovarianceMatrix(result, allParams, "results/"+FilePrefixStr(channel)+"_corrMatrix.table" );
-
-    if( outFile != NULL ) {
-
-      //
-      // We only print info for the FIRST POI,
-      // but the rest are still saved in the ModelConfig
-      // 
-
-      RooRealVar* poi = 0; // (RooRealVar*) POIs->first();
-      // for results tables
-      TIterator* params_itr=POIs->createIterator();
-      TObject* params_obj=0;
-      while((params_obj=params_itr->Next())){
-	poi = (RooRealVar*) params_obj;
-	cout << "printing results for " << poi->GetName() << " at " << poi->getVal()<< " high " << poi->getErrorLo() << " low " << poi->getErrorHi()<<endl;
-      }
-      fprintf(tableFile, " %.4f / %.4f  ", poi->getErrorLo(), poi->getErrorHi());
-
-      RooAbsReal* nll = model->createNLL(*simData);
-      RooAbsReal* profile = nll->createProfile(*poi);
-      if( profile==NULL ) {
-	std::cout << "Error: Failed to make ProfileLikelihood for: " << poi->GetName() 
-		  << " using model: " << model->GetName()
-		  << " and data: " << simData->GetName()
-		  << std::endl;
-	throw hf_exc();
-      }
-      RooPlot* frame = poi->frame();
-      if( frame == NULL ) {
-	std::cout << "Error: Failed to create RooPlot frame for: " << poi->GetName() << std::endl;
-	throw hf_exc();
-      }
-      FormatFrameForLikelihood(frame);
-      TCanvas* c1 = new TCanvas( channel.c_str(), "",800,600);
-      nll->plotOn(frame, ShiftToZero(), LineColor(kRed), LineStyle(kDashed));
-      profile->plotOn(frame);
-      frame->SetMinimum(0);
-      frame->SetMaximum(2.);
-      frame->Draw();
-      //    c1->SaveAs( ("results/"+FilePrefixStr(channel)+"_profileLR.eps").c_str() );
-      c1->SaveAs( (FileNamePrefix+"_"+channel+"_"+MeasurementName+"_profileLR.eps").c_str() );
-      delete c1;
-
-      TDirectory* channel_dir = outFile->mkdir(channel.c_str());
-      if( channel_dir == NULL ) {
-	std::cout << "Error: Failed to make channel directory: " << channel << std::endl;
-	throw hf_exc();
-      }
-      TDirectory* summary_dir = channel_dir->mkdir("Summary");
-      if( summary_dir == NULL ) {
-	std::cout << "Error: Failed to make Summary directory for channel: " << channel << std::endl;
-	throw hf_exc();
-      }
-      summary_dir->cd();
-      //outFile->mkdir(channel.c_str())->mkdir("Summary")->cd();
-    
-      RooCurve* curve=frame->getCurve();
-      Int_t curve_N=curve->GetN();
-      Double_t* curve_x=curve->GetX();
-      delete frame;
-    
-      //
-      // Verbose output from MINUIT
-      //
-      /*
-	RooMsgService::instance().setGlobalKillBelow(RooFit::DEBUG) ;
-	profile->getVal();
-	RooMinuit* minuit = ((RooProfileLL*) profile)->minuit();
-	minuit->setPrintLevel(5) ; // Print MINUIT messages
-	minuit->setVerbose(5) ; // Print RooMinuit messages with parameter 
-	// changes (corresponds to the Verbose() option of fitTo()
-	*/
+  if( combined == NULL ) {
+    std::cout << "Error: Supplied workspace in FitModelAndPlot is NULL" << std::endl;
+    throw hf_exc();
+  }
+
+  ModelConfig* combined_config = (ModelConfig *) combined->obj("ModelConfig");
+  if(!combined_config){
+    std::cout << "Error: no ModelConfig found in Measurement: "
+	      << MeasurementName <<  std::endl;
+    throw hf_exc();
+  }
+
+  RooAbsData* simData = combined->data(data_name.c_str());
+  if(!simData){
+    std::cout << "Error: Failed to get dataset: " << data_name
+	      << " in measurement: " << MeasurementName << std::endl;
+    throw hf_exc();
+  }
     
-      Double_t * x_arr = new Double_t[curve_N];
-      Double_t * y_arr_nll = new Double_t[curve_N];
-      //     Double_t y_arr_prof_nll[curve_N];
-      //     Double_t y_arr_prof[curve_N];
-      
-      for(int i=0; i<curve_N; i++){
-	double f=curve_x[i];
-	poi->setVal(f);
-	x_arr[i]=f;
-	y_arr_nll[i]=nll->getVal();
-      }
+  const RooArgSet* POIs = combined_config->GetParametersOfInterest();
+  if(!POIs) {
+    std::cout << "Not Fitting Model for measurement: " << MeasurementName
+	      << ", no poi found" << std::endl;
+    // Should I throw an exception here?
+    return;
+  }
 
-      TGraph * g = new TGraph(curve_N, x_arr, y_arr_nll);
-      //g->SetName( (FilePrefixStr(channel) +"_nll").c_str());
-      g->SetName( (FileNamePrefix +"_nll").c_str() );
-      g->Write(); 
-      delete g;
-      delete [] x_arr;
-      delete [] y_arr_nll;
+  RooAbsPdf* model = combined_config->GetPdf();
+  if( model==NULL ) {
+    std::cout << "Error: Failed to find pdf in ModelConfig: " << combined_config->GetName()
+	      << std::endl;
+    throw hf_exc();
+  }
 
-    }
+  // Save a Snapshot
+  RooArgSet PoiPlusNuisance( *combined_config->GetNuisanceParameters() );
+  PoiPlusNuisance.add( *combined_config->GetParametersOfInterest() );
+  combined->saveSnapshot("InitialValues", PoiPlusNuisance);
+
+  ///////////////////////////////////////
+  // Do the fit
+  std::cout << "\n\n---------------" << std::endl;
+  std::cout << "---------------- Doing "<< channel << " Fit" << std::endl;
+  std::cout << "---------------\n\n" << std::endl;
+  model->fitTo(*simData, Minos(kTRUE), PrintLevel(1));
+
+  // If there are no parameters of interest,
+  // we exit the function here
+  if( POIs->getSize()==0 ) {
+    std::cout << "WARNING: No POIs found in measurement: " << MeasurementName << std::endl;
+    return;
+  }
+
+  // Loop over all POIs and print their fitted values
+  RooRealVar* poi = NULL; // (RooRealVar*) POIs->first();
+  TIterator* params_itr = POIs->createIterator();
+  TObject* poi_obj=NULL;
+  while( (poi_obj=params_itr->Next()) ) {
+    //poi = (RooRealVar*) poi_obj;
+    poi = dynamic_cast<RooRealVar*>(poi_obj);
+    std::cout << "printing results for " << poi->GetName() 
+	      << " at " << poi->getVal()<< " high " 
+	      << poi->getErrorLo() << " low " 
+	      << poi->getErrorHi() << std::endl;
+  }
 
-    /** find out what's inside the workspace **/
-    //combined->Print();
+  // But we only make detailed plots and tables
+  // for the 'first' POI
+  poi = dynamic_cast<RooRealVar*>(POIs->first());
+
+  // Print the MINOS errors to the TableFile
+  fprintf(tableFile, " %.4f / %.4f  ", poi->getErrorLo(), poi->getErrorHi());
+
+  // Make the Profile Likelihood Plot
+  RooAbsReal* nll = model->createNLL(*simData);
+  RooAbsReal* profile = nll->createProfile(*poi);
+  if( profile==NULL ) {
+    std::cout << "Error: Failed to make ProfileLikelihood for: " << poi->GetName() 
+	      << " using model: " << model->GetName()
+	      << " and data: " << simData->GetName()
+	      << std::endl;
+    throw hf_exc();
+  }
 
+  RooPlot* frame = poi->frame();
+  if( frame == NULL ) {
+    std::cout << "Error: Failed to create RooPlot frame for: " << poi->GetName() << std::endl;
+    throw hf_exc();
   }
 
+  // Draw the likelihood curve
+  FormatFrameForLikelihood(frame);
+  TCanvas* ProfileLikelihoodCanvas = new TCanvas( channel.c_str(), "",800,600);
+  nll->plotOn(frame, ShiftToZero(), LineColor(kRed), LineStyle(kDashed));
+  profile->plotOn(frame);
+  frame->SetMinimum(0);
+  frame->SetMaximum(2.);
+  frame->Draw();
+  std::string ProfilePlotName = FileNamePrefix+"_"+channel+"_"+MeasurementName+"_profileLR.eps";
+  ProfileLikelihoodCanvas->SaveAs( ProfilePlotName.c_str() );
+  delete ProfileLikelihoodCanvas;
+
+  // Now, we save our results to the 'output' file
+  // (I'm not sure if users actually look into this file,
+  // but adding additional information and useful plots
+  // may make it more attractive)
+
+  // Save to the output file
+  TDirectory* channel_dir = outFile->mkdir(channel.c_str());
+  if( channel_dir == NULL ) {
+    std::cout << "Error: Failed to make channel directory: " << channel << std::endl;
+    throw hf_exc();
+  }
+  TDirectory* summary_dir = channel_dir->mkdir("Summary");
+  if( summary_dir == NULL ) {
+    std::cout << "Error: Failed to make Summary directory for channel: " 
+	      << channel << std::endl;
+    throw hf_exc();
+  }
+  summary_dir->cd();
 
-void RooStats::HistFactory::FitModel(RooWorkspace * combined, string data_name )
-  {
+  // Save a graph of the profile likelihood curve
+  RooCurve* curve=frame->getCurve();
+  Int_t curve_N=curve->GetN();
+  Double_t* curve_x=curve->GetX();
+  delete frame;
 
-    cout << "In Fit Model"<<endl;
+  Double_t * x_arr = new Double_t[curve_N];
+  Double_t * y_arr_nll = new Double_t[curve_N];
+      
+  for(int i=0; i<curve_N; i++){
+    double f=curve_x[i];
+    poi->setVal(f);
+    x_arr[i]=f;
+    y_arr_nll[i]=nll->getVal();
+  }
+
+  TGraph* g = new TGraph(curve_N, x_arr, y_arr_nll);
+  g->SetName( (FileNamePrefix +"_nll").c_str() );
+  g->Write(); 
+  delete g;
+  delete [] x_arr;
+  delete [] y_arr_nll;
+    
+  // Finally, restore the initial values
+  combined->loadSnapshot("InitialValues");
+    
+}
+
+
+void RooStats::HistFactory::FitModel(RooWorkspace * combined, std::string data_name ) {
+
+    std::cout << "In Fit Model" << std::endl;
     ModelConfig * combined_config = (ModelConfig *) combined->obj("ModelConfig");
     if(!combined_config){
-      cout << "no model config " << "ModelConfig" << " exiting" << endl;
+      std::cout << "no model config " << "ModelConfig" << " exiting" << std::endl;
       return;
     }
-    //    RooDataSet * simData = (RooDataSet *) combined->obj(data_name.c_str());
+    
     RooAbsData* simData = combined->data(data_name.c_str());
     if(!simData){
-      cout << "no data " << data_name << " exiting" << endl;
+      std::cout << "no data " << data_name << " exiting" << std::endl;
       return;
     }
-    //    const RooArgSet * constrainedParams=combined_config->GetNuisanceParameters();
+
     const RooArgSet * POIs=combined_config->GetParametersOfInterest();
     if(!POIs){
-      cout << "no poi " << data_name << " exiting" << endl;
+      std::cout << "no poi " << data_name << " exiting" << std::endl;
       return;
     }
 
-    //RooAbsPdf* model=combined->pdf(model_name.c_str()); 
     RooAbsPdf* model=combined_config->GetPdf();
-    //    RooArgSet* allParams = model->getParameters(*simData);
-
-    ///////////////////////////////////////
-    //Do combined fit
-    //RooMsgService::instance().setGlobalKillBelow(RooMsgService::INFO) ;
-    //    RooFitResult* result = model->fitTo(*simData, Minos(kTRUE), Save(kTRUE), PrintLevel(1));
     model->fitTo(*simData, Minos(kTRUE), PrintLevel(1));
-    //    PrintCovarianceMatrix(result, allParams, "results/"+FilePrefixStr(channel)+"_corrMatrix.table" );
-
+    
   }
 
 
-void RooStats::HistFactory::FormatFrameForLikelihood(RooPlot* frame, string /*XTitle*/, string YTitle){
+void RooStats::HistFactory::FormatFrameForLikelihood(RooPlot* frame, std::string /*XTitle*/, 
+						     std::string YTitle){
 
     gStyle->SetCanvasBorderMode(0);
     gStyle->SetPadBorderMode(0);
@@ -554,9 +498,3 @@ void RooStats::HistFactory::FormatFrameForLikelihood(RooPlot* frame, string /*XT
 }
 
 
-
-
-/*
-Removed.  Use instead HistoToWorkspaceFactoryFast.MakeCombinedModel()
-RooWorkspace* RooStats::HistFactory::MakeModelFast( RooStats::HistFactory::Measurement& measurement ) {
-*/
diff --git a/roofit/histfactory/src/Measurement.cxx b/roofit/histfactory/src/Measurement.cxx
index 2f2fd1b..748d954 100644
--- a/roofit/histfactory/src/Measurement.cxx
+++ b/roofit/histfactory/src/Measurement.cxx
@@ -1,3 +1,26 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+The RooStats::HistFactory::Measurement class can be used to construct a model
+by combining multiple RooStats::HistFactory::Channel objects. It also allows
+to set some general properties like the integrated luminosity, its relative
+uncertainty or the functional form of constraints on nuisance parameters.
+</p>
+END_HTML
+*/
+//
+
 
 #include <ctime>
 #include <iostream>
@@ -16,7 +39,10 @@ ClassImp(RooStats::HistFactory::Measurement) ;
 
 RooStats::HistFactory::Measurement::Measurement() :
   fPOI(), fLumi( 1.0 ), fLumiRelErr( .10 ), 
-  fBinLow( 0 ), fBinHigh( 1 ), fExportOnly( false )  { ; }
+  fBinLow( 0 ), fBinHigh( 1 ), fExportOnly( false )
+{
+  // standard constructor
+}
 
 /*
 RooStats::HistFactory::Measurement::Measurement(const Measurement& other) :
@@ -29,10 +55,17 @@ RooStats::HistFactory::Measurement::Measurement(const Measurement& other) :
 RooStats::HistFactory::Measurement::Measurement(const char* Name, const char* Title) :
   TNamed( Name, Title ),
   fPOI(), fLumi( 1.0 ), fLumiRelErr( .10 ), 
-  fBinLow( 0 ), fBinHigh( 1 ), fExportOnly( false )  { ; }
+  fBinLow( 0 ), fBinHigh( 1 ), fExportOnly( false )
+{
+  // standard constructor specifying name and title of measurement
+}
 
 
-void RooStats::HistFactory::Measurement::AddConstantParam( const std::string& param ) { 
+void RooStats::HistFactory::Measurement::AddConstantParam( const std::string& param )
+{ 
+  // set a parameter in the model to be constant
+  // the parameter does not have to exist yet, the information will be used when
+  // the model is actually created
   
   // Check if the parameter is already set constant
   // We don't need to set it constant twice,
@@ -51,7 +84,9 @@ void RooStats::HistFactory::Measurement::AddConstantParam( const std::string& pa
 
 }
 
-void RooStats::HistFactory::Measurement::SetParamValue( const std::string& param, double value ) {
+void RooStats::HistFactory::Measurement::SetParamValue( const std::string& param, double value )
+{
+  // set parameter of the model to given value
 
   // Check if this parameter is already set to a value
   // If so, issue a warning
@@ -73,7 +108,10 @@ void RooStats::HistFactory::Measurement::SetParamValue( const std::string& param
 
 }
 
-void RooStats::HistFactory::Measurement::AddPreprocessFunction( std::string name, std::string expression, std::string dependencies ) {
+void RooStats::HistFactory::Measurement::AddPreprocessFunction( std::string name, std::string expression, std::string dependencies )
+{
+  // Add a preprocessed function by giving the function a name,
+  // a functional expression, and a string with a bracketed list of dependencies (eg "SigXsecOverSM[0,3]")
 
   PreprocessFunction func(name, expression, dependencies);
   AddFunctionObject(func);
@@ -81,7 +119,10 @@ void RooStats::HistFactory::Measurement::AddPreprocessFunction( std::string name
 }
 
 
-std::vector<std::string> RooStats::HistFactory::Measurement::GetPreprocessFunctions() {
+std::vector<std::string> RooStats::HistFactory::Measurement::GetPreprocessFunctions()
+{
+  // returns a list of defined proprocess function expressions
+  
   std::vector<std::string> PreprocessFunctionExpressions;
   for( unsigned int i = 0; i < fFunctionObjects.size(); ++i ) {
     std::string expression = fFunctionObjects.at(i).GetCommand();
@@ -90,24 +131,38 @@ std::vector<std::string> RooStats::HistFactory::Measurement::GetPreprocessFuncti
   return PreprocessFunctionExpressions;
 }
 
-void RooStats::HistFactory::Measurement::AddGammaSyst(std::string syst, double uncert) {
+void RooStats::HistFactory::Measurement::AddGammaSyst(std::string syst, double uncert)
+{
+  // set constraint term for given systematic to Gamma distribution
+  
   fGammaSyst[syst] = uncert;
 }
 
-void RooStats::HistFactory::Measurement::AddLogNormSyst(std::string syst, double uncert) {
+void RooStats::HistFactory::Measurement::AddLogNormSyst(std::string syst, double uncert)
+{
+  // set constraint term for given systematic to LogNormal distribution
+  
   fLogNormSyst[syst] = uncert;
 }
 
-void RooStats::HistFactory::Measurement::AddUniformSyst(std::string syst) {
+void RooStats::HistFactory::Measurement::AddUniformSyst(std::string syst)
+{
+  // set constraint term for given systematic to uniform distribution
+
   fUniformSyst[syst] = 1.0; // Is this parameter simply a dummy?
 }
 
-void RooStats::HistFactory::Measurement::AddNoSyst(std::string syst) {
+void RooStats::HistFactory::Measurement::AddNoSyst(std::string syst)
+{
+  // define given systematics to have no external constraint
+  
   fNoSyst[syst] = 1.0; // dummy value
 }
 
 
-bool RooStats::HistFactory::Measurement::HasChannel( std::string ChanName ) {
+bool RooStats::HistFactory::Measurement::HasChannel( std::string ChanName )
+{
+  // is the given channel part of this measurement
 
   for( unsigned int i = 0; i < fChannels.size(); ++i ) {
 
@@ -122,7 +177,10 @@ bool RooStats::HistFactory::Measurement::HasChannel( std::string ChanName ) {
 
 }
 
-RooStats::HistFactory::Channel& RooStats::HistFactory::Measurement::GetChannel( std::string ChanName ) {
+RooStats::HistFactory::Channel& RooStats::HistFactory::Measurement::GetChannel( std::string ChanName )
+{
+  // get channel with given name from this measurement
+  // throws an exception in case the channel is not found
 
   for( unsigned int i = 0; i < fChannels.size(); ++i ) {
 
@@ -152,7 +210,9 @@ RooStats::HistFactory::Channel& RooStats::HistFactory::Measurement::GetChannel(
   }
 */
 
-void RooStats::HistFactory::Measurement::PrintTree( std::ostream& stream ) {
+void RooStats::HistFactory::Measurement::PrintTree( std::ostream& stream )
+{
+  // print information about measurement object in tree-like structure to given stream
   
   stream << "Measurement Name: " << GetName()
 	 << "\t OutputFilePrefix: " << fOutputFilePrefix
@@ -197,7 +257,10 @@ void RooStats::HistFactory::Measurement::PrintTree( std::ostream& stream ) {
 
 
 
-void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::string NewOutputPrefix ) {
+void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::string NewOutputPrefix )
+{
+  // create XML files for this measurement in the given directory
+  // XML files can be configured with a different output prefix
 
   // Create an XML file for this measurement
   // First, create the XML driver
@@ -205,7 +268,6 @@ void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::s
 
   // First, check that the directory exists:
 
-
   // LM : fixes for Windows 
   if( gSystem->OpenDirectory( Directory.c_str() ) == 0 ) {
     int success = gSystem->MakeDirectory(Directory.c_str() );    
@@ -252,7 +314,6 @@ void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::s
       << day
       << std::endl;
 
-
   xml << "-->" << std::endl;
 
   // Add the doctype
@@ -264,10 +325,13 @@ void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::s
   // Add the Preprocessed Functions
   for( unsigned int i = 0; i < fFunctionObjects.size(); ++i ) {
     RooStats::HistFactory::PreprocessFunction func = fFunctionObjects.at(i);
+    func.PrintXML(xml);
+    /*
     xml << "<Function Name=\"" << func.GetName() << "\" "
 	<< "Expression=\""     << func.GetExpression() << "\" "
 	<< "Dependents=\""     << func.GetDependents() << "\" "
 	<< "/>" << std::endl;
+    */
   }
   
   xml << std::endl;
@@ -283,8 +347,8 @@ void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::s
   xml << "  <Measurement Name=\"" << GetName() << "\" "
       << "Lumi=\""        << fLumi       << "\" " 
       << "LumiRelErr=\""  << fLumiRelErr << "\" "
-      << "BinLow=\""      << fBinLow     << "\" "
-      << "BinHigh=\""     << fBinHigh    << "\" "
+    //<< "BinLow=\""      << fBinLow     << "\" "
+    // << "BinHigh=\""     << fBinHigh    << "\" "
       << "ExportOnly=\""  << (fExportOnly ? std::string("True") : std::string("False")) << "\" "
       << " >" <<  std::endl;
 
@@ -292,16 +356,49 @@ void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::s
   // Set the POI
   xml << "    <POI>" ;
   for(unsigned int i = 0; i < fPOI.size(); ++i) {
-    xml << fPOI.at(i) << " ";
+    if(i==0) xml << fPOI.at(i);
+    else     xml << " " << fPOI.at(i);
   } 
   xml << "</POI>  " << std::endl;
   
   // Set the Constant Parameters
-  xml << "    <ParamSetting Const=\"True\">";
-  for( unsigned int i = 0; i < fConstantParams.size(); ++i ) {
-    xml << fConstantParams.at(i) << " ";
+  if(fConstantParams.size()) {
+    xml << "    <ParamSetting Const=\"True\">";
+    for( unsigned int i = 0; i < fConstantParams.size(); ++i ) {
+      if (i==0) xml << fConstantParams.at(i);
+      else      xml << " " << fConstantParams.at(i);;
+    }
+    xml << "</ParamSetting>" << std::endl;
+  }
+  
+  // Set the Parameters with new Constraint Terms
+  std::map<std::string, double>::iterator ConstrItr;
+  
+  // Gamma
+  for( ConstrItr = fGammaSyst.begin(); ConstrItr != fGammaSyst.end(); ++ConstrItr ) {
+    xml << "<ConstraintTerm Type=\"Gamma\" RelativeUncertainty=\""
+	<< ConstrItr->second << "\">" << ConstrItr->first
+	<< "</ConstraintTerm>" << std::endl; 
   }
-  xml << "</ParamSetting>" << std::endl;
+  // Uniform
+  for( ConstrItr = fUniformSyst.begin(); ConstrItr != fUniformSyst.end(); ++ConstrItr ) {
+    xml << "<ConstraintTerm Type=\"Uniform\" RelativeUncertainty=\""
+	<< ConstrItr->second << "\">" << ConstrItr->first
+	<< "</ConstraintTerm>" << std::endl; 
+  }
+  // LogNormal
+  for( ConstrItr = fLogNormSyst.begin(); ConstrItr != fLogNormSyst.end(); ++ConstrItr ) {
+    xml << "<ConstraintTerm Type=\"LogNormal\" RelativeUncertainty=\""
+	<< ConstrItr->second << "\">" << ConstrItr->first
+	<< "</ConstraintTerm>" << std::endl; 
+  }
+  // NoSyst
+  for( ConstrItr = fNoSyst.begin(); ConstrItr != fNoSyst.end(); ++ConstrItr ) {
+    xml << "<ConstraintTerm Type=\"NoSyst\" RelativeUncertainty=\""
+	<< ConstrItr->second << "\">" << ConstrItr->first
+	<< "</ConstraintTerm>" << std::endl; 
+  }
+
 
   // Close the Measurement
   xml << "  </Measurement> " << std::endl << std::endl;
@@ -327,12 +424,16 @@ void RooStats::HistFactory::Measurement::PrintXML( std::string Directory, std::s
 
 
 
-void RooStats::HistFactory::Measurement::writeToFile( TFile* file ) {
-
+void RooStats::HistFactory::Measurement::writeToFile( TFile* file )
+{
+  // A measurement, once fully configured, can be saved into a ROOT
+  // file. This will persitify the Measurement object, along with any
+  // channels and samples that have been added to it. It can then be
+  // loaded, potentially modified, and used to create new models.
+    
   // Write every histogram to the file.
   // Edit the measurement to point to this file
   // and to point to each histogram in this file
-
   // Then write the measurement itself.
 
   // Create a tempory measurement
@@ -381,7 +482,6 @@ void RooStats::HistFactory::Measurement::writeToFile( TFile* file ) {
     chanDir->cd();
 
     // Save the data:
-    
     TDirectory* dataDir = chanDir->mkdir( "data" );
     if( dataDir == NULL ) {
       std::cout << "Error: Cannot make directory " << chanDir << std::endl;
@@ -450,6 +550,8 @@ void RooStats::HistFactory::Measurement::writeToFile( TFile* file ) {
 
       // Write the histograms associated with
       // systematics
+
+      /*  THIS IS WHAT I"M COMMENTING
       sample.GetStatError().writeToFile( OutputFileName, sampleDirPath );
 
       // Must write all systematics that contain internal histograms
@@ -464,7 +566,7 @@ void RooStats::HistFactory::Measurement::writeToFile( TFile* file ) {
       for( unsigned int i = 0; i < sample.GetShapeSysList().size(); ++i ) {
 	sample.GetShapeSysList().at(i).writeToFile( OutputFileName, sampleDirPath );
       }
-
+      END COMMENT  */
       /*
       sample.statError.writeToFile( OutputFileName, sampleDirPath );
 
@@ -502,8 +604,8 @@ void RooStats::HistFactory::Measurement::writeToFile( TFile* file ) {
 }
 
 
-std::string RooStats::HistFactory::Measurement::GetDirPath( TDirectory* dir ) {
-
+std::string RooStats::HistFactory::Measurement::GetDirPath( TDirectory* dir )
+{
   // Return the directory's path,
   // stripped of unnecessary prefixes
 
@@ -531,7 +633,16 @@ std::string RooStats::HistFactory::Measurement::GetDirPath( TDirectory* dir ) {
 
 
 
-void RooStats::HistFactory::Measurement::CollectHistograms() {
+void RooStats::HistFactory::Measurement::CollectHistograms()
+{
+  // The most common way to add histograms to channels is to have them
+  // stored in ROOT files and to give HistFactory the location of these
+  // files. This means providing the path to the ROOT file and the path
+  // and name of the histogram within that file. When providing these
+  // in a script, HistFactory doesn't load the histogram from the file
+  // right away. Instead, once all such histograms have been supplied,
+  // one should run this method to open all ROOT files and to copy and
+  // save all necessary histograms.
 
   for( unsigned int chanItr = 0; chanItr < fChannels.size(); ++chanItr) {
 
diff --git a/roofit/histfactory/src/ParamHistFunc.cxx b/roofit/histfactory/src/ParamHistFunc.cxx
index 1213cfa..9457868 100755
--- a/roofit/histfactory/src/ParamHistFunc.cxx
+++ b/roofit/histfactory/src/ParamHistFunc.cxx
@@ -1,22 +1,33 @@
-/*****************************************************************************
-
- *****************************************************************************/
-
-//////////////////////////////////////////////////////////////////////////////
-// 
-// BEGIN_HTML
-// ParamHistFunc 
-// END_HTML
+// @(#)root/roostats:$Id:  cranmer $
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+</p>
+END_HTML
+*/
 //
 
 
 #include <sstream>
+#include <math.h>
+#include <stdexcept>
+
 #include "TMath.h"
 #include "TH1.h"
 
 #include "Riostream.h"
 #include "Riostream.h"
-#include <math.h>
+
 
 #include "RooFit.h"
 #include "RooStats/HistFactory/ParamHistFunc.h"
@@ -40,13 +51,40 @@
 #include "RooWorkspace.h"
 #include "RooBinning.h"
 
-using namespace std;
+//using namespace std;
 
 ClassImp(ParamHistFunc);
 
 
+/*
+  
+  A class which maps the current values of a RooRealVar
+  (or a set of RooRealVars) to one of a number of RooRealVars:
+
+  ParamHistFunc: {val1, val2, ...} -> {gamma (RooRealVar)}
+  
+  The intended interpretation is that each parameter in the
+  range represent the height of a bin over the domain
+  space.
+
+  The 'createParamSet' is an easy way to create these
+  parameters from a set of observables.  They are
+  stored using the "TH1" ordering convention (as compared
+  to the RooDataHist convention, which is used internally
+  and one must map between the two).
+
+  All indices include '0'
+
+  gamma_i_j = paramSet[ size(i)*j + i ]
+
+  ie assuming the dimensions are 5*5:
+  gamma_2_1 = paramSet[ 5*1 + 2 ] = paramSet[7]
+
+ */
+
+
 //_____________________________________________________________________________
-ParamHistFunc::ParamHistFunc() : _numBins(0), _Normalized(false)
+ParamHistFunc::ParamHistFunc() : _numBins(0)
 {
   ;
 }
@@ -59,8 +97,7 @@ ParamHistFunc::ParamHistFunc(const char* name, const char* title,
   _dataVars("!dataVars","data Vars",       this),
   _paramSet("!paramSet","bin parameters",  this),
   _numBins(0),
-  _dataSet( (string(name)+"_dataSet").c_str(), "", vars),
-  _Normalized( false )
+  _dataSet( (std::string(name)+"_dataSet").c_str(), "", vars) 
 {
   
   // Create a function which returns binewise-values
@@ -105,8 +142,7 @@ ParamHistFunc::ParamHistFunc(const char* name, const char* title,
   _dataVars("!dataVars","data Vars",       this),
   _paramSet("!paramSet","bin parameters",  this),
   _numBins(0),
-  _dataSet( (string(name)+"_dataSet").c_str(), "", vars, Hist),
-  _Normalized( false )
+  _dataSet( (std::string(name)+"_dataSet").c_str(), "", vars, Hist) 
 {
 
   // Create a function which returns binewise-values
@@ -133,7 +169,6 @@ ParamHistFunc::ParamHistFunc(const char* name, const char* title,
 
 Int_t ParamHistFunc::GetNumBins( const RooArgSet& vars ) {
   
-  
   // A helper method to get the number of bins
   
   if( vars.getSize() == 0 ) return 0;
@@ -144,7 +179,8 @@ Int_t ParamHistFunc::GetNumBins( const RooArgSet& vars ) {
   RooAbsArg* comp ;
   while((comp = (RooAbsArg*) varIter.next())) {
     if (!dynamic_cast<RooRealVar*>(comp)) {
-      cout << "ParamHistFunc::GetNumBins" << vars.GetName() << ") ERROR: component " << comp->GetName() 
+      std::cout << "ParamHistFunc::GetNumBins" << vars.GetName() << ") ERROR: component " 
+	   << comp->GetName() 
 	   << " in vars list is not of type RooRealVar" << std::endl ;
       RooErrorHandler::softAbort() ;
       return -1;
@@ -167,8 +203,7 @@ ParamHistFunc::ParamHistFunc(const ParamHistFunc& other, const char* name) :
   _paramSet("!paramSet", this, other._paramSet),
   _numBins( other._numBins ),
   _binMap( other._binMap ),
-  _dataSet( other._dataSet ),
-  _Normalized( other._Normalized )
+  _dataSet( other._dataSet )
 {
   ;
   // Copy constructor
@@ -188,33 +223,26 @@ Int_t ParamHistFunc::getCurrentBin() const {
 
   // Get the index of the gamma parameter associated
   // with the current bin
+  // This number is the "RooDataSet" style index
+  // and it must be because it uses the RooDataSet method directly
+  // This is intended to be fed into the getParameter(Int_t) method:
+  //
+  // RooRealVar currentParam = getParameter( getCurrentBin() );
 
   Int_t dataSetIndex = _dataSet.getIndex( _dataVars ); // calcTreeIndex();
-
   return dataSetIndex;
 
-  /*
-  Int_t currentIndex = -1;
-  if( _binMap.find( dataSetIndex ) != _binMap.end() ) {
-    currentIndex = _binMap[ dataSetIndex ];
-  }
-  else {
-    std::cout << "Error: ParamHistFunc internal bin index map "
-	      << "not properly configured" << std::endl;
-    throw -1;
-    return -1;
-  }
-
-  return currentIndex;
-  */
-
 }
 
+
 //_____________________________________________________________________________
 RooRealVar& ParamHistFunc::getParameter( Int_t index ) const {
 
   // Get the parameter associate with the the
   // input RooDataHist style index
+  // It uses the binMap to convert the RooDataSet style index
+  // into the TH1 style index (which is how they are stored
+  // internally in the '_paramSet' vector
 
   Int_t gammaIndex = -1;
   if( _binMap.find( index ) != _binMap.end() ) {
@@ -229,44 +257,86 @@ RooRealVar& ParamHistFunc::getParameter( Int_t index ) const {
   return (RooRealVar&) _paramSet[gammaIndex];
 }
 
+
 //_____________________________________________________________________________
 RooRealVar& ParamHistFunc::getParameter() const {
   Int_t index = getCurrentBin();
   return getParameter( index );
 }
 
-void ParamHistFunc::setParamConst( Int_t index, Bool_t varConst ) {
 
+void ParamHistFunc::setParamConst( Int_t index, Bool_t varConst ) {
   RooRealVar& var = getParameter( index );
   var.setConstant( varConst );
 }
 
 
+void ParamHistFunc::setConstant( bool constant ) {
+  for( int i=0; i < numBins(); ++i) {
+    setParamConst(i, constant);
+  }
+}
+
+
+//_____________________________________________________________________________
+void ParamHistFunc::setShape( TH1* shape ) {
+  
+  int num_hist_bins = shape->GetNbinsX()*shape->GetNbinsY()*shape->GetNbinsZ();
+
+  if( num_hist_bins != numBins() ) {
+    std::cout << "Error - ParamHistFunc: cannot set Shape of ParamHistFunc: " << GetName()
+	      << " using histogram: " << shape->GetName()
+	      << ". Bins don't match" << std::endl;
+    throw std::runtime_error("setShape");
+  }
+
+
+  Int_t TH1BinNumber = 0;
+  for( Int_t i = 0; i < numBins(); ++i) {
+    
+    TH1BinNumber++;
+    
+    while( shape->IsBinUnderflow(TH1BinNumber) || shape->IsBinOverflow(TH1BinNumber) ){
+      TH1BinNumber++;
+    }
+
+    //RooRealVar& var = dynamic_cast<RooRealVar&>(getParameter(i));
+    RooRealVar& var = dynamic_cast<RooRealVar&>(_paramSet[i]);
+    var.setVal( shape->GetBinContent(TH1BinNumber) );
+  }
+
+}
+
 
 //_____________________________________________________________________________
-RooArgList ParamHistFunc::createParamSet(RooWorkspace& w, const std::string& Prefix, const RooArgList& vars) {
+RooArgList ParamHistFunc::createParamSet(RooWorkspace& w, const std::string& Prefix, 
+					 const RooArgList& vars) {
   
   // Create the list of RooRealVar
   // parameters which represent the
   // height of the histogram bins.
-  // Store them in a list
+  // The list 'vars' represents the 
+  // observables (corresponding to histogram bins)
+  // that these newly created parameters will 
+  // be mapped to. (ie, we create one parameter
+  // per observable in vars and per bin in each observable)
 
+  // Store them in a list using:
   // _paramSet.add( createParamSet() );
+  // This list is stored in the "TH1" index order
 
   // Get the number of bins
   // in the nominal histogram
 
-
   RooArgList paramSet;
 
   Int_t numVars = vars.getSize();
   Int_t numBins = GetNumBins( vars );
 
-
   if( numVars == 0 ) {
-    cout << "Warning - ParamHistFunc::createParamSet() :"
+    std::cout << "Warning - ParamHistFunc::createParamSet() :"
 	 << " No Variables provided.  Not making constraint terms." 
-	 << endl;
+	 << std::endl;
     return paramSet;
   }
 
@@ -366,57 +436,7 @@ RooArgList ParamHistFunc::createParamSet(RooWorkspace& w, const std::string& Pre
   }
 
   else {
- 
-    cout << " Error: ParamHistFunc doesn't support dimensions > 3D " <<  endl;
-    
-    /*
-    // Create a vector of indices
-    // all starting at 0
-    std::vector< Int_t > Indices(numVars, 0);
-
-    // Loop over vars:
-    RooFIter varIter = vars.fwdIterator() ;
-    Int_t VarIndex = 0;
-    RooAbsArg* comp ;
-    while((comp = (RooAbsArg*) varIter.next())) {
-    
-      RooRealVar* var = (RooRealVar*) comp;
-
-      // For each bin, create a RooRealVar
-      for( Int_t i = 0; i < var->numBins(); ++i) {
-
-	if( i != 0 ) Indices.at(VarIndex)++;
-	
-	// Make the name of the var:
-	// Varname_bin_0_2_1  where x=0, y=2, z=1 (etc)
-	std::stringstream VarNameStream;
-	VarNameStream << Prefix << "_bin";
-	for(Int_t j = 0; j < numVars; ++j) {
-	  VarNameStream << "_" << Indices.at(j);;
-	}
-	std::string VarName = VarNameStream.str();
-	
-	RooRealVar gamma( VarName.c_str(), VarName.c_str(), 1.0 ); 
-	// "Hard-Code" a minimum of 0.0
-	gamma.setMin( 0.0 );
-	gamma.setConstant( false );
-	
-	w.import( gamma, RooFit::RecycleConflictNodes() );
-	RooRealVar* gamma_wspace = (RooRealVar*) w.var( VarName.c_str() );
-	
-	paramSet.add( *gamma_wspace );
-	
-	// Increase the bin index on this var
-	// (Used in naming)
-
-      }
-
-      // Increase the Int_t iterator
-      // over variables
-      VarIndex++;
-
-    }
-    */
+    std::cout << " Error: ParamHistFunc doesn't support dimensions > 3D " <<  std::endl;
   }
 
   return paramSet;  
@@ -425,86 +445,48 @@ RooArgList ParamHistFunc::createParamSet(RooWorkspace& w, const std::string& Pre
 
 
 //_____________________________________________________________________________
-RooArgList ParamHistFunc::createParamSet(RooWorkspace& w, const std::string& Prefix, const RooArgList& vars, 
+RooArgList ParamHistFunc::createParamSet(RooWorkspace& w, const std::string& Prefix, 
+					 const RooArgList& vars, 
 					 Double_t gamma_min, Double_t gamma_max) {
 
-  RooArgList params = ParamHistFunc::createParamSet( w, Prefix, vars );
-
-  RooFIter paramIter = params.fwdIterator() ;
-  RooAbsArg* comp ;
-  while((comp = (RooAbsArg*) paramIter.next())) {
-    
-    RooRealVar* var = (RooRealVar*) comp;
-
-    var->setMin( gamma_min );
-    var->setMax( gamma_max );
-  }
-
-  return params;
-
-  /*  
-
   // Create the list of RooRealVar
   // parameters which represent the
   // height of the histogram bins.
-  // Store them in a list
+  // The list 'vars' represents the 
+  // observables (corresponding to histogram bins)
+  // that these newly created parameters will 
+  // be mapped to. (ie, we create one parameter
+  // per observable in vars and per bin in each observable)
 
+  // Store them in a list using:
   // _paramSet.add( createParamSet() );
+  // This list is stored in the "TH1" index order
 
   // Get the number of bins
   // in the nominal histogram
- 
 
-  RooArgList paramSet;
-
-  if( gamma_max <= gamma_min ) {
-
-    std::cout << "Warming: gamma_min <= gamma_max: Using default values (0, 10)" << std::endl;
-
-    gamma_min = 0.0;
-    gamma_max = 10.0;
-
-  }
-
-  Double_t gamma_nominal = 1.0;
-
-  if( gamma_nominal < gamma_min ) {
-    gamma_nominal = gamma_min;
-  }
-
-  if( gamma_nominal > gamma_max ) {
-    gamma_nominal = gamma_max;
-  }
+  // We also set the parameters to have nominal min and max values
 
+  RooArgList params = ParamHistFunc::createParamSet( w, Prefix, vars );
 
-  // For each bin, create a RooRealVar
-  for( Int_t i = 0; i < numBins; ++i) {
-
-    std::stringstream VarNameStream;
-    VarNameStream << Prefix << "_bin_" << i;
-    std::string VarName = VarNameStream.str();
-
-    RooRealVar gamma( VarName.c_str(), VarName.c_str(), 
-		      gamma_nominal, gamma_min, gamma_max );
-    gamma.setConstant( false );
-
-    w.import( gamma, RooFit::RecycleConflictNodes() );
-    RooRealVar* gamma_wspace = (RooRealVar*) w.var( VarName.c_str() );
-
-    paramSet.add( *gamma_wspace );
+  RooFIter paramIter = params.fwdIterator() ;
+  RooAbsArg* comp ;
+  while((comp = (RooAbsArg*) paramIter.next())) {
+    
+    RooRealVar* var = (RooRealVar*) comp;
 
+    var->setMin( gamma_min );
+    var->setMax( gamma_max );
   }
 
-
-  return paramSet;
-  */
+  return params;
 
 }
 
 
-
 //_____________________________________________________________________________
-RooArgList ParamHistFunc::createParamSet(const std::string& Prefix, Int_t numBins, Double_t gamma_min, Double_t gamma_max) {
+RooArgList ParamHistFunc::createParamSet(const std::string& Prefix, Int_t numBins, 
+					 Double_t gamma_min, Double_t gamma_max) {
 
   // Create the list of RooRealVar
   // parameters which represent the
@@ -555,6 +537,7 @@ RooArgList ParamHistFunc::createParamSet(const std::string& Prefix, Int_t numBin
 
 }
 
+
 //_____________________________________________________________________________
 Int_t ParamHistFunc::addVarSet( const RooArgList& vars ) {
   
@@ -572,8 +555,9 @@ Int_t ParamHistFunc::addVarSet( const RooArgList& vars ) {
   RooAbsArg* comp ;
   while((comp = (RooAbsArg*) varIter.next())) {
     if (!dynamic_cast<RooRealVar*>(comp)) {
-      coutE(InputArguments) << "ParamHistFunc::(" << GetName() << ") ERROR: component " << comp->GetName() 
-			    << " in variables list is not of type RooRealVar" << std::endl ;
+      coutE(InputArguments) << "ParamHistFunc::(" << GetName() << ") ERROR: component " 
+			    << comp->GetName() << " in variables list is not of type RooRealVar" 
+			    << std::endl;
       RooErrorHandler::softAbort() ;
       return 1;
     }
@@ -634,6 +618,7 @@ Int_t ParamHistFunc::addVarSet( const RooArgList& vars ) {
 
 }
 
+
 //_____________________________________________________________________________
 Int_t ParamHistFunc::addParamSet( const RooArgList& params ) {
   
@@ -665,8 +650,9 @@ Int_t ParamHistFunc::addParamSet( const RooArgList& params ) {
   RooAbsArg* comp ;
   while((comp = (RooAbsArg*) paramIter.next())) {
     if (!dynamic_cast<RooRealVar*>(comp)) {
-      coutE(InputArguments) << "ParamHistFunc::(" << GetName() << ") ERROR: component " << comp->GetName() 
-			    << " in parameter list is not of type RooRealVar" << std::endl ;
+      coutE(InputArguments) << "ParamHistFunc::(" << GetName() << ") ERROR: component " 
+			    << comp->GetName() << " in paramater list is not of type RooRealVar" 
+			    << std::endl;
       RooErrorHandler::softAbort() ;
       return 1;
     }
@@ -687,30 +673,17 @@ Double_t ParamHistFunc::evaluate() const
   // Find the bin cooresponding to the current
   // value of the RooRealVar:
 
-  /*
-  Int_t currentBin = getCurrentBin();
-  RooRealVar* param = (RooRealVar*) &(_paramSet[currentBin]);
-  */
-
   RooRealVar* param = (RooRealVar*) &(getParameter());
-
   Double_t value = param->getVal();
-
-  // If we don't require the function to
-  // be normalized, return right away
-  if( !_Normalized ) return value;
-  
-  // Else, we divide the value by the integral
-  // which effectively normalizes the function over bins
-  Double_t scale = 1.0 / analyticalIntegralWN(0, NULL, NULL);
-  return scale*value;
+  return value;
   
 }
 
 
 //_____________________________________________________________________________
 Int_t ParamHistFunc::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, 
-						      const RooArgSet* normSet, const char* /*rangeName*/) const 
+					     const RooArgSet* normSet, 
+					     const char* /*rangeName*/) const 
 {
   // Advertise that all integrals can be handled internally.
 
@@ -718,11 +691,9 @@ Int_t ParamHistFunc::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& anal
   if (allVars.getSize()==0) return 0 ;
   if (_forceNumInt) return 0 ;
 
+
   // Select subset of allVars that are actual dependents
   analVars.add(allVars) ;
-  //  RooArgSet* normSet = normSet2 ? getObservables(normSet2) : 0 ;
-  //  RooArgSet* normSet = getObservables();
-  //  RooArgSet* normSet = 0;
 
   // Check if this configuration was created before
   Int_t sterileIdx(-1) ;
@@ -739,45 +710,12 @@ Int_t ParamHistFunc::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& anal
 
   return code+1 ; 
 
-  // Make list of function projection and normalization integrals 
-  //  RooAbsReal* param ;
-  // RooAbsReal *func ;
-  //  const RooArgSet* nset = _paramList.nset() ;
-
-  // do nominal
-  /*
-  func = (RooAbsReal*) &( _dataVar.arg() );
-  RooAbsReal* funcInt = func->createIntegral(analVars) ;
-  cache->_funcIntList.addOwned(*funcInt) ;
-
-  // Implement integration here
-
-  // do variations
-  //_lowIter->Reset() ;
-  //_highIter->Reset() ;
-  _paramIter->Reset() ;
-  int i=0;
-  while((param=(RooAbsReal*)_paramIter->Next())) {
-
-    / *
-    func = (RooAbsReal*)_lowIter->Next() ;
-    funcInt = func->createIntegral(analVars) ;
-    cache->_lowIntList.addOwned(*funcInt) ;
-
-    func = (RooAbsReal*)_highIter->Next() ;
-    funcInt = func->createIntegral(analVars) ;
-    cache->_highIntList.addOwned(*funcInt) ;
-    * /
-    ++i;
-
-  }
-*/
-
 }
 
 
 //_____________________________________________________________________________
-Double_t ParamHistFunc::analyticalIntegralWN(Int_t /*code*/, const RooArgSet* /*normSet2*/,const char* /*rangeName*/) const 
+Double_t ParamHistFunc::analyticalIntegralWN(Int_t /*code*/, const RooArgSet* /*normSet2*/,
+					     const char* /*rangeName*/) const 
 {
   // Implement analytical integrations by doing appropriate weighting from  component integrals
   // functions to integrators of components
@@ -824,13 +762,15 @@ Double_t ParamHistFunc::analyticalIntegralWN(Int_t /*code*/, const RooArgSet* /*
 
 
 //_____________________________________________________________________________
-list<Double_t>* ParamHistFunc::plotSamplingHint(RooAbsRealLValue& /*obs*/, Double_t /*xlo*/, Double_t /*xhi*/) const
+std::list<Double_t>* ParamHistFunc::plotSamplingHint(RooAbsRealLValue& /*obs*/, Double_t /*xlo*/, 
+						Double_t /*xhi*/) const
 {
   // Return sampling hint for making curves of (projections) of this function
   // as the recursive division strategy of RooCurve cannot deal efficiently
   // with the vertical lines that occur in a non-interpolated histogram
 
   return 0;
+
   /*
   // copied and edited from RooHistFunc
   RooAbsLValue* lvarg = &obs;
@@ -862,7 +802,8 @@ list<Double_t>* ParamHistFunc::plotSamplingHint(RooAbsRealLValue& /*obs*/, Doubl
 
 
 //______________________________________________________________________________
-std::list<Double_t>* ParamHistFunc::binBoundaries(RooAbsRealLValue& /*obs*/, Double_t /*xlo*/, Double_t /*xhi*/) const 
+std::list<Double_t>* ParamHistFunc::binBoundaries(RooAbsRealLValue& /*obs*/, Double_t /*xlo*/, 
+						  Double_t /*xhi*/) const 
 {
   // Return sampling hint for making curves of (projections) of this function
   // as the recursive division strategy of RooCurve cannot deal efficiently
diff --git a/roofit/histfactory/src/PreprocessFunction.cxx b/roofit/histfactory/src/PreprocessFunction.cxx
index 3ab2301..0328293 100644
--- a/roofit/histfactory/src/PreprocessFunction.cxx
+++ b/roofit/histfactory/src/PreprocessFunction.cxx
@@ -1,3 +1,21 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+</p>
+END_HTML
+*/
+//
 
 #include "RooStats/HistFactory/PreprocessFunction.h"
 
@@ -23,3 +41,10 @@ void RooStats::HistFactory::PreprocessFunction::Print( std::ostream& stream ) {
 	 << std::endl;  
   
 }
+
+void RooStats::HistFactory::PreprocessFunction::PrintXML( std::ostream& xml ) {
+  xml << "<Function Name=\"" << GetName() << "\" "
+      << "Expression=\""     << GetExpression() << "\" "
+      << "Dependents=\""     << GetDependents() << "\" "
+      << "/>" << std::endl;
+}
diff --git a/roofit/histfactory/src/RooBarlowBeestonLL.cxx b/roofit/histfactory/src/RooBarlowBeestonLL.cxx
index 76b8a0a..637bc68 100644
--- a/roofit/histfactory/src/RooBarlowBeestonLL.cxx
+++ b/roofit/histfactory/src/RooBarlowBeestonLL.cxx
@@ -1,13 +1,12 @@
-/***************************************************************************** 
-  * Project: RooFit                                                           * 
-  *                                                                           * 
-  * Copyright (c) 2000-2005, Regents of the University of California          * 
-  *                          and Stanford University. All rights reserved.    * 
-  *                                                                           * 
-  * Redistribution and use in source and binary forms,                        * 
-  * with or without modification, are permitted according to the terms        * 
-  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             * 
-  *****************************************************************************/ 
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
 
 //////////////////////////////////////////////////////////////////////////////
 //
diff --git a/roofit/histfactory/src/Sample.cxx b/roofit/histfactory/src/Sample.cxx
index 584406a..4d5b783 100644
--- a/roofit/histfactory/src/Sample.cxx
+++ b/roofit/histfactory/src/Sample.cxx
@@ -1,23 +1,48 @@
-
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+</p>
+END_HTML
+*/
+//
+
+#include "TH1.h"
 #include "RooStats/HistFactory/Sample.h"
 #include "RooStats/HistFactory/HistFactoryException.h"
 
 //#include "TClass.h"
 
 RooStats::HistFactory::Sample::Sample() : 
-  fNormalizeByTheory(false), fStatErrorActivate(false) { ; }
+  fNormalizeByTheory(false), fStatErrorActivate(false), fhNominal(), fhCountingHist(0) { ; }
 
 
 RooStats::HistFactory::Sample::Sample(std::string SampName, std::string SampHistoName, std::string SampInputFile, std::string SampHistoPath) : 
   fName( SampName ),   fInputFile( SampInputFile), 
   fHistoName( SampHistoName ), fHistoPath( SampHistoPath ),
-  fNormalizeByTheory(true), fStatErrorActivate(false)  { ; }
+  fNormalizeByTheory(true), fStatErrorActivate(false), fhNominal(),
+  fhCountingHist(0) { ; }
 
 RooStats::HistFactory::Sample::Sample(std::string SampName) : 
   fName( SampName ),   fInputFile( "" ), 
   fHistoName( "" ), fHistoPath( "" ),
-  fNormalizeByTheory(true), fStatErrorActivate(false)  { ; }
+  fNormalizeByTheory(true), fStatErrorActivate(false),fhNominal(),
+  fhCountingHist(0) { ; }
 
+RooStats::HistFactory::Sample::~Sample() {
+  if(fhCountingHist)
+    delete fhCountingHist;
+}
 
 TH1* RooStats::HistFactory::Sample::GetHisto()  {
   TH1* histo = (TH1*) fhNominal.GetObject();
@@ -37,6 +62,24 @@ void RooStats::HistFactory::Sample::writeToFile( std::string OutputFileName, std
   fHistoName = histNominal->GetName();
   fHistoPath = DirName;
 
+  // Write this sample's StatError
+  GetStatError().writeToFile( OutputFileName, DirName );
+
+  // Must write all systematics that contain internal histograms
+  // (This is not all systematics)
+  for( unsigned int i = 0; i < GetHistoSysList().size(); ++i ) {
+    GetHistoSysList().at(i).writeToFile( OutputFileName, DirName );
+  }
+  for( unsigned int i = 0; i < GetHistoFactorList().size(); ++i ) {
+    GetHistoFactorList().at(i).writeToFile( OutputFileName, DirName );
+  }
+  for( unsigned int i = 0; i < GetShapeSysList().size(); ++i ) {
+    GetShapeSysList().at(i).writeToFile( OutputFileName, DirName );
+  }
+  for( unsigned int i = 0; i < GetShapeFactorList().size(); ++i ) {
+    GetShapeFactorList().at(i).writeToFile( OutputFileName, DirName );
+  }
+
   return;
 
 }
@@ -52,12 +95,15 @@ void RooStats::HistFactory::Sample::SetValue( Double_t val ) {
   std::string SampleHistName = fName + "_hist";
   
   // Histogram has 1-bin (hard-coded)
-  TH1F* hSample = new TH1F( SampleHistName.c_str(), SampleHistName.c_str(), 1, 0, 1 );
-  hSample->SetBinContent( 1, val );
+  if(fhCountingHist)
+    delete fhCountingHist;
+  
+  fhCountingHist = new TH1F( SampleHistName.c_str(), SampleHistName.c_str(), 1, 0, 1 );
+  fhCountingHist->SetBinContent( 1, val );
 
   // Set the histogram of the internally held data
   // node of this channel to this newly created histogram
-  SetHisto( hSample );
+  SetHisto( fhCountingHist );
 
 }
 
@@ -114,7 +160,10 @@ void RooStats::HistFactory::Sample::PrintXML( std::ofstream& xml ) {
       << " NormalizeByTheory=\"" << (fNormalizeByTheory ? std::string("True") : std::string("False"))  << "\" "
       << ">" << std::endl;
 
+
   // Print Stat Error (if necessary)
+  fStatError.PrintXML( xml );
+  /*
   if( fStatError.GetActivate() ) {
     xml << "      <StatError Activate=\"" << (fStatError.GetActivate() ? std::string("True") : std::string("False"))  << "\" "
 	<< " InputFile=\"" << fStatError.GetInputFile() << "\" "
@@ -122,26 +171,36 @@ void RooStats::HistFactory::Sample::PrintXML( std::ofstream& xml ) {
 	<< " HistoPath=\"" << fStatError.GetHistoPath() << "\" "
 	<< " /> " << std::endl;
   }
-  
+  */
+
+
   // Now, print the systematics:
   for( unsigned int i = 0; i < fOverallSysList.size(); ++i ) {
     RooStats::HistFactory::OverallSys sys = fOverallSysList.at(i);
+    sys.PrintXML(xml);
+    /*
     xml << "      <OverallSys Name=\"" << sys.GetName() << "\" "
 	<< " High=\"" << sys.GetHigh() << "\" "
 	<< " Low=\""  << sys.GetLow()  << "\" "
 	<< "  /> " << std::endl;
+    */
   }
   for( unsigned int i = 0; i < fNormFactorList.size(); ++i ) {
     RooStats::HistFactory::NormFactor sys = fNormFactorList.at(i);
+    sys.PrintXML(xml);
+    /*
     xml << "      <NormFactor Name=\"" << sys.GetName() << "\" "
 	<< " Val=\""   << sys.GetVal()   << "\" "
 	<< " High=\""  << sys.GetHigh()  << "\" "
 	<< " Low=\""   << sys.GetLow()   << "\" "
 	<< " Const=\"" << (sys.GetConst() ? std::string("True") : std::string("False")) << "\" "
 	<< "  /> " << std::endl;
+    */
   }
   for( unsigned int i = 0; i < fHistoSysList.size(); ++i ) {
     RooStats::HistFactory::HistoSys sys = fHistoSysList.at(i);
+    sys.PrintXML(xml);
+    /*
     xml << "      <HistoSys Name=\"" << sys.GetName() << "\" "
 
 	<< " InputFileLow=\""  << sys.GetInputFileLow()  << "\" "
@@ -152,9 +211,12 @@ void RooStats::HistFactory::Sample::PrintXML( std::ofstream& xml ) {
 	<< " HistoNameHigh=\""  << sys.GetHistoNameHigh()  << "\" "
 	<< " HistoPathHigh=\""  << sys.GetHistoPathHigh()  << "\" "
 	<< "  /> " << std::endl;
+    */
   }
   for( unsigned int i = 0; i < fHistoFactorList.size(); ++i ) {
     RooStats::HistFactory::HistoFactor sys = fHistoFactorList.at(i);
+    sys.PrintXML(xml);
+    /*
     xml << "      <HistoFactor Name=\"" << sys.GetName() << "\" "
 
 	<< " InputFileLow=\""  << sys.GetInputFileLow()  << "\" "
@@ -165,9 +227,12 @@ void RooStats::HistFactory::Sample::PrintXML( std::ofstream& xml ) {
 	<< " HistoNameHigh=\""  << sys.GetHistoNameHigh()  << "\" "
 	<< " HistoPathHigh=\""  << sys.GetHistoPathHigh()  << "\" "
 	<< "  /> " << std::endl;
+    */
   }
   for( unsigned int i = 0; i < fShapeSysList.size(); ++i ) {
     RooStats::HistFactory::ShapeSys sys = fShapeSysList.at(i);
+    sys.PrintXML(xml);
+    /*
     xml << "      <ShapeSys Name=\"" << sys.GetName() << "\" "
 
 	<< " InputFile=\""  << sys.GetInputFile()  << "\" "
@@ -175,18 +240,20 @@ void RooStats::HistFactory::Sample::PrintXML( std::ofstream& xml ) {
 	<< " HistoPath=\""  << sys.GetHistoPath()  << "\" "
 	<< " ConstraintType=\"" << std::string(Constraint::Name(sys.GetConstraintType())) << "\" "
 	<< "  /> " << std::endl;
+    */
   }
   for( unsigned int i = 0; i < fShapeFactorList.size(); ++i ) {
     RooStats::HistFactory::ShapeFactor sys = fShapeFactorList.at(i);
+    sys.PrintXML(xml);
+    /*
     xml << "      <ShapeFactor Name=\"" << sys.GetName() << "\" "
 	<< "  /> " << std::endl;
+    */
   }
 
-
   // Finally, close the tag
   xml << "    </Sample>" << std::endl;
 
-
 }
 
 
diff --git a/roofit/histfactory/src/Systematics.cxx b/roofit/histfactory/src/Systematics.cxx
index b8c2466..87882f8 100644
--- a/roofit/histfactory/src/Systematics.cxx
+++ b/roofit/histfactory/src/Systematics.cxx
@@ -1,3 +1,21 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+</p>
+END_HTML
+*/
+//
 
 
 #include "RooStats/HistFactory/Systematics.h"
@@ -5,7 +23,6 @@
 
 
 // Constraints
-
 std::string RooStats::HistFactory::Constraint::Name( Constraint::Type type ) {
 
   if( type == Constraint::Gaussian ) return "Gaussian";
@@ -13,7 +30,7 @@ std::string RooStats::HistFactory::Constraint::Name( Constraint::Type type ) {
   return "";
 }
 
-RooStats::HistFactory::Constraint::Type RooStats::HistFactory::Constraint::GetType( std::string Name ) {
+RooStats::HistFactory::Constraint::Type RooStats::HistFactory::Constraint::GetType( const std::string& Name ) {
 
   if( Name == "" ) {
     std::cout << "Error: Given empty name for ConstraintType" << std::endl;
@@ -49,6 +66,15 @@ void RooStats::HistFactory::NormFactor::Print( std::ostream& stream ) {
 	 << std::endl;
 }
 
+void RooStats::HistFactory::NormFactor::PrintXML( std::ostream& xml ) {
+  xml << "      <NormFactor Name=\"" << GetName() << "\" "
+      << " Val=\""   << GetVal()   << "\" "
+      << " High=\""  << GetHigh()  << "\" "
+      << " Low=\""   << GetLow()   << "\" "
+      << " Const=\"" << (GetConst() ? std::string("True") : std::string("False")) << "\" "
+      << "  /> " << std::endl;
+}
+
 // Overall Sys
 void RooStats::HistFactory::OverallSys::Print( std::ostream& stream ) {
   stream << "\t \t Name: " << fName
@@ -57,8 +83,14 @@ void RooStats::HistFactory::OverallSys::Print( std::ostream& stream ) {
 	 << std::endl;
 }
 
-// HistoSys
+void RooStats::HistFactory::OverallSys::PrintXML( std::ostream& xml ) {
+  xml << "      <OverallSys Name=\"" << GetName() << "\" "
+      << " High=\"" << GetHigh() << "\" "
+      << " Low=\""  << GetLow()  << "\" "
+      << "  /> " << std::endl;
+}
 
+// HistoSys
 TH1* RooStats::HistFactory::HistoSys::GetHistoLow() {
   TH1* histo_low = (TH1*) fhLow.GetObject();
   return histo_low;
@@ -80,8 +112,20 @@ void RooStats::HistFactory::HistoSys::Print( std::ostream& stream ) {
 	 << std::endl;
 }
 
+void RooStats::HistFactory::HistoSys::PrintXML( std::ostream& xml ) {
+  xml << "      <HistoSys Name=\"" << GetName() << "\" "
+      << " InputFileLow=\""  << GetInputFileLow()  << "\" "
+      << " HistoNameLow=\""  << GetHistoNameLow()  << "\" "
+      << " HistoPathLow=\""  << GetHistoPathLow()  << "\" "
+
+      << " InputFileHigh=\""  << GetInputFileHigh()  << "\" "
+      << " HistoNameHigh=\""  << GetHistoNameHigh()  << "\" "
+      << " HistoPathHigh=\""  << GetHistoPathHigh()  << "\" "
+      << "  /> " << std::endl;
+}
 
-void RooStats::HistFactory::HistoSys::writeToFile( std::string FileName, std::string DirName ) {
+void RooStats::HistFactory::HistoSys::writeToFile( const std::string& FileName, 
+						   const std::string& DirName ) {
 
   // This saves the histograms to a file and 
   // changes the name of the local file and histograms
@@ -112,13 +156,11 @@ void RooStats::HistFactory::HistoSys::writeToFile( std::string FileName, std::st
   fHistoPathHigh = DirName;
   fHistoNameHigh = histHigh->GetName();
 
-
   return;
 
 }
 
 
-
 // Shape Sys
 
 TH1* RooStats::HistFactory::ShapeSys::GetErrorHist() {
@@ -135,7 +177,19 @@ void RooStats::HistFactory::ShapeSys::Print( std::ostream& stream ) {
 	 << std::endl;
 }
 
-void RooStats::HistFactory::ShapeSys::writeToFile( std::string FileName, std::string DirName ) {
+
+void RooStats::HistFactory::ShapeSys::PrintXML( std::ostream& xml ) {
+  xml << "      <ShapeSys Name=\"" << GetName() << "\" "
+      << " InputFile=\""  << GetInputFile()  << "\" "
+      << " HistoName=\""  << GetHistoName()  << "\" "
+      << " HistoPath=\""  << GetHistoPath()  << "\" "
+      << " ConstraintType=\"" << std::string(Constraint::Name(GetConstraintType())) << "\" "
+      << "  /> " << std::endl;
+}
+
+
+void RooStats::HistFactory::ShapeSys::writeToFile( const std::string& FileName, 
+						   const std::string& DirName ) {
 
   TH1* histError = GetErrorHist();
   if( histError==NULL ) {
@@ -155,6 +209,8 @@ void RooStats::HistFactory::ShapeSys::writeToFile( std::string FileName, std::st
 }
 
 
+
+
 // HistoFactor
 
 void RooStats::HistFactory::HistoFactor::Print( std::ostream& stream ) {
@@ -180,7 +236,8 @@ TH1* RooStats::HistFactory::HistoFactor::GetHistoHigh() {
 }
 
 
-void RooStats::HistFactory::HistoFactor::writeToFile( std::string FileName, std::string DirName ) {
+void RooStats::HistFactory::HistoFactor::writeToFile( const std::string& FileName, 
+						      const std::string& DirName ) {
 
 
   // This saves the histograms to a file and 
@@ -216,23 +273,94 @@ void RooStats::HistFactory::HistoFactor::writeToFile( std::string FileName, std:
 
 }
 
+void RooStats::HistFactory::HistoFactor::PrintXML( std::ostream& xml ) {
+  xml << "      <HistoFactor Name=\"" << GetName() << "\" "
+
+      << " InputFileLow=\""  << GetInputFileLow()  << "\" "
+      << " HistoNameLow=\""  << GetHistoNameLow()  << "\" "
+      << " HistoPathLow=\""  << GetHistoPathLow()  << "\" "
+
+      << " InputFileHigh=\""  << GetInputFileHigh()  << "\" "
+      << " HistoNameHigh=\""  << GetHistoNameHigh()  << "\" "
+      << " HistoPathHigh=\""  << GetHistoPathHigh()  << "\" "
+      << "  /> " << std::endl;
+}
+
+
 // Shape Factor
+RooStats::HistFactory::ShapeFactor::ShapeFactor() : fConstant(false), 
+						    fHasInitialShape(false),
+						    fhInitialShape(NULL) {;}
 
 void RooStats::HistFactory::ShapeFactor::Print( std::ostream& stream ) {
-  stream << "\t \t Name: " << fName
-	 << std::endl;
+
+  stream << "\t \t Name: " << fName << std::endl;
+  
+  if( fHistoName != "" ) {
+    stream << "\t \t "
+	   << " Shape Hist Name: " << fHistoName
+	   << " Shape Hist Path Name: " << fHistoPath
+	   << " Shape Hist FileName: " << fInputFile
+	   << std::endl;
+  }
+
+  if( fConstant ) { stream << "\t \t ( Constant ): " << std::endl; }
+
 }
 
 
-// Stat Error
+void RooStats::HistFactory::ShapeFactor::writeToFile( const std::string& FileName, 
+						      const std::string& DirName ) {
+
+  if( HasInitialShape() ) {
+    TH1* histInitialShape = GetInitialShape();
+    if( histInitialShape==NULL ) {
+      std::cout << "Error: Cannot write " << GetName()
+		<< " to file: " << FileName
+		<< " InitialShape is NULL" 
+		<< std::endl;
+      throw hf_exc();
+    }
+    histInitialShape->Write();
+    fInputFile = FileName;
+    fHistoPath = DirName;
+    fHistoName = histInitialShape->GetName(); 
+  }
+
+  return;
+
+}
+
+
+void RooStats::HistFactory::ShapeFactor::PrintXML( std::ostream& xml ) {
+  xml << "      <ShapeFactor Name=\"" << GetName() << "\" ";
+  if( fHasInitialShape ) {
+    xml << " InputFile=\""  << GetInputFile()  << "\" "
+	<< " HistoName=\""  << GetHistoName()  << "\" "
+	<< " HistoPath=\""  << GetHistoPath()  << "\" ";
+  }
+  xml << "  /> " << std::endl;
+}
 
 
+// Stat Error Config
 void RooStats::HistFactory::StatErrorConfig::Print( std::ostream& stream ) {
   stream << "\t \t RelErrorThreshold: " << fRelErrorThreshold
 	 << "\t ConstraintType: " << Constraint::Name( fConstraintType )
 	 << std::endl;
 }  
 
+void RooStats::HistFactory::StatErrorConfig::PrintXML( std::ostream& xml ) {
+  xml << "    <StatErrorConfig RelErrorThreshold=\"" << GetRelErrorThreshold() 
+      << "\" "
+      << "ConstraintType=\"" << Constraint::Name( GetConstraintType() ) 
+      << "\" "
+      << "/> " << std::endl << std::endl;
+
+}
+
+
+// Stat Error
 TH1* RooStats::HistFactory::StatError::GetErrorHist() {
   return (TH1*) fhError.GetObject();
 }
@@ -246,7 +374,23 @@ void RooStats::HistFactory::StatError::Print( std::ostream& stream ) {
 	 << std::endl;
 }  
 
-void RooStats::HistFactory::StatError::writeToFile( std::string OutputFileName, std::string DirName ) {
+void RooStats::HistFactory::StatError::PrintXML( std::ostream& xml ) {
+
+  if( GetActivate() ) {
+    xml << "      <StatError Activate=\"" 
+	<< (GetActivate() ? std::string("True") : std::string("False"))  
+	<< "\" "
+	<< " InputFile=\"" << GetInputFile() << "\" "
+	<< " HistoName=\"" << GetHistoName() << "\" "
+	<< " HistoPath=\"" << GetHistoPath() << "\" "
+	<< " /> " << std::endl;
+  }
+
+}
+
+
+void RooStats::HistFactory::StatError::writeToFile( const std::string& OutputFileName, 
+						    const std::string& DirName ) {
 
   if( fUseHisto ) {
     
diff --git a/roofit/histfactory/src/hist2workspace.cxx b/roofit/histfactory/src/hist2workspace.cxx
index 1a5ae95..02228c7 100644
--- a/roofit/histfactory/src/hist2workspace.cxx
+++ b/roofit/histfactory/src/hist2workspace.cxx
@@ -1,19 +1,68 @@
+// @(#)root/roostats:$Id$
+// Author: Kyle Cranmer, George Lewis 
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//_________________________________________________
+/*
+BEGIN_HTML
+<p>
+</p>
+END_HTML
+*/
+//
 
 #include <string>
 #include <exception>
+#include <vector>
 
 //void topDriver(string input); // in MakeModelAndMeasurements
 //void fastDriver(string input); // in MakeModelAndMeasurementsFast
 
 //#include "RooStats/HistFactory/MakeModelAndMeasurements.h"
+#include "RooStats/HistFactory/ConfigParser.h"
 #include "RooStats/HistFactory/MakeModelAndMeasurementsFast.h"
 
 //_____________________________batch only_____________________
 #ifndef __CINT__
 
+namespace RooStats {
+  namespace HistFactory {
+    void fastDriver(std::string input) {
+
+      // Create the initial list of measurements and channels
+      std::vector< HistFactory::Measurement > measurement_list;
+      // std::vector< HistFactory::Channel >     channel_list;
+
+      // Fill them using the XML parser
+      HistFactory::ConfigParser xmlParser;
+      measurement_list = xmlParser.GetMeasurementsFromXML( input );
+	
+      // At this point, we have all the information we need
+      // from the xml files.
+
+      // We will make the measurements 1-by-1
+      for(unsigned int i = 0; i < measurement_list.size(); ++i) {
+	HistFactory::Measurement measurement = measurement_list.at(i);
+	measurement.CollectHistograms();
+	MakeModelAndMeasurementFast( measurement );
+      }
+
+      return;
+
+    }
+  } // namespace RooStats
+} // namespace HistFactory
+
+
 int main(int argc, char** argv) {
 
-  if( !(argc>1) ) {
+  if( !(argc > 1) ) {
     std::cerr << "need input file" << std::endl;
     exit(1);
   }
@@ -21,13 +70,18 @@ int main(int argc, char** argv) {
   if(argc==2){
     std::string input(argv[1]);
     try {
-      fastDriver(input);
+      RooStats::HistFactory::fastDriver(input);
     }
-    catch (std::string str) {
-      std::cerr << "caught exception: " << str << std::endl ;
+    catch(std::string str) {
+      std::cerr << "hist2workspace - Caught exception: " << str << std::endl ;
+      exit(1);
     }
     catch( const std::exception& e ) {
-      std::cerr << "Caught Exception: " << e.what() << std::endl;
+      std::cerr << "hist2workspace - Caught Exception: " << e.what() << std::endl;
+      exit(1);
+    }
+    catch(...) {
+      exit(1);
     }
   }
   
@@ -37,19 +91,26 @@ int main(int argc, char** argv) {
 
     if(flag=="-standard_form") {
       try {
-	fastDriver(input);
+	RooStats::HistFactory::fastDriver(input);
       }
-      catch (std::string str) {
-	std::cerr << "caught exception: " << str << std::endl ;
+      catch(std::string str) {
+	std::cerr << "hist2workspace - Caught exception: " << str << std::endl ;
+	exit(1);
       }
       catch( const std::exception& e ) {
-	std::cerr << "Caught Exception: " << e.what() << std::endl;
+	std::cerr << "hist2workspace - Caught Exception: " << e.what() << std::endl;
+	exit(1);
+      }
+      catch(...) {
+	std::cerr << "hist2workspace - Caught Exception" << std::endl;
+	exit(1);
       }
     }
       
     else if(flag=="-number_counting_form") {
+      std::cout << "ERROR: 'number_counting_form' is now depricated." << std::endl;
+      /*
       try {
-	std::cout << "ERROR: 'number_counting_form' is now depricated." << std::endl;
 	//topDriver(input);
       }
       catch (std::string str) {
@@ -57,14 +118,19 @@ int main(int argc, char** argv) {
       }
       catch( const std::exception& e ) {
 	std::cerr << "Caught Exception: " << e.what() << std::endl;
-      }
+	}
+      */
+      return 255;
     }
     
     else {
-      std::cerr <<"unrecognized flag.  Options are -standard_form or -number_counting_form"<<std::endl;
+      std::cerr << "Unrecognized flag.  " << std::endl;
+      return 255;
     }
   }
+
   return 0;
+
 }
 
 #endif
diff --git a/roofit/roofit/inc/RooChebychev.h b/roofit/roofit/inc/RooChebychev.h
index 48460c2..d270133 100644
--- a/roofit/roofit/inc/RooChebychev.h
+++ b/roofit/roofit/inc/RooChebychev.h
@@ -42,6 +42,7 @@ private:
   RooListProxy _coefList ;
 
   Double_t evaluate() const;
+  Double_t evalAnaInt(const Double_t x) const;
 
   ClassDef(RooChebychev,1) // Chebychev polynomial PDF
 };
diff --git a/roofit/roofit/inc/RooGExpModel.h b/roofit/roofit/inc/RooGExpModel.h
index c3d36fe..7e2d01c 100644
--- a/roofit/roofit/inc/RooGExpModel.h
+++ b/roofit/roofit/inc/RooGExpModel.h
@@ -16,9 +16,12 @@
 #ifndef ROO_GEXP_MODEL
 #define ROO_GEXP_MODEL
 
+#include <cmath>
+#include <complex>
+
+#include "Rtypes.h"
 #include "RooResolutionModel.h"
 #include "RooRealProxy.h"
-#include "RooComplex.h"
 #include "RooMath.h"
 
 class RooGExpModel : public RooResolutionModel {
@@ -76,35 +79,24 @@ protected:
   //Double_t calcDecayConv(Double_t sign, Double_t tau, Double_t sig, Double_t rtau) const ;
   Double_t calcDecayConv(Double_t sign, Double_t tau, Double_t sig, Double_t rtau, Double_t fsign) const ;  
 	// modified FMV,08/13/03
-  RooComplex calcSinConv(Double_t sign, Double_t sig, Double_t tau, Double_t omega, Double_t rtau, Double_t fsign) const ;
+  std::complex<Double_t> calcSinConv(Double_t sign, Double_t sig, Double_t tau, Double_t omega, Double_t rtau, Double_t fsign) const ;
   Double_t calcSinConv(Double_t sign, Double_t sig, Double_t tau, Double_t rtau, Double_t fsign) const ;
-  RooComplex calcSinConvNorm(Double_t sign, Double_t tau, Double_t omega, 
+  std::complex<Double_t> calcSinConvNorm(Double_t sign, Double_t tau, Double_t omega, 
 	                     Double_t sig, Double_t rtau, Double_t fsign, const char* rangeName) const ; // modified FMV,07/24/03
   Double_t calcSinConvNorm(Double_t sign, Double_t tau, 
         Double_t sig, Double_t rtau, Double_t fsign, const char* rangeName) const ; // added FMV,08/18/03
   //Double_t calcSinhConv(Double_t sign, Double_t sign1, Double_t sign2, Double_t tau, Double_t dgamma, Double_t sig, Double_t rtau, Double_t fsign) const ;
   //Double_t calcCoshConv(Double_t sign, Double_t tau, Double_t dgamma, Double_t sig, Double_t rtau, Double_t fsign) const ;
   virtual Double_t evaluate() const ;
-  RooComplex evalCerfApprox(Double_t swt, Double_t u, Double_t c) const ;
+  static std::complex<Double_t> evalCerfApprox(Double_t swt, Double_t u, Double_t c);
 
   // Calculate exp(-u^2) cwerf(swt*c + i(u+c)), taking care of numerical instabilities
-  inline RooComplex evalCerf(Double_t swt, Double_t u, Double_t c) const {
-    RooComplex z(swt*c,u+c);
-    return (z.im()>-4.0) ? RooMath::FastComplexErrFunc(z)*exp(-u*u) : evalCerfApprox(swt,u,c) ;
+  static inline std::complex<Double_t> evalCerf(Double_t swt, Double_t u, Double_t c)
+  {
+    std::complex<Double_t> z(swt*c,u+c);
+    return (z.imag()>-4.0) ? RooMath::faddeeva_fast(z)*std::exp(-u*u) : evalCerfApprox(swt,u,c) ;
   }
     
-  // Calculate Re(exp(-u^2) cwerf(swt*c + i(u+c))), taking care of numerical instabilities
-  inline Double_t evalCerfRe(Double_t swt, Double_t u, Double_t c) const {
-    RooComplex z(swt*c,u+c);
-    return (z.im()>-4.0) ? RooMath::FastComplexErrFuncRe(z)*exp(-u*u) : evalCerfApprox(swt,u,c).re() ;
-  }
-  
-  // Calculate Im(exp(-u^2) cwerf(swt*c + i(u+c))), taking care of numerical instabilities
-  inline Double_t evalCerfIm(Double_t swt, Double_t u, Double_t c) const {
-    RooComplex z(swt*c,u+c);
-    return (z.im()>-4.0) ? RooMath::FastComplexErrFuncIm(z)*exp(-u*u) : evalCerfApprox(swt,u,c).im() ;
-  }
-
   // Calculate Re(exp(-u^2) cwerf(i(u+c)))
   // added FMV, 08/17/03
   inline Double_t evalCerfRe(Double_t u, Double_t c) const {
@@ -118,7 +110,7 @@ protected:
 
   // Calculate common normalization factors 
   // added FMV,07/24/03
-  RooComplex evalCerfInt(Double_t sign, Double_t wt, Double_t tau, Double_t umin, Double_t umax, Double_t c) const ;
+  std::complex<Double_t> evalCerfInt(Double_t sign, Double_t wt, Double_t tau, Double_t umin, Double_t umax, Double_t c) const ;
   Double_t evalCerfInt(Double_t sign, Double_t tau, Double_t umin, Double_t umax, Double_t c) const ;
 
   RooRealProxy sigma ;
diff --git a/roofit/roofit/inc/RooGaussModel.h b/roofit/roofit/inc/RooGaussModel.h
index d8297d7..2896068 100644
--- a/roofit/roofit/inc/RooGaussModel.h
+++ b/roofit/roofit/inc/RooGaussModel.h
@@ -16,9 +16,11 @@
 #ifndef ROO_GAUSS_MODEL
 #define ROO_GAUSS_MODEL
 
+#include <cmath>
+#include <complex>
+
 #include "RooResolutionModel.h"
 #include "RooRealProxy.h"
-#include "RooComplex.h"
 #include "RooMath.h"
 
 class RooGaussModel : public RooResolutionModel {
@@ -61,28 +63,17 @@ public:
 protected:
 
   virtual Double_t evaluate() const ;
-  RooComplex evalCerfApprox(Double_t swt, Double_t u, Double_t c) const ;
+  static std::complex<Double_t> evalCerfApprox(Double_t swt, Double_t u, Double_t c);
 
   // Calculate exp(-u^2) cwerf(swt*c + i(u+c)), taking care of numerical instabilities
-  inline RooComplex evalCerf(Double_t swt, Double_t u, Double_t c) const {
-    RooComplex z(swt*c,u+c);
-    return (z.im()>-4.0) ? RooMath::FastComplexErrFunc(z)*exp(-u*u) : evalCerfApprox(swt,u,c) ;
+  static inline std::complex<Double_t> evalCerf(Double_t swt, Double_t u, Double_t c)
+  {
+    std::complex<Double_t> z(swt*c,u+c);
+    return (z.imag()>-4.0) ? (std::exp(-u*u)*RooMath::faddeeva_fast(z)) : evalCerfApprox(swt,u,c);
   }
     
-  // Calculate Re(exp(-u^2) cwerf(swt*c + i(u+c))), taking care of numerical instabilities
-  inline Double_t evalCerfRe(Double_t swt, Double_t u, Double_t c) const {
-    RooComplex z(swt*c,u+c);
-    return (z.im()>-4.0) ? RooMath::FastComplexErrFuncRe(z)*exp(-u*u) : evalCerfApprox(swt,u,c).re() ;
-  }
-  
-  // Calculate Im(exp(-u^2) cwerf(swt*c + i(u+c))), taking care of numerical instabilities
-  inline Double_t evalCerfIm(Double_t swt, Double_t u, Double_t c) const {
-    RooComplex z(swt*c,u+c);
-    return (z.im()>-4.0) ? RooMath::FastComplexErrFuncIm(z)*exp(-u*u) : evalCerfApprox(swt,u,c).im() ;
-  }
-
   // Calculate common normalization factors 
-  RooComplex evalCerfInt(Double_t sign, Double_t wt, Double_t tau, Double_t umin, Double_t umax, Double_t c) const ;
+  std::complex<Double_t> evalCerfInt(Double_t sign, Double_t wt, Double_t tau, Double_t umin, Double_t umax, Double_t c) const;
 
   Bool_t _flatSFInt ;
 
diff --git a/roofit/roofit/inc/RooKeysPdf.h b/roofit/roofit/inc/RooKeysPdf.h
index 6c5662a..2593e15 100644
--- a/roofit/roofit/inc/RooKeysPdf.h
+++ b/roofit/roofit/inc/RooKeysPdf.h
@@ -35,6 +35,12 @@ public:
   RooKeysPdf(const RooKeysPdf& other, const char* name=0);
   virtual TObject* clone(const char* newname) const {return new RooKeysPdf(*this,newname); }
   virtual ~RooKeysPdf();
+
+  virtual Int_t getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars,
+	  const char* rangeName = 0) const;
+  virtual Double_t analyticalIntegral(Int_t code, const char* rangeName = 0) const;
+  virtual Int_t getMaxVal(const RooArgSet& vars) const;
+  virtual Double_t maxVal(Int_t code) const;
   
   void LoadDataSet( RooDataSet& data);
 
diff --git a/roofit/roofit/src/RooChebychev.cxx b/roofit/roofit/src/RooChebychev.cxx
index f278904..2cf724d 100644
--- a/roofit/roofit/src/RooChebychev.cxx
+++ b/roofit/roofit/src/RooChebychev.cxx
@@ -20,18 +20,26 @@
 // END_HTML
 //
 
+#include <cmath>
+#include <iostream>
+
 #include "RooFit.h"
 
 #include "Riostream.h"
-#include "Riostream.h"
-#include <math.h>
 
 #include "RooChebychev.h"
 #include "RooAbsReal.h"
 #include "RooRealVar.h"
 #include "RooArgList.h"
 
-using namespace std;
+#if defined(__my_func__)
+#undef __my_func__
+#endif
+#if defined(WIN32)
+#define __my_func__ __FUNCTION__
+#else
+#define __my_func__ __func__
+#endif
 
 ClassImp(RooChebychev)
 ;
@@ -55,8 +63,9 @@ RooChebychev::RooChebychev(const char* name, const char* title,
   RooAbsArg* coef ;
   while((coef = (RooAbsArg*)coefIter->Next())) {
     if (!dynamic_cast<RooAbsReal*>(coef)) {
-      cout << "RooChebychev::ctor(" << GetName() << ") ERROR: coefficient " << coef->GetName() 
-	   << " is not of type RooAbsReal" << endl ;
+	std::cerr << "RooChebychev::ctor(" << GetName() <<
+	    ") ERROR: coefficient " << coef->GetName() <<
+	    " is not of type RooAbsReal" << std::endl ;
       assert(0) ;
     }
     _coefList.add(*coef) ;
@@ -74,11 +83,11 @@ RooChebychev::RooChebychev(const RooChebychev& other, const char* name) :
 {
 }
 
-inline static double p0(double ,double a) {  return a; }
-inline static double p1(double t,double a,double b) {  return a*t+b; }
-inline static double p2(double t,double a,double b,double c) {  return p1(t,p1(t,a,b),c); }
-inline static double p3(double t,double a,double b,double c,double d) {  return p2(t,p1(t,a,b),c,d); }
-inline static double p4(double t,double a,double b,double c,double d,double e) {  return p3(t,p1(t,a,b),c,d,e); }
+inline static double p0(double ,double a) { return a; }
+inline static double p1(double t,double a,double b) { return a*t+b; }
+inline static double p2(double t,double a,double b,double c) { return p1(t,p1(t,a,b),c); }
+inline static double p3(double t,double a,double b,double c,double d) { return p2(t,p1(t,a,b),c,d); }
+inline static double p4(double t,double a,double b,double c,double d,double e) { return p3(t,p1(t,a,b),c,d,e); }
 
 
 //_____________________________________________________________________________
@@ -97,20 +106,19 @@ Double_t RooChebychev::evaluate() const
   case  3: sum+=((RooAbsReal&)_coefList[2]).getVal()*x*p1(x2,4,-3);
   case  2: sum+=((RooAbsReal&)_coefList[1]).getVal()*p1(x2,2,-1);
   case  1: sum+=((RooAbsReal&)_coefList[0]).getVal()*x;
-  case  0: sum+=1;
+  case  0: sum+=1; break;
+  default: std::cerr << "In " << __my_func__ << " (" << __FILE__ << ", line " <<
+	       __LINE__ << "): Higher order Chebychev polynomials currently "
+	       "unimplemented." << std::endl;
+	   assert(false);
   }
   return sum;
 }
 
 
 //_____________________________________________________________________________
-Int_t RooChebychev::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* rangeName) const 
+Int_t RooChebychev::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /* rangeName */) const 
 {
-  // No analytical calculation available (yet) of integrals over subranges
-  if (rangeName && strlen(rangeName)) {
-    return 0 ;
-  }
-
   if (matchArgs(allVars, analVars, _x)) return 1;
   return 0;
 }
@@ -119,19 +127,48 @@ Int_t RooChebychev::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVar
 //_____________________________________________________________________________
 Double_t RooChebychev::analyticalIntegral(Int_t code, const char* rangeName) const 
 {
-  assert(code==1) ;
-  // WVE check that this works all right for sub ranges
-  Double_t xmin = _x.min(rangeName); Double_t xmax = _x.max(rangeName);
-  Double_t norm(0) ;
-  switch(_coefList.getSize()) {
-  // coverity[MISSING_BREAK]
-  case  7: case  6: norm+=((RooAbsReal&)_coefList[5]).getVal()*(-1 + 18./3. - 48./5. + 32./7.);
-  // coverity[MISSING_BREAK]
-  case  5: case  4: norm+=((RooAbsReal&)_coefList[3]).getVal()*( 1 -  8./3. +  8./5.);
-  // coverity[MISSING_BREAK]
-  case  3: case  2: norm+=((RooAbsReal&)_coefList[1]).getVal()*(-1 +  2./3.);
-  case  1: case  0: norm+= 1;
+  assert(1 == code);
+
+  // the full range of the function is mapped to the normalised [-1, 1] range
+  const Double_t xminfull(_x.min()), xmaxfull(_x.max());
+  const Double_t fullRange = xmaxfull - xminfull;
+
+  // define limits of the integration range on a normalised scale
+  Double_t minScaled = -1., maxScaled = +1.;
+
+  // check to see if integral of a subrange is requested
+  if (rangeName && 0 != rangeName[0]) {
+    assert(xminfull <= _x.min(rangeName) && _x.min(rangeName) <= xmaxfull);
+    assert(xminfull <= _x.max(rangeName) && _x.max(rangeName) <= xmaxfull);
+    minScaled = -1. + 2. * (_x.min(rangeName) - xminfull) / fullRange;
+    maxScaled = +1. - 2. * (xmaxfull - _x.max(rangeName)) / fullRange;
   }
-  norm *= xmax-xmin;
-  return norm;
+
+  // return half of the range since the normalised range runs from -1 to 1
+  // which has a range of two
+  return 0.5 * fullRange * (evalAnaInt(maxScaled) - evalAnaInt(minScaled));
 }
+
+Double_t RooChebychev::evalAnaInt(const Double_t x) const
+{
+  const Double_t x2 = x * x;
+  Double_t sum = 0.;
+  switch (_coefList.getSize()) {
+    case  7: sum+=((RooAbsReal&)_coefList[6]).getVal()*x2*p3(x2,8.,-112./6.,14.,-7./2.);
+    case  6: sum+=((RooAbsReal&)_coefList[5]).getVal()*x*p3(x2,32./7.,-48./5.,6.,-1.);
+    case  5: sum+=((RooAbsReal&)_coefList[4]).getVal()*x2*p2(x2,16./6.,-5.,2.5);
+    case  4: sum+=((RooAbsReal&)_coefList[3]).getVal()*x*p2(x2,8./5.,-8./3.,1.);
+    case  3: sum+=((RooAbsReal&)_coefList[2]).getVal()*x2*p1(x2,1.,-3./2.);
+    case  2: sum+=((RooAbsReal&)_coefList[1]).getVal()*x*p1(x2,2./3.,-1.);
+    case  1: sum+=((RooAbsReal&)_coefList[0]).getVal()*x2*.5;
+    case  0: sum+=x; break;
+	     
+    default: std::cerr << "In " << __my_func__ << " (" << __FILE__ << ", line " <<
+	     __LINE__ << "): Higher order Chebychev polynomials currently "
+		 "unimplemented." << std::endl;
+	     assert(false);
+  }
+  return sum;
+}
+
+#undef __my_func__
diff --git a/roofit/roofit/src/RooGExpModel.cxx b/roofit/roofit/src/RooGExpModel.cxx
index 32ee9da..8f4fb9a 100644
--- a/roofit/roofit/src/RooGExpModel.cxx
+++ b/roofit/roofit/src/RooGExpModel.cxx
@@ -187,7 +187,7 @@ Double_t RooGExpModel::evaluate() const
     //Double_t xprime = x/rtau ;
     //Double_t c = sig/(root2*rtau) ;
     //Double_t u = xprime/(2*c) ;
-    //Double_t result = 0.5*evalCerfRe(fsign*u,c) ;  // sign=-1 ! 
+    //Double_t result = 0.5*evalCerf(fsign*u,c).real() ;  // sign=-1 ! 
 
     if (_basisCode!=0 && basisSign==Both) result *= 2 ;
     //cout << "1st form " << "x= " << x << " result= " << result << endl;
@@ -219,8 +219,8 @@ Double_t RooGExpModel::evaluate() const
 			     << omega << ", tau = " << tau << endl ;
     Double_t result(0) ;
     if (wt==0.) return result ;
-    if (basisSign!=Minus) result += -1*calcSinConv(+1,sig,tau,omega,rtau,fsign).im() ;
-    if (basisSign!=Plus) result += -1*calcSinConv(-1,sig,tau,omega,rtau,fsign).im() ;
+    if (basisSign!=Minus) result += -1*calcSinConv(+1,sig,tau,omega,rtau,fsign).imag() ;
+    if (basisSign!=Plus) result += -1*calcSinConv(-1,sig,tau,omega,rtau,fsign).imag() ;
     //cout << "4th form " << "x= " << x << " result= " << result << endl;
     return result ;
   }
@@ -230,8 +230,8 @@ Double_t RooGExpModel::evaluate() const
     if (verboseEval()>2) cout << "RooGExpModel::evaluate(" << GetName() 
 			     << ") 5th form omega = " << omega << ", tau = " << tau << endl ;
     Double_t result(0) ;
-    if (basisSign!=Minus) result += calcSinConv(+1,sig,tau,omega,rtau,fsign).re() ;
-    if (basisSign!=Plus) result += calcSinConv(-1,sig,tau,omega,rtau,fsign).re() ;
+    if (basisSign!=Minus) result += calcSinConv(+1,sig,tau,omega,rtau,fsign).real() ;
+    if (basisSign!=Plus) result += calcSinConv(-1,sig,tau,omega,rtau,fsign).real() ;
     //cout << "5th form " << "x= " << x << " result= " << result << endl;
     return result ;  
   }
@@ -303,7 +303,7 @@ Double_t RooGExpModel::logErfC(Double_t xx) const
 
 
 //_____________________________________________________________________________
-RooComplex RooGExpModel::calcSinConv(Double_t sign, Double_t sig, Double_t tau, Double_t omega, Double_t rtau, Double_t fsign) const
+std::complex<Double_t> RooGExpModel::calcSinConv(Double_t sign, Double_t sig, Double_t tau, Double_t omega, Double_t rtau, Double_t fsign) const
 {
   static Double_t root2(sqrt(2.)) ;
 
@@ -316,11 +316,11 @@ RooComplex RooGExpModel::calcSinConv(Double_t sign, Double_t sig, Double_t tau,
   Double_t u2= fsign*s2/(2*c2) ;
   //Double_t u2= s2/(2*c2) ;
 
-  RooComplex eins(1,0);
-  RooComplex k(1/tau,sign*omega);  
+  std::complex<Double_t> eins(1,0);
+  std::complex<Double_t> k(1/tau,sign*omega);  
   //return (evalCerf(-sign*omega*tau,u1,c1)+evalCerf(0,u2,c2)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
 
-  return (evalCerf(-sign*omega*tau,u1,c1)+RooComplex(evalCerfRe(u2,c2),0)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
+  return (evalCerf(-sign*omega*tau,u1,c1)+std::complex<Double_t>(evalCerfRe(u2,c2),0)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
   // equivalent form, added FMV, 07/24/03
   //return (evalCerf(-sign*omega*tau,-sign*u1,c1)+evalCerf(0,fsign*u2,c2)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
 }
@@ -346,7 +346,7 @@ Double_t RooGExpModel::calcSinConv(Double_t sign, Double_t sig, Double_t tau, Do
   Double_t k(1/tau);  
   return (evalCerfRe(u1,c1)+evalCerfRe(u2,c2)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
   // equivalent form, added FMV, 07/24/03
-  //return (evalCerfRe(-sign*u1,c1)+evalCerfRe(fsign*u2,c2)*fsign*sign) / (eins + k*fsign*sign*rtau) ;
+  //return (evalCerf(-sign*u1,c1).real()+evalCerf(fsign*u2,c2).real()*fsign*sign) / (eins + k*fsign*sign*rtau) ;
 }
 
 
@@ -623,11 +623,11 @@ Double_t RooGExpModel::analyticalIntegral(Int_t code, const char* rangeName) con
     //cout << "sin integral" << endl;
     Double_t result(0) ;
     if (wt==0) return result ;
-    //if (basisSign!=Minus) result += calcSinConvNorm(+1,tau,omega).im() ;
-    //if (basisSign!=Plus) result += calcSinConvNorm(-1,tau,omega).im() ;
+    //if (basisSign!=Minus) result += calcSinConvNorm(+1,tau,omega).imag() ;
+    //if (basisSign!=Plus) result += calcSinConvNorm(-1,tau,omega).imag() ;
     // finite+asymtotic normalization, added FMV, 07/24/03
-    if (basisSign!=Minus) result += -1*calcSinConvNorm(+1,tau,omega,sig,rtau,fsign,rangeName).im();
-    if (basisSign!=Plus) result += -1*calcSinConvNorm(-1,tau,omega,sig,rtau,fsign,rangeName).im();
+    if (basisSign!=Minus) result += -1*calcSinConvNorm(+1,tau,omega,sig,rtau,fsign,rangeName).imag();
+    if (basisSign!=Plus) result += -1*calcSinConvNorm(-1,tau,omega,sig,rtau,fsign,rangeName).imag();
     //cout << "Integral 4th form " << " result= " << result*ssfInt << endl;
     return result*ssfInt ;
   }
@@ -638,11 +638,11 @@ Double_t RooGExpModel::analyticalIntegral(Int_t code, const char* rangeName) con
 			     << ") 5th form omega = " << omega << ", tau = " << tau << endl ;
     //cout << "cos integral" << endl;
     Double_t result(0) ;
-    //if (basisSign!=Minus) result += calcSinConvNorm(+1,tau,omega).re() ;
-    //if (basisSign!=Plus) result += calcSinConvNorm(-1,tau,omega).re() ;
+    //if (basisSign!=Minus) result += calcSinConvNorm(+1,tau,omega).real() ;
+    //if (basisSign!=Plus) result += calcSinConvNorm(-1,tau,omega).real() ;
     // finite+asymtotic normalization, added FMV, 07/24/03
-    if (basisSign!=Minus) result += calcSinConvNorm(+1,tau,omega,sig,rtau,fsign,rangeName).re();
-    if (basisSign!=Plus) result += calcSinConvNorm(-1,tau,omega,sig,rtau,fsign,rangeName).re();
+    if (basisSign!=Minus) result += calcSinConvNorm(+1,tau,omega,sig,rtau,fsign,rangeName).real();
+    if (basisSign!=Plus) result += calcSinConvNorm(-1,tau,omega,sig,rtau,fsign,rangeName).real();
     //cout << "Integral 5th form " << " result= " << result*ssfInt << endl;
     return result*ssfInt ;
   }
@@ -696,11 +696,11 @@ Double_t RooGExpModel::analyticalIntegral(Int_t code, const char* rangeName) con
 // modified FMV, 07/24/03. Finite+asymtotic normalization
 
 //_____________________________________________________________________________
-RooComplex RooGExpModel::calcSinConvNorm(Double_t sign, Double_t tau, Double_t omega, 
+std::complex<Double_t> RooGExpModel::calcSinConvNorm(Double_t sign, Double_t tau, Double_t omega, 
 					 Double_t sig, Double_t rtau, Double_t fsign, const char* rangeName) const
 {
   //  old code (asymptotic normalization only)
-  //  RooComplex z(1/tau,sign*omega);
+  //  std::complex<Double_t> z(1/tau,sign*omega);
   //  return z*2/(omega*omega+1/(tau*tau));
 
   static Double_t root2(sqrt(2.)) ;
@@ -716,11 +716,11 @@ RooComplex RooGExpModel::calcSinConvNorm(Double_t sign, Double_t tau, Double_t o
   Double_t umin2= smin2/(2*c2) ;
   Double_t umax2= smax2/(2*c2) ;
 
-  RooComplex eins(1,0);
-  RooComplex k(1/tau,sign*omega);
-  RooComplex term1 = evalCerfInt(sign,-sign*omega*tau, tau, -sign*umin1, -sign*umax1, c1);
-  //RooComplex term2 = evalCerfInt(-fsign,0., rtau, fsign*umin2, fsign*umax2, c2)*RooComplex(fsign*sign,0);
-  RooComplex term2 = RooComplex(evalCerfInt(-fsign, rtau, fsign*umin2, fsign*umax2, c2)*fsign*sign,0);
+  std::complex<Double_t> eins(1,0);
+  std::complex<Double_t> k(1/tau,sign*omega);
+  std::complex<Double_t> term1 = evalCerfInt(sign,-sign*omega*tau, tau, -sign*umin1, -sign*umax1, c1);
+  //std::complex<Double_t> term2 = evalCerfInt(-fsign,0., rtau, fsign*umin2, fsign*umax2, c2)*std::complex<Double_t>(fsign*sign,0);
+  std::complex<Double_t> term2 = std::complex<Double_t>(evalCerfInt(-fsign, rtau, fsign*umin2, fsign*umax2, c2)*fsign*sign,0);
   return (term1+term2)/(eins + k*fsign*sign*rtau) ;
 }
 
@@ -761,15 +761,15 @@ Double_t RooGExpModel::calcSinConvNorm(Double_t sign, Double_t tau, Double_t sig
 
 // added FMV, 07/24/03
 //_____________________________________________________________________________
-RooComplex RooGExpModel::evalCerfInt(Double_t sign, Double_t wt, Double_t tau, Double_t umin, Double_t umax, Double_t c) const
+std::complex<Double_t> RooGExpModel::evalCerfInt(Double_t sign, Double_t wt, Double_t tau, Double_t umin, Double_t umax, Double_t c) const
 {
-  RooComplex diff;
+  std::complex<Double_t> diff;
   if (_asympInt) {
-    diff = RooComplex(2,0) ;
+    diff = std::complex<Double_t>(2,0) ;
   } else {
-    diff = RooComplex(sign,0.)*(evalCerf(wt,umin,c) - evalCerf(wt,umax,c) + RooMath::erf(umin) - RooMath::erf(umax));
+    diff = std::complex<Double_t>(sign,0.)*(evalCerf(wt,umin,c) - evalCerf(wt,umax,c) + RooMath::erf(umin) - RooMath::erf(umax));
   }
-  return RooComplex(tau/(1.+wt*wt),0)*RooComplex(1,wt)*diff;
+  return std::complex<Double_t>(tau/(1.+wt*wt),0)*std::complex<Double_t>(1,wt)*diff;
 }
 // added FMV, 08/17/03. Modified FMV, 08/30/03
 
@@ -793,19 +793,19 @@ Double_t RooGExpModel::evalCerfInt(Double_t sign, Double_t tau, Double_t umin, D
 
 
 //_____________________________________________________________________________
-RooComplex RooGExpModel::evalCerfApprox(Double_t swt, Double_t u, Double_t c) const
+std::complex<Double_t> RooGExpModel::evalCerfApprox(Double_t swt, Double_t u, Double_t c)
 {
   // use the approximation: erf(z) = exp(-z*z)/(sqrt(pi)*z)
   // to explicitly cancel the divergent exp(y*y) behaviour of
   // CWERF for z = x + i y with large negative y
 
   static Double_t rootpi= sqrt(atan2(0.,-1.));
-  RooComplex z(swt*c,u+c);  
-  RooComplex zc(u+c,-swt*c);
-  RooComplex zsq= z*z;
-  RooComplex v= -zsq - u*u;
+  std::complex<Double_t> z(swt*c,u+c);  
+  std::complex<Double_t> zc(u+c,-swt*c);
+  std::complex<Double_t> zsq= z*z;
+  std::complex<Double_t> v= -zsq - u*u;
 
-  return v.exp()*(-zsq.exp()/(zc*rootpi) + 1)*2 ;
+  return std::exp(v)*(-std::exp(zsq)/(zc*rootpi) + 1.)*2.;
 }
 
 
diff --git a/roofit/roofit/src/RooGaussModel.cxx b/roofit/roofit/src/RooGaussModel.cxx
index 3987a5a..5b58d34 100644
--- a/roofit/roofit/src/RooGaussModel.cxx
+++ b/roofit/roofit/src/RooGaussModel.cxx
@@ -29,7 +29,6 @@
 #include "Riostream.h"
 #include "Riostream.h"
 #include "RooGaussModel.h"
-#include "RooMath.h"
 #include "RooRealConstant.h"
 #include "RooRandom.h"
 
@@ -140,9 +139,9 @@ Double_t RooGaussModel::evaluate() const
   //cout << "RooGaussModel::evaluate(" << GetName() << ") basisCode = " << _basisCode << endl ;
   
   // *** 1st form: Straight Gaussian, used for unconvoluted PDF or expBasis with 0 lifetime ***
-  static Double_t root2(sqrt(2.)) ;
-  static Double_t root2pi(sqrt(2*atan2(0.,-1.))) ;
-  static Double_t rootpi(sqrt(atan2(0.,-1.))) ;
+  static Double_t root2(std::sqrt(2.)) ;
+  static Double_t root2pi(std::sqrt(2.*std::atan2(0.,-1.))) ;
+  static Double_t rootpi(std::sqrt(std::atan2(0.,-1.))) ;
 
   BasisType basisType = (BasisType)( (_basisCode == 0) ? 0 : (_basisCode/10) + 1 );
   BasisSign basisSign = (BasisSign)( _basisCode - 10*(basisType-1) - 2 ) ;
@@ -157,7 +156,7 @@ Double_t RooGaussModel::evaluate() const
     Double_t xprime = (x-(mean*msf))/(sigma*ssf) ;
     if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 1st form" << endl ;
     
-    Double_t result = exp(-0.5*xprime*xprime)/(sigma*ssf*root2pi) ;
+    Double_t result = std::exp(-0.5*xprime*xprime)/(sigma*ssf*root2pi) ;
     if (_basisCode!=0 && basisSign==Both) result *= 2 ;
     return result ;
   }
@@ -180,8 +179,8 @@ Double_t RooGaussModel::evaluate() const
   if (basisType==expBasis || (basisType==cosBasis && _x==0.)) {
     if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 3d form tau=" << tau << endl ;
     Double_t result(0) ;
-    if (basisSign!=Minus) result += evalCerfRe(0,-u,c) ; 
-    if (basisSign!=Plus)  result += evalCerfRe(0, u,c) ; 
+    if (basisSign!=Minus) result += evalCerf(0,-u,c).real(); 
+    if (basisSign!=Plus)  result += evalCerf(0, u,c).real(); 
     if (TMath::IsNaN(result)) { cxcoutE(Tracing) << "RooGaussModel::getVal(" << GetName() << ") got nan during case 1 " << endl; }
     return result ;
   }
@@ -191,8 +190,8 @@ Double_t RooGaussModel::evaluate() const
     if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 4th form omega = " << omega << ", tau = " << tau << endl ;
     Double_t result(0) ;
     if (_x==0.) return result ;
-    if (basisSign!=Minus) result += -evalCerfIm(-_x,-u,c) ; 
-    if (basisSign!=Plus)  result += -evalCerfIm( _x, u,c) ; 
+    if (basisSign!=Minus) result += -evalCerf(-_x,-u,c).imag(); 
+    if (basisSign!=Plus)  result += -evalCerf( _x, u,c).imag(); 
     if (TMath::IsNaN(result)) cxcoutE(Tracing) << "RooGaussModel::getVal(" << GetName() << ") got nan during case 3 " << endl; 
     return result ;
   }
@@ -201,8 +200,8 @@ Double_t RooGaussModel::evaluate() const
   if (basisType==cosBasis) {
     if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 5th form omega = " << omega << ", tau = " << tau << endl ;
     Double_t result(0) ;
-    if (basisSign!=Minus) result += evalCerfRe(-_x,-u,c) ; 
-    if (basisSign!=Plus)  result += evalCerfRe( _x, u,c) ; 
+    if (basisSign!=Minus) result += evalCerf(-_x,-u,c).real(); 
+    if (basisSign!=Plus)  result += evalCerf( _x, u,c).real(); 
     if (TMath::IsNaN(result)) cxcoutE(Tracing) << "RooGaussModel::getVal(" << GetName() << ") got nan during case 4 " << endl; 
     return result ;  
   }
@@ -212,8 +211,8 @@ Double_t RooGaussModel::evaluate() const
     if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 8th form tau = " << tau << endl ;
     Double_t result(0);   
     int sgn = ( basisType == coshBasis ? +1 : -1 );
-    if (basisSign!=Minus) result += 0.5*(    evalCerfRe(0,-u,c*(1-_y))+sgn*evalCerfRe(0,-u,c*(1+_y))) ; 
-    if (basisSign!=Plus)  result += 0.5*(sgn*evalCerfRe(0, u,c*(1-_y))+    evalCerfRe(0, u,c*(1+_y))) ; 
+    if (basisSign!=Minus) result += 0.5*(    evalCerf(0,-u,c*(1-_y)).real()+sgn*evalCerf(0,-u,c*(1+_y)).real()) ; 
+    if (basisSign!=Plus)  result += 0.5*(sgn*evalCerf(0, u,c*(1-_y)).real()+    evalCerf(0, u,c*(1+_y)).real()) ; 
     if (TMath::IsNaN(result)) cxcoutE(Tracing) << "RooGaussModel::getVal(" << GetName() << ") got nan during case 8 " << endl; 
     return result ;
   }
@@ -223,8 +222,8 @@ Double_t RooGaussModel::evaluate() const
     if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 6th form tau = " << tau << endl ;
     assert(basisSign==Plus);  // This should only be for positive times
 
-    Double_t f0 = exp(-xprime+c*c) * RooMath::erfc(-u+c);
-    Double_t f1 = exp(-u*u);
+    Double_t f0 = std::exp(-xprime+c*c) * RooMath::erfc(-u+c);
+    Double_t f1 = std::exp(-u*u);
     return (xprime - 2*c*c)*f0 + (2*c/rootpi)*f1 ; 
   }
 
@@ -233,8 +232,8 @@ Double_t RooGaussModel::evaluate() const
     if (verboseEval()>2) cout << "RooGaussModel::evaluate(" << GetName() << ") 7th form tau = " << tau << endl ;
     assert(basisSign==Plus);  // This should only be for positive times
 
-    Double_t f0 = exp(-xprime+c*c) * RooMath::erfc(-u+c);
-    Double_t f1 = exp(-u*u);
+    Double_t f0 = std::exp(-xprime+c*c) * RooMath::erfc(-u+c);
+    Double_t f1 = std::exp(-u*u);
     Double_t x2c2 = xprime - 2*c*c; 
     return ( x2c2*x2c2*f0 + (2*c/rootpi)*x2c2*f1 + 2*c*c*f0 );
   }
@@ -300,9 +299,9 @@ Int_t RooGaussModel::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVa
 //_____________________________________________________________________________
 Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) const 
 {
-  static Double_t root2 = sqrt(2.) ;
-  //static Double_t rootPiBy2 = sqrt(atan2(0.0,-1.0)/2.0);
-  static Double_t rootpi = sqrt(atan2(0.0,-1.0));
+  static const Double_t root2 = std::sqrt(2.) ;
+  //static Double_t rootPiBy2 = std::sqrt(std::atan2(0.0,-1.0)/2.0);
+  static const Double_t rootpi = std::sqrt(std::atan2(0.0,-1.0));
   Double_t ssfInt(1.0) ;
 
   // Code must be 1 or 2
@@ -358,8 +357,8 @@ Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) co
   if (basisType==expBasis || (basisType==cosBasis && omega==0.)) {
     if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 3d form tau=" << tau << endl ;
     Double_t result(0) ;
-    if (basisSign!=Minus) result += evalCerfInt(+1,0,tau,-umin,-umax,c).re();   
-    if (basisSign!=Plus)  result += evalCerfInt(-1,0,tau, umin, umax,c).re();
+    if (basisSign!=Minus) result += evalCerfInt(+1,0,tau,-umin,-umax,c).real();   
+    if (basisSign!=Plus)  result += evalCerfInt(-1,0,tau, umin, umax,c).real();
     if (TMath::IsNaN(result)) { cxcoutE(Tracing) << "RooGaussModel::analyticalIntegral(" << GetName() << ") got nan during case 3 " << endl; }
     return result*ssfInt ;
   }
@@ -372,8 +371,8 @@ Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) co
     if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 4th form omega = " << omega << ", tau = " << tau << endl ;
     Double_t result(0) ;
     if (_x==0) return result*ssfInt ;
-    if (basisSign!=Minus) result += -1*evalCerfInt(+1,-_x,tau,-umin,-umax,c).im();
-    if (basisSign!=Plus)  result += -1*evalCerfInt(-1, _x,tau, umin, umax,c).im();      
+    if (basisSign!=Minus) result += -1*evalCerfInt(+1,-_x,tau,-umin,-umax,c).imag();
+    if (basisSign!=Plus)  result += -1*evalCerfInt(-1, _x,tau, umin, umax,c).imag();      
     if (TMath::IsNaN(result)) { cxcoutE(Tracing) << "RooGaussModel::analyticalIntegral(" << GetName() << ") got nan during case 4 " << endl; }
     return result*ssfInt ;
   }
@@ -382,8 +381,8 @@ Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) co
   if (basisType==cosBasis) {
     if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 5th form omega = " << omega << ", tau = " << tau << endl ;
     Double_t result(0) ;
-    if (basisSign!=Minus) result += evalCerfInt(+1,-_x,tau,-umin,-umax,c).re();
-    if (basisSign!=Plus)  result += evalCerfInt(-1, _x,tau, umin, umax,c).re();      
+    if (basisSign!=Minus) result += evalCerfInt(+1,-_x,tau,-umin,-umax,c).real();
+    if (basisSign!=Plus)  result += evalCerfInt(-1, _x,tau, umin, umax,c).real();      
     if (TMath::IsNaN(result)) { cxcoutE(Tracing) << "RooGaussModel::analyticalIntegral(" << GetName() << ") got nan during case 5 " << endl; }
     return result*ssfInt ;
   }
@@ -394,8 +393,8 @@ Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) co
     if (verboseEval()>0) {cout << "RooGaussModel::analyticalIntegral(" << GetName()                             << ") 8th form tau=" << tau << endl ; }
     Double_t result(0) ;
     int sgn = ( basisType == coshBasis ? +1 : -1 );
-    if (basisSign!=Minus) result += 0.5*(    evalCerfInt(+1,0,tau/(1-_y),-umin,-umax,c*(1-_y)).re()+ sgn*evalCerfInt(+1,0,tau/(1+_y),-umin,-umax,c*(1+_y)).re());
-    if (basisSign!=Plus)  result += 0.5*(sgn*evalCerfInt(-1,0,tau/(1-_y), umin, umax,c*(1-_y)).re()+     evalCerfInt(-1,0,tau/(1+_y), umin, umax,c*(1+_y)).re());
+    if (basisSign!=Minus) result += 0.5*(    evalCerfInt(+1,0,tau/(1-_y),-umin,-umax,c*(1-_y)).real()+ sgn*evalCerfInt(+1,0,tau/(1+_y),-umin,-umax,c*(1+_y)).real());
+    if (basisSign!=Plus)  result += 0.5*(sgn*evalCerfInt(-1,0,tau/(1-_y), umin, umax,c*(1-_y)).real()+     evalCerfInt(-1,0,tau/(1+_y), umin, umax,c*(1+_y)).real());
     if (TMath::IsNaN(result)) { cxcoutE(Tracing) << "RooGaussModel::analyticalIntegral(" << GetName() << ") got nan during case 6 " << endl; }
     return result*ssfInt ;
   }
@@ -405,15 +404,15 @@ Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) co
     if (verboseEval()>0) cout << "RooGaussModel::analyticalIntegral(" << GetName() << ") 6th form tau=" << tau << endl ;
 
     Double_t f0 = RooMath::erf(-umax) - RooMath::erf(-umin);
-    Double_t f1 = exp(-umax*umax) - exp(-umin*umin);
+    Double_t f1 = std::exp(-umax*umax) - std::exp(-umin*umin);
 
-    Double_t tmp1 = exp(-xpmax)*RooMath::erfc(-umax + c);
-    Double_t tmp2 = exp(-xpmin)*RooMath::erfc(-umin + c);
+    Double_t tmp1 = std::exp(-xpmax)*RooMath::erfc(-umax + c);
+    Double_t tmp2 = std::exp(-xpmin)*RooMath::erfc(-umin + c);
 
     Double_t f2 = tmp1 - tmp2;
     Double_t f3 = xpmax*tmp1 - xpmin*tmp2;
 
-    Double_t expc2 = exp(c*c);
+    Double_t expc2 = std::exp(c*c);
 
     return -tau*(              f0 +
 		  (2*c/rootpi)*f1 +
@@ -428,20 +427,20 @@ Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) co
 
     Double_t f0 = RooMath::erf(-umax) - RooMath::erf(-umin);
 
-    Double_t tmpA1 = exp(-umax*umax);
-    Double_t tmpA2 = exp(-umin*umin);
+    Double_t tmpA1 = std::exp(-umax*umax);
+    Double_t tmpA2 = std::exp(-umin*umin);
 
     Double_t f1 = tmpA1 - tmpA2;
     Double_t f2 = umax*tmpA1 - umin*tmpA2;
 
-    Double_t tmpB1 = exp(-xpmax)*RooMath::erfc(-umax + c);
-    Double_t tmpB2 = exp(-xpmin)*RooMath::erfc(-umin + c);
+    Double_t tmpB1 = std::exp(-xpmax)*RooMath::erfc(-umax + c);
+    Double_t tmpB2 = std::exp(-xpmin)*RooMath::erfc(-umin + c);
 
     Double_t f3 = tmpB1 - tmpB2;
     Double_t f4 = xpmax*tmpB1 - xpmin*tmpB2;
     Double_t f5 = xpmax*xpmax*tmpB1 - xpmin*xpmin*tmpB2;
 
-    Double_t expc2 = exp(c*c);
+    Double_t expc2 = std::exp(c*c);
 
     return -tau*( 2*f0 +
 		  (4*c/rootpi)*((1-c*c)*f1 + c*f2) +
@@ -452,34 +451,38 @@ Double_t RooGaussModel::analyticalIntegral(Int_t code, const char* rangeName) co
   return 0 ;
 }
 
-
-
 //_____________________________________________________________________________
-RooComplex RooGaussModel::evalCerfApprox(Double_t _x, Double_t u, Double_t c) const
+std::complex<Double_t> RooGaussModel::evalCerfApprox(Double_t _x, Double_t u, Double_t c)
 {
-  // use the approximation: erf(z) = exp(-z*z)/(sqrt(pi)*z)
+  // use the approximation: erf(z) = exp(-z*z)/(std::sqrt(pi)*z)
   // to explicitly cancel the divergent exp(y*y) behaviour of
   // CWERF for z = x + i y with large negative y
 
-  static Double_t rootpi= sqrt(atan2(0.,-1.));
-  RooComplex z(_x*c,u+c);  
-  RooComplex zc(u+c,-_x*c);
-  RooComplex zsq= z*z;
-  RooComplex v= -zsq - u*u;
+  static const Double_t rootpi= std::sqrt(std::atan2(0.,-1.));
+  const std::complex<Double_t> z(_x * c, u + c);  
+  const std::complex<Double_t> zc(u + c, - _x * c);
+  const std::complex<Double_t> zsq((z.real() + z.imag()) * (z.real() - z.imag()),
+	  2. * z.real() * z.imag());
+  const std::complex<Double_t> v(-zsq.real() - u*u, -zsq.imag());
+  const std::complex<Double_t> ev = std::exp(v);
+  const std::complex<Double_t> mez2zcrootpi = -std::exp(zsq)/(zc*rootpi);
 
-  return v.exp()*(-zsq.exp()/(zc*rootpi) + 1)*2 ;
+  return 2. * (ev * (mez2zcrootpi + 1.));
 }
 
 //_____________________________________________________________________________
-RooComplex RooGaussModel::evalCerfInt(Double_t sign, Double_t _x, Double_t tau, Double_t umin, Double_t umax, Double_t c) const
+std::complex<Double_t> RooGaussModel::evalCerfInt(Double_t sign, Double_t _x, Double_t tau, Double_t umin, Double_t umax, Double_t c) const
 {
-  RooComplex diff;
-  if (_asympInt) {
-    diff = RooComplex(2,0) ;
-  } else {
-    diff = RooComplex(sign,0.)*(evalCerf(_x,umin,c) - evalCerf(_x,umax,c) + RooMath::erf(umin) - RooMath::erf(umax));
+  std::complex<Double_t> diff(2., 0.);
+  if (!_asympInt) {
+    diff = evalCerf(_x,umin,c);
+    diff -= evalCerf(_x,umax,c);
+    diff += RooMath::erf(umin) - RooMath::erf(umax);
+    diff *= sign;
   }
-  return RooComplex(tau/(1.+_x*_x),0)*RooComplex(1,_x)*diff;
+  diff *= std::complex<Double_t>(1., _x);
+  diff *= tau / (1.+_x*_x);
+  return diff;
 }
 
 //_____________________________________________________________________________
diff --git a/roofit/roofit/src/RooKeysPdf.cxx b/roofit/roofit/src/RooKeysPdf.cxx
index 5730af1..b6b51c6 100644
--- a/roofit/roofit/src/RooKeysPdf.cxx
+++ b/roofit/roofit/src/RooKeysPdf.cxx
@@ -16,6 +16,8 @@
  *****************************************************************************/
 #include "RooFit.h"
 
+#include <limits>
+#include <algorithm>
 #include <math.h>
 #include "Riostream.h"
 #include "TMath.h"
@@ -215,6 +217,67 @@ Double_t RooKeysPdf::evaluate() const {
   return (_lookupTable[i]+dx*(_lookupTable[i+1]-_lookupTable[i]));
 }
 
+Int_t RooKeysPdf::getAnalyticalIntegral(
+	RooArgSet& allVars, RooArgSet& analVars, const char* /* rangeName */) const
+{
+  if (matchArgs(allVars, analVars, _x)) return 1;
+  return 0;
+}
+
+Double_t RooKeysPdf::analyticalIntegral(Int_t code, const char* rangeName) const
+{
+  assert(1 == code);
+  // this code is based on _lookupTable and uses linear interpolation, just as
+  // evaluate(); integration is done using the trapez rule
+  const Double_t xmin = std::max(_lo, _x.min(rangeName));
+  const Double_t xmax = std::min(_hi, _x.max(rangeName));
+  const Int_t imin = (Int_t)floor((xmin - _lo) / _binWidth);
+  const Int_t imax = std::min((Int_t)floor((xmax - _lo) / _binWidth),
+      _nPoints - 1);
+  Double_t sum = 0.;
+  // sum up complete bins in middle
+  if (imin + 1 < imax)
+    sum += _lookupTable[imin + 1] + _lookupTable[imax];
+  for (Int_t i = imin + 2; i < imax; ++i)
+    sum += 2. * _lookupTable[i];
+  sum *= _binWidth * 0.5;
+  // treat incomplete bins
+  const Double_t dxmin = (xmin - (_lo + imin * _binWidth)) / _binWidth;
+  const Double_t dxmax = (xmax - (_lo + imax * _binWidth)) / _binWidth;
+  if (imin < imax) {
+    // first bin
+    sum += _binWidth * (1. - dxmin) * 0.5 * (_lookupTable[imin + 1] +
+	_lookupTable[imin] + dxmin *
+	(_lookupTable[imin + 1] - _lookupTable[imin]));
+    // last bin
+    sum += _binWidth * dxmax * 0.5 * (_lookupTable[imax] +
+	_lookupTable[imax] + dxmax *
+	(_lookupTable[imax + 1] - _lookupTable[imax]));
+  } else if (imin == imax) {
+    // first bin == last bin
+    sum += _binWidth * (dxmax - dxmin) * 0.5 * (
+	_lookupTable[imin] + dxmin *
+	(_lookupTable[imin + 1] - _lookupTable[imin]) +
+	_lookupTable[imax] + dxmax *
+	(_lookupTable[imax + 1] - _lookupTable[imax]));
+  }
+  return sum;
+}
+
+Int_t RooKeysPdf::getMaxVal(const RooArgSet& vars) const
+{
+  if (vars.contains(*_x.absArg())) return 1;
+  return 0;
+}
+
+Double_t RooKeysPdf::maxVal(Int_t code) const
+{
+  assert(1 == code);
+  Double_t max = -std::numeric_limits<Double_t>::max();
+  for (Int_t i = 0; i <= _nPoints; ++i)
+    if (max < _lookupTable[i]) max = _lookupTable[i];
+  return max;
+}
 
 //_____________________________________________________________________________
 Double_t RooKeysPdf::evaluateFull( Double_t x ) const {
@@ -249,7 +312,6 @@ Double_t RooKeysPdf::evaluateFull( Double_t x ) const {
   return y/(sqrt2pi*_sumWgt);
 }
 
-
 //_____________________________________________________________________________
 Double_t RooKeysPdf::g(Double_t x,Double_t sigmav) const {
   
diff --git a/roofit/roofit/src/RooVoigtian.cxx b/roofit/roofit/src/RooVoigtian.cxx
index fc57921..bfc78e9 100644
--- a/roofit/roofit/src/RooVoigtian.cxx
+++ b/roofit/roofit/src/RooVoigtian.cxx
@@ -26,17 +26,16 @@
 // END_HTML
 //
 
+#include <cmath>
+#include <complex>
 
 #include "RooFit.h"
 
 #include "Riostream.h"
-#include "Riostream.h"
-#include <math.h>
 
 #include "RooVoigtian.h"
 #include "RooAbsReal.h"
 #include "RooRealVar.h"
-#include "RooComplex.h"
 #include "RooMath.h"
 
 using namespace std;
@@ -94,14 +93,14 @@ Double_t RooVoigtian::evaluate() const
   Double_t c = 1./(sqrt(2.)*s);
   Double_t a = 0.5*c*w;
   Double_t u = c*arg;
-  RooComplex z(u,a) ;
-  RooComplex v(0.) ;
+  std::complex<Double_t> z(u,a) ;
+  std::complex<Double_t> v(0.) ;
 
   if (_doFast) {
-    v = RooMath::FastComplexErrFunc(z);
+    v = RooMath::faddeeva_fast(z);
   } else {
-    v = RooMath::ComplexErrFunc(z);
+    v = RooMath::faddeeva(z);
   }
-  return c*_invRootPi*v.re();
+  return c*_invRootPi*v.real();
 
 }
diff --git a/roofit/roofitcore/Module.mk b/roofit/roofitcore/Module.mk
index 1d256be..8a7910b 100644
--- a/roofit/roofitcore/Module.mk
+++ b/roofit/roofitcore/Module.mk
@@ -128,7 +128,7 @@ $(ROOFITCORELIB): $(ROOFITCOREO) $(ROOFITCOREDO) $(ORDER_) $(MAINLIBS) \
 		@$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \
 		   "$(SOFLAGS)" libRooFitCore.$(SOEXT) $@ \
 		   "$(ROOFITCOREO) $(ROOFITCOREDO)" \
-		   "$(ROOFITCORELIBEXTRA)"
+		   "$(ROOFITCORELIBEXTRA) $(OSTHREADLIBDIR) $(OSTHREADLIB)"
 
 $(ROOFITCOREDS1): $(ROOFITCOREH1) $(ROOFITCOREL1) $(ROOTCINTTMPDEP)
 		$(MAKEDIR)
diff --git a/roofit/roofitcore/inc/LinkDef1.h b/roofit/roofitcore/inc/LinkDef1.h
index 2b01f84..c534931 100644
--- a/roofit/roofitcore/inc/LinkDef1.h
+++ b/roofit/roofitcore/inc/LinkDef1.h
@@ -40,7 +40,7 @@
 #pragma link C++ class RooArgProxy+ ;
 #pragma link C++ class RooArgSet+ ;
 #pragma link C++ class RooBinnedGenContext+ ;
-#pragma link C++ class RooBinning- ;
+#pragma link C++ class RooBinning-;
 #pragma link C++ class RooBrentRootFinder+ ;
 #pragma link C++ class RooCategory- ;
 #pragma link C++ class RooCategoryProxy+ ;
diff --git a/roofit/roofitcore/inc/RooAbsArg.h b/roofit/roofitcore/inc/RooAbsArg.h
index e79f77d..68dde14 100644
--- a/roofit/roofitcore/inc/RooAbsArg.h
+++ b/roofit/roofitcore/inc/RooAbsArg.h
@@ -395,7 +395,16 @@ public:
   inline OperMode operMode() const { return _operMode  ; }
   void setOperMode(OperMode mode, Bool_t recurseADirty=kTRUE) ; 
 
-  static UInt_t crc32(const char* data) ;
+  static UInt_t crc32(const char* data);
+  static UInt_t crc32(const char* data, ULong_t sz, UInt_t crc = 0);
+
+  static const UInt_t fnv1a32start = 2166136261u;
+  static UInt_t fnv1a32(const char* data);
+  static UInt_t fnv1a32(const char* data, ULong_t sz, UInt_t hash = fnv1a32start);
+
+  static const ULong64_t fnv1a64start = (ULong64_t(3421674724u) << 32) | ULong64_t(2216829733u);
+  static ULong64_t fnv1a64(const char* data);
+  static ULong64_t fnv1a64(const char* data, ULong_t sz, ULong64_t hash = fnv1a64start);
   
   Bool_t addOwnedComponents(const RooArgSet& comps) ;
   const RooArgSet* ownedComponents() const { return _ownedComponents ; }
diff --git a/roofit/roofitcore/inc/RooAbsPdf.h b/roofit/roofitcore/inc/RooAbsPdf.h
index 7e07a4e..740c7de 100644
--- a/roofit/roofitcore/inc/RooAbsPdf.h
+++ b/roofit/roofitcore/inc/RooAbsPdf.h
@@ -111,6 +111,7 @@ public:
               ) const {
     return RooAbsReal::plotOn(frame,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) ;
   }
+  virtual RooPlot* plotOn(RooPlot* frame, RooLinkedList& cmdList) const ;
 
 
   virtual RooPlot* paramOn(RooPlot* frame, 
@@ -262,7 +263,6 @@ protected:
 			   Double_t xmax= 0.99,Double_t ymax=0.95, const RooCmdArg* formatCmd=0) ;
 
 
-  virtual RooPlot* plotOn(RooPlot* frame, RooLinkedList& cmdList) const ;
   void plotOnCompSelect(RooArgSet* selNodes) const ;
 
   virtual RooPlot *plotOn(RooPlot *frame, PlotOpt o) const;  
diff --git a/roofit/roofitcore/inc/RooAbsReal.h b/roofit/roofitcore/inc/RooAbsReal.h
index c267271..b0aec3f 100644
--- a/roofit/roofitcore/inc/RooAbsReal.h
+++ b/roofit/roofitcore/inc/RooAbsReal.h
@@ -251,12 +251,12 @@ public:
   // Evaluation error logging 
   class EvalError {
   public:
-    EvalError() { _msg[0] = 0 ; _srvval[0] = 0 ; }
-    EvalError(const EvalError& other) { strlcpy(_msg,other._msg,1024) ; strlcpy(_srvval,other._srvval,1024) ; } ;
-    void setMessage(const char* tmp) ;
-    void setServerValues(const char* tmp) ;
-    char _msg[1024] ;
-    char _srvval[1024] ;
+    EvalError() { }
+    EvalError(const EvalError& other) : _msg(other._msg), _srvval(other._srvval) { }
+    void setMessage(const char* tmp) { std::string s(tmp); s.swap(_msg); }
+    void setServerValues(const char* tmp) { std::string s(tmp); s.swap(_srvval); }
+    std::string _msg;
+    std::string _srvval;
   } ;
 
   enum ErrorLoggingMode { PrintErrors, CollectErrors, CountErrors, Ignore } ;
@@ -312,10 +312,6 @@ public:
   static Bool_t hideOffset() ;
 
 protected:
-
-  // PlotOn with command list
-  virtual RooPlot* plotOn(RooPlot* frame, RooLinkedList& cmdList) const ;
-
   // Hook for objects with normalization-dependent parameters interperetation
   virtual void selectNormalization(const RooArgSet* depSet=0, Bool_t force=kFALSE) ;
   virtual void selectNormalizationRange(const char* rangeName=0, Bool_t force=kFALSE) ;
@@ -450,6 +446,9 @@ protected:
 
   // Plot implementation functions
   virtual RooPlot *plotOn(RooPlot* frame, PlotOpt o) const;
+  // PlotOn with command list
+  virtual RooPlot* plotOn(RooPlot* frame, RooLinkedList& cmdList) const ;
+
   virtual RooPlot *plotAsymOn(RooPlot *frame, const RooAbsCategoryLValue& asymCat, PlotOpt o) const;
 
 
diff --git a/roofit/roofitcore/inc/RooAbsTestStatistic.h b/roofit/roofitcore/inc/RooAbsTestStatistic.h
index 8c33395..2e0169a 100644
--- a/roofit/roofitcore/inc/RooAbsTestStatistic.h
+++ b/roofit/roofitcore/inc/RooAbsTestStatistic.h
@@ -35,6 +35,7 @@ typedef RooAbsData* pRooAbsData ;
 typedef RooRealMPFE* pRooRealMPFE ;
 
 class RooAbsTestStatistic : public RooAbsReal {
+    friend class RooRealMPFE;
 public:
 
   // Constructors, assignment etc
@@ -61,6 +62,7 @@ public:
   void enableOffsetting(Bool_t flag) ;
   Bool_t isOffsetting() const { return _doOffset ; }
   virtual Double_t offset() const { return _offset ; }
+  virtual Double_t offsetCarry() const { return _offsetCarry; }
 
 protected:
 
@@ -70,6 +72,7 @@ protected:
   virtual Double_t evaluate() const ;
 
   virtual Double_t evaluatePartition(Int_t firstEvent, Int_t lastEvent, Int_t stepSize) const = 0 ;
+  virtual Double_t getCarry() const;
 
   void setMPSet(Int_t setNum, Int_t numSets) ; 
   void setSimCount(Int_t simCount) { 
@@ -141,6 +144,7 @@ protected:
   Bool_t         _doOffset ; // Apply interval value offset to control numeric precision?
   mutable Double_t _offset ; //! Offset
   mutable Double_t _offsetCarry; //! avoids loss of precision
+  mutable Double_t _evalCarry; //! carry of Kahan sum in evaluatePartition
 
   ClassDef(RooAbsTestStatistic,2) // Abstract base class for real-valued test statistics
 
diff --git a/roofit/roofitcore/inc/RooBinning.h b/roofit/roofitcore/inc/RooBinning.h
index 4838574..af20110 100644
--- a/roofit/roofitcore/inc/RooBinning.h
+++ b/roofit/roofitcore/inc/RooBinning.h
@@ -21,72 +21,73 @@
 #include "RooDouble.h"
 #include "RooAbsBinning.h"
 #include "RooNumber.h"
-#include <set>
-class RooAbsPdf ;
-class RooRealVar ;
+#include <vector>
+class RooAbsPdf;
+class RooRealVar;
 
 
 class RooBinning : public RooAbsBinning {
 public:
 
-  RooBinning(Double_t xlo=-RooNumber::infinity(), Double_t xhi=RooNumber::infinity(), const char* name=0) ;
-  RooBinning(Int_t nBins, Double_t xlo, Double_t xhi, const char* name=0) ;
-  RooBinning(Int_t nBins, const Double_t* boundaries, const char* name=0) ;
-  RooBinning(const RooBinning& other, const char* name=0) ;
-  RooAbsBinning* clone(const char* name=0) const { return new RooBinning(*this,name?name:GetName()) ; }
-  ~RooBinning() ;
+  RooBinning(Double_t xlo = -RooNumber::infinity(), Double_t xhi = RooNumber::infinity(), const char* name = 0);
+  RooBinning(Int_t nBins, Double_t xlo, Double_t xhi, const char* name = 0);
+  RooBinning(Int_t nBins, const Double_t* boundaries, const char* name = 0);
+  RooBinning(const RooBinning& other, const char* name = 0);
+  RooAbsBinning* clone(const char* name = 0) const { return new RooBinning(*this,name?name:GetName()); }
+  ~RooBinning();
 
-  virtual Int_t numBoundaries() const { 
+  virtual Int_t numBoundaries() const {
     // Return the number boundaries
-    return _nbins+1 ; 
+    return _nbins+1;
   }
-  virtual Int_t binNumber(Double_t x) const ;
-  virtual Int_t rawBinNumber(Double_t x) const ;
-  virtual Double_t nearestBoundary(Double_t x) const ;
+  virtual Int_t binNumber(Double_t x) const;
+  virtual Int_t rawBinNumber(Double_t x) const;
+  virtual Double_t nearestBoundary(Double_t x) const;
 
-  virtual void setRange(Double_t xlo, Double_t xhi) ;
+  virtual void setRange(Double_t xlo, Double_t xhi);
 
-  virtual Double_t lowBound() const { 
+  virtual Double_t lowBound() const {
     // Return the lower bound value
-    return _xlo ; 
+    return _xlo;
   }
-  virtual Double_t highBound() const { 
+  virtual Double_t highBound() const {
     // Return the upper bound value
-    return _xhi ; 
+    return _xhi;
   }
-  virtual Double_t averageBinWidth() const { 
+  virtual Double_t averageBinWidth() const {
     // Return the average bin width
-    return (highBound()-lowBound())/numBins() ; 
+    return (highBound() - lowBound()) / numBins();
   }
-  virtual Double_t* array() const ;
-
-  virtual Double_t binCenter(Int_t bin) const ;
-  virtual Double_t binWidth(Int_t bin) const ;
-  virtual Double_t binLow(Int_t bin) const ;
-  virtual Double_t binHigh(Int_t bin) const  ;
-  
-  Bool_t addBoundary(Double_t boundary) ;
-  void addBoundaryPair(Double_t boundary, Double_t mirrorPoint=0) ;
-  void addUniform(Int_t nBins, Double_t xlo, Double_t xhi) ;
-  Bool_t removeBoundary(Double_t boundary) ;
-
-  Bool_t hasBoundary(Double_t boundary) ;
-  
+  virtual Double_t* array() const;
+
+  virtual Double_t binCenter(Int_t bin) const;
+  virtual Double_t binWidth(Int_t bin) const;
+  virtual Double_t binLow(Int_t bin) const;
+  virtual Double_t binHigh(Int_t bin) const;
+
+  Bool_t addBoundary(Double_t boundary);
+  void addBoundaryPair(Double_t boundary, Double_t mirrorPoint = 0);
+  void addUniform(Int_t nBins, Double_t xlo, Double_t xhi);
+  Bool_t removeBoundary(Double_t boundary);
+
+  Bool_t hasBoundary(Double_t boundary);
+
 protected:
 
-  Bool_t binEdges(Int_t bin, Double_t& xlo, Double_t& xhi) const ;
-  void updateBinCount() ;
+  Bool_t binEdges(Int_t bin, Double_t& xlo, Double_t& xhi) const;
+  void updateBinCount();
 
-  Double_t _xlo ;          // Lower bound
-  Double_t _xhi ;          // Upper bound
-  Bool_t _ownBoundLo ;     // Does the lower bound coincide with a bin boundary
-  Bool_t _ownBoundHi ;     // Does the upper bound coincide with a bin boundary
-  Int_t _nbins ;           // Numer of bins
+  Double_t _xlo;          // Lower bound
+  Double_t _xhi;          // Upper bound
+  Bool_t _ownBoundLo;     // Does the lower bound coincide with a bin boundary
+  Bool_t _ownBoundHi;     // Does the upper bound coincide with a bin boundary
+  Int_t _nbins;           // Numer of bins
 
-  std::set<Double_t> _boundaries ;   // Boundaries
-  mutable Double_t* _array ;         //! Array of boundaries
+  std::vector<Double_t> _boundaries;   // Boundaries
+  mutable Double_t* _array;         //! Array of boundaries
+  mutable Int_t _blo; //! bin number for _xlo
 
-  ClassDef(RooBinning,2) // Generic binning specification
+  ClassDef(RooBinning,3) // Generic binning specification
 };
 
 #endif
diff --git a/roofit/roofitcore/inc/RooComplex.h b/roofit/roofitcore/inc/RooComplex.h
index b67db6b..f7d8408 100644
--- a/roofit/roofitcore/inc/RooComplex.h
+++ b/roofit/roofitcore/inc/RooComplex.h
@@ -16,9 +16,15 @@
 #ifndef ROO_COMPLEX
 #define ROO_COMPLEX
 
+#if !defined(ROO_MATH) && !defined(ROO_COMPLEX_CXX) && !defined(__CINT__) && \
+    !defined(R__DICTIONARY_FILENAME)
+#warning "RooComplex is deprecated, use std::complex instead!"
+#endif
+
 #include <math.h>
 #include "Rtypes.h"
 #include "Riosfwd.h"
+#include <complex>
 
 // This is a bare-bones complex class adapted from the CINT complex.h header,
 // and introduced to support the complex error function in RooMath. The main
@@ -28,9 +34,13 @@
 
 class RooComplex {
 public:
-  inline RooComplex(Double_t a=0, Double_t b=0) : _re(a), _im(b) { }
-  virtual ~RooComplex() {} ;
+
+  inline RooComplex(std::complex<Double_t> c) : _re(c.real()), _im(c.imag()) { }
+
+  inline RooComplex(Double_t a=0, Double_t b=0) : _re(a), _im(b) { warn(); }
+  virtual ~RooComplex() { }
   inline RooComplex& operator=(const RooComplex& other) {
+    warn();
     if (&other==this) return *this ;
     this->_re= other._re;
     this->_im= other._im;
@@ -94,6 +104,9 @@ public:
   void Print() const;
 private:
   Double_t _re,_im;
+
+  void warn() const;
+
   ClassDef(RooComplex,0) // a non-persistent bare-bones complex class
 };
 
diff --git a/roofit/roofitcore/inc/RooMath.h b/roofit/roofitcore/inc/RooMath.h
index a3ee93c..1d07608 100644
--- a/roofit/roofitcore/inc/RooMath.h
+++ b/roofit/roofitcore/inc/RooMath.h
@@ -19,17 +19,25 @@
 #include <cmath>
 #include <complex>
 
+#include "Rtypes.h"
+#include "TMath.h"
 #include "RooComplex.h"
 
-#include <fstream>
+#if defined(__my_func__)
+#undef __my_func__
+#endif
+#if defined(WIN32)
+#define __my_func__ __FUNCTION__
+#else
+#define __my_func__ __func__
+#endif
 
-typedef RooComplex* pRooComplex ;
-typedef Double_t* pDouble_t ;
+typedef Double_t* pDouble_t;
 
 class RooMath {
 public:
 
-  virtual ~RooMath() {} ;
+  virtual ~RooMath() {};
 
   /** @brief evaluate Faddeeva function for complex argument
    *
@@ -86,6 +94,18 @@ public:
    * to better than 4e-13 relative, the average relative error is better than
    * 7e-16. On a modern x86_64 machine, the routine is roughly three times as
    * fast than the old CERNLIB implementation and offers better accuracy.
+   *
+   * For large @f$|z|@f$, the familiar continued fraction approximation
+   * 
+   * @f[ w(z)=\frac{-iz/\sqrt{\pi}}{-z^2+\frac{1/2}{1+\frac{2/2}{-z^2 +
+   * \frac{3/2}{1+\frac{4/2}{-z^2+\frac{5/2}{1+\frac{6/2}{-z^2+\frac{7/2
+   * }{1+\frac{8/2}{-z^2+\frac{9/2}{1+\ldots}}}}}}}}}} @f]
+   *
+   * is used, truncated at the ellipsis ("...") in the formula; for @f$|z| >
+   * 12 at f$, @f$Im(z)>0 at f$ it will give full double precision at a smaller
+   * computational cost than the method described above. (For @f$|z|>12 at f$,
+   * @f$Im(z)<0 at f$, the symmetry property @f$w(x-iy)=2e^{-(x+iy)^2-w(x+iy)}@f$
+   * is used.
    */
   static std::complex<double> faddeeva(std::complex<double> z);
   /** @brief evaluate Faddeeva function for complex argument (fast version)
@@ -110,6 +130,17 @@ public:
    * interpolation/lookup table based fast method used previously in RooFit,
    * and offers better accuracy than the latter (the relative error is roughly
    * a factor 280 smaller than the old interpolation/table lookup routine).
+   *
+   * For large @f$|z|@f$, the familiar continued fraction approximation
+   * 
+   * @f[ w(z)=\frac{-iz/\sqrt{\pi}}{-z^2+\frac{1/2}{1+\frac{2/2}{-z^2 +
+   * \frac{3/2}{1+\ldots}}}} @f]
+   *
+   * is used, truncated at the ellipsis ("...") in the formula; for @f$|z| >
+   * 8 at f$, @f$Im(z)>0 at f$ it will give full float precision at a smaller
+   * computational cost than the method described above. (For @f$|z|>8 at f$,
+   * @f$Im(z)<0 at f$, the symmetry property @f$w(x-iy)=2e^{-(x+iy)^2-w(x+iy)}@f$
+   * is used.
    */
   static std::complex<double> faddeeva_fast(std::complex<double> z);
 
@@ -147,44 +178,58 @@ public:
    */
   static std::complex<double> erfc_fast(const std::complex<double> z);
 
-
-  // CERNLIB complex error function
-  static RooComplex ComplexErrFunc(Double_t re, Double_t im= 0);
-  static RooComplex ComplexErrFunc(const RooComplex& z);
-
-  // Interpolated CERF with automatic interpolation order selection
-  static RooComplex FastComplexErrFunc(const RooComplex& z) ;
-  
-  // Interpolated Re(CERF) with automatic interpolation order selection
-  static Double_t FastComplexErrFuncRe(const RooComplex& z) ;
-
-  // Interpolated Im(CERF) with automatic interpolation order selection
-  static Double_t FastComplexErrFuncIm(const RooComplex& z) ;
-
-  // Interpolated complex error function at specified interpolation order
-  static RooComplex ITPComplexErrFunc(const RooComplex& z, Int_t nOrder) ;
-  static Double_t ITPComplexErrFuncRe(const RooComplex& z, Int_t nOrder) ;
-  static Double_t ITPComplexErrFuncIm(const RooComplex& z, Int_t nOrder) ;
-
-  // Switch to use file cache for CERF lookup table
-  static void cacheCERF(Bool_t flag=kTRUE) ;
-
   // 1-D nth order polynomial interpolation routines
   static Double_t interpolate(Double_t yArr[],Int_t nOrder, Double_t x) ;
   static Double_t interpolate(Double_t xa[], Double_t ya[], Int_t n, Double_t x) ;
 
-  static Double_t erf(Double_t x) ;
-  static Double_t erfc(Double_t x) ;
-  
-  static void cleanup() ;
-
-  // Allocate and initialize CERF lookup grid
-  static void initFastCERF(Int_t reBins= 800, Double_t reMin=-4.0, Double_t reMax=4.0, 
-			   Int_t imBins=1000, Double_t imMin=-4.0, Double_t imMax=6.0) ;
+  static inline Double_t erf(Double_t x)
+  { return TMath::Erf(x); }
 
+  static inline Double_t erfc(Double_t x)
+  { return TMath::Erfc(x); }
+  
+  /// deprecated function
+  static RooComplex ComplexErrFunc(Double_t re, Double_t im = 0.)
+  { warn(__my_func__, "RooMath::faddeeva"); std::complex<Double_t> z = faddeeva(std::complex<Double_t>(re, im)); return RooComplex(z.real(), z.imag()); }
+  /// deprecated function
+  static RooComplex ComplexErrFunc(const RooComplex& zz)
+  { warn(__my_func__, "RooMath::faddeeva"); std::complex<Double_t> z = faddeeva(std::complex<Double_t>(zz.re(), zz.im())); return RooComplex(z.real(), z.imag()); }
+  /// deprecated function
+  static RooComplex ComplexErrFuncFast(const RooComplex& zz)
+  { warn(__my_func__, "RooMath::faddeeva_fast"); std::complex<Double_t> z = faddeeva_fast(std::complex<Double_t>(zz.re(), zz.im())); return RooComplex(z.real(), z.imag()); }
+  /// deprecated function
+  static Double_t ComplexErrFuncFastRe(const RooComplex& zz)
+  { warn(__my_func__, "RooMath::faddeeva_fast"); std::complex<Double_t> z = faddeeva_fast(std::complex<Double_t>(zz.re(), zz.im())); return z.real(); }
+  /// deprecated function
+  static Double_t ComplexErrFuncFastIm(const RooComplex& zz)
+  { warn(__my_func__, "RooMath::faddeeva_fast"); std::complex<Double_t> z = faddeeva_fast(std::complex<Double_t>(zz.re(), zz.im())); return z.imag(); }
+  /// deprecated function
+  static RooComplex ITPComplexErrFuncFast(const RooComplex& zz, Int_t)
+  { warn(__my_func__, "RooMath::faddeeva_fast"); std::complex<Double_t> z = faddeeva_fast(std::complex<Double_t>(zz.re(), zz.im())); return RooComplex(z.real(), z.imag()); }
+  /// deprecated function
+  static Double_t ITPComplexErrFuncFastRe(const RooComplex& zz, Int_t)
+  { warn(__my_func__, "RooMath::faddeeva_fast"); std::complex<Double_t> z = faddeeva_fast(std::complex<Double_t>(zz.re(), zz.im())); return z.real(); }
+  /// deprecated function
+  static Double_t ITPComplexErrFuncFastIm(const RooComplex& zz, Int_t)
+  { warn(__my_func__, "RooMath::faddeeva_fast"); std::complex<Double_t> z = faddeeva_fast(std::complex<Double_t>(zz.re(), zz.im())); return z.imag(); }
+  /// deprecated function
+  static void cacheCERF(Bool_t) { warn(__my_func__); }
+  /// deprecated function
+  static void cleanup() { warn(__my_func__); }
+  /// deprecated function
+  static void initFastCERF(Int_t /*reBins =  800*/, Double_t /*reMin = -4.0*/, Double_t /*reMax = 4.0*/, 
+			   Int_t /*imBins = 1000*/, Double_t /*imMin = -4.0*/, Double_t /*imMax = 6.0*/)
+  {
+    warn(__my_func__);
+  }
+  
 private:
+  // deprecation warnings
+  static void warn(const char* oldfun, const char* newfun = 0);
 
   ClassDef(RooMath,0) // math utility routines
 };
 
+#undef __my_func__
+
 #endif
diff --git a/roofit/roofitcore/inc/RooMinimizer.h b/roofit/roofitcore/inc/RooMinimizer.h
index cf8b1cc..83bb97f 100644
--- a/roofit/roofitcore/inc/RooMinimizer.h
+++ b/roofit/roofitcore/inc/RooMinimizer.h
@@ -47,8 +47,10 @@ public:
   void setErrorLevel(Double_t level) ;
   void setEps(Double_t eps) ;
   void optimizeConst(Int_t flag) ;
-  void setEvalErrorWall(Bool_t flag) { _fcn->SetEvalErrorWall(flag); }
+  void setEvalErrorWall(Bool_t flag) { fitterFcn()->SetEvalErrorWall(flag); }
   void setOffsetting(Bool_t flag) ;
+  void setMaxIterations(Int_t n) ;
+  void setMaxFunctionCalls(Int_t n) ; 
 
   RooFitResult* fit(const char* options) ;
 
@@ -68,10 +70,10 @@ public:
 		   Double_t n4=0, Double_t n5=0, Double_t n6=0) ;
 
   Int_t setPrintLevel(Int_t newLevel) ; 
-  void setPrintEvalErrors(Int_t numEvalErrors) { _fcn->SetPrintEvalErrors(numEvalErrors); }
-  void setVerbose(Bool_t flag=kTRUE) { _verbose = flag ; _fcn->SetVerbose(flag); }
+  void setPrintEvalErrors(Int_t numEvalErrors) { fitterFcn()->SetPrintEvalErrors(numEvalErrors); }
+  void setVerbose(Bool_t flag=kTRUE) { _verbose = flag ; fitterFcn()->SetVerbose(flag); }
   void setProfile(Bool_t flag=kTRUE) { _profile = flag ; }
-  Bool_t setLogFile(const char* logf=0) { return _fcn->SetLogFile(logf); }
+  Bool_t setLogFile(const char* logf=0) { return fitterFcn()->SetLogFile(logf); }
 
   void setMinimizerType(const char* type) ;
 
@@ -80,8 +82,11 @@ public:
 
   void saveStatus(const char* label, Int_t status) { _statusHistory.push_back(std::pair<std::string,int>(label,status)) ; }
 
-  Int_t evalCounter() const { return _fcn->evalCounter() ; }
-  void zeroEvalCount() { _fcn->zeroEvalCount() ; }
+  Int_t evalCounter() const { return fitterFcn()->evalCounter() ; }
+  void zeroEvalCount() { fitterFcn()->zeroEvalCount() ; }
+
+  ROOT::Fit::Fitter* fitter() ;
+  const ROOT::Fit::Fitter* fitter() const ;
   
 protected:
 
@@ -91,9 +96,12 @@ protected:
   void profileStart() ;
   void profileStop() ;
 
-  inline Int_t getNPar() const { return _fcn->NDim() ; }
-  inline std::ofstream* logfile() const { return _fcn->GetLogFile(); }
-  inline Double_t& maxFCN() { return _fcn->GetMaxFCN() ; }
+  inline Int_t getNPar() const { return fitterFcn()->NDim() ; }
+  inline std::ofstream* logfile() { return fitterFcn()->GetLogFile(); }
+  inline Double_t& maxFCN() { return fitterFcn()->GetMaxFCN() ; }
+  
+  const RooMinimizerFcn* fitterFcn() const {  return ( fitter()->GetFCN() ? ((RooMinimizerFcn*) fitter()->GetFCN()) : _fcn ) ; }
+  RooMinimizerFcn* fitterFcn() { return ( fitter()->GetFCN() ? ((RooMinimizerFcn*) fitter()->GetFCN()) : _fcn ) ; }
 
 private:
 
diff --git a/roofit/roofitcore/inc/RooNLLVar.h b/roofit/roofitcore/inc/RooNLLVar.h
index f030731..d7e21cd 100644
--- a/roofit/roofitcore/inc/RooNLLVar.h
+++ b/roofit/roofitcore/inc/RooNLLVar.h
@@ -63,8 +63,10 @@ protected:
   virtual Double_t evaluatePartition(Int_t firstEvent, Int_t lastEvent, Int_t stepSize) const ;
   Bool_t _weightSq ; // Apply weights squared?
   mutable Bool_t _first ; //!
+  Double_t _offsetSaveW2; //!
+  Double_t _offsetCarrySaveW2; //!
   
-  ClassDef(RooNLLVar,1) // Function representing (extended) -log(L) of p.d.f and dataset
+  ClassDef(RooNLLVar,2) // Function representing (extended) -log(L) of p.d.f and dataset
 };
 
 #endif
diff --git a/roofit/roofitcore/inc/RooRealMPFE.h b/roofit/roofitcore/inc/RooRealMPFE.h
index 98dec08..e803599 100644
--- a/roofit/roofitcore/inc/RooRealMPFE.h
+++ b/roofit/roofitcore/inc/RooRealMPFE.h
@@ -25,6 +25,7 @@
 #include <vector> 
 
 class RooArgSet ;
+namespace RooFit { class BidirMMapPipe; }
 
 class RooRealMPFE : public RooAbsReal {
 public:
@@ -52,12 +53,13 @@ public:
   virtual Double_t evaluate() const ;
   friend class RooAbsTestStatistic ;
   virtual void constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTracking=kTRUE) ;
+  virtual Double_t getCarry() const;
 
   enum State { Initialize,Client,Server,Inline } ;
   State _state ;
 
-  enum Message { SendReal=0, SendCat=1, Calculate=2, Retrieve=3, ReturnValue=4, Terminate=5, 
-		 ConstOpt=6, Verbose=7, RetrieveErrors=8, SendError=9, LogEvalError=10, ApplyNLLW2=11, EnableOffset=12, CalculateNoOffset=13 } ;
+  enum Message { SendReal=0, SendCat, Calculate, Retrieve, ReturnValue, Terminate, 
+		 ConstOpt, Verbose, LogEvalError, ApplyNLLW2, EnableOffset, CalculateNoOffset } ;
   
   void initialize() ; 
   void initVars() ;
@@ -74,19 +76,18 @@ public:
   Bool_t _inlineMode ;
   mutable Bool_t _forceCalc ;
   mutable RooAbsReal::ErrorLoggingMode _remoteEvalErrorLoggingState ;
-  Int_t  _pid ;            // PID of child process
 
-  Int_t _pipeToClient[2] ; // Pipe to client process
-  Int_t _pipeToServer[2] ; // Pipe to server process
+  RooFit::BidirMMapPipe *_pipe; //! connection to child
 
   mutable std::vector<Bool_t> _valueChanged ; //! Flags if variable needs update on server-side
   mutable std::vector<Bool_t> _constChanged ; //! Flags if variable needs update on server-side
   RooRealMPFE* _updateMaster ; //! Update master
   mutable Bool_t _retrieveDispatched ; //!
+  mutable Double_t _evalCarry; //!
 
   static RooMPSentinel _sentinel ;
 
-  ClassDef(RooRealMPFE,1) // Multi-process front-end for parallel calculation of a real valued function 
+  ClassDef(RooRealMPFE,2) // Multi-process front-end for parallel calculation of a real valued function 
 };
 
 #endif
diff --git a/roofit/roofitcore/inc/RooSimultaneous.h b/roofit/roofitcore/inc/RooSimultaneous.h
index b7654da..ae24be0 100644
--- a/roofit/roofitcore/inc/RooSimultaneous.h
+++ b/roofit/roofitcore/inc/RooSimultaneous.h
@@ -68,6 +68,7 @@ public:
 			  const RooCmdArg& arg9=RooCmdArg(), const RooCmdArg& arg10=RooCmdArg()) const {
     return RooAbsReal::plotOn(frame,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) ;
   }
+  virtual RooPlot* plotOn(RooPlot* frame, RooLinkedList& cmdList) const ;
 
   // Backward compatibility function
   virtual RooPlot *plotOn(RooPlot *frame, Option_t* drawOptions, Double_t scaleFactor=1.0, 
@@ -87,7 +88,6 @@ public:
 protected:
 
   void initialize(RooAbsCategoryLValue& inIndexCat, std::map<std::string,RooAbsPdf*> pdfMap) ;
-  virtual RooPlot* plotOn(RooPlot* frame, RooLinkedList& cmdList) const ;
 
   virtual void selectNormalization(const RooArgSet* depSet=0, Bool_t force=kFALSE) ;
   virtual void selectNormalizationRange(const char* rangeName=0, Bool_t force=kFALSE) ;
diff --git a/roofit/roofitcore/src/BidirMMapPipe.cxx b/roofit/roofitcore/src/BidirMMapPipe.cxx
new file mode 100644
index 0000000..37ea360
--- /dev/null
+++ b/roofit/roofitcore/src/BidirMMapPipe.cxx
@@ -0,0 +1,1967 @@
+/** @file BidirMMapPipe.cxx
+ *
+ * implementation of BidirMMapPipe, a class which forks off a child process
+ * and serves as communications channel between parent and child
+ *
+ * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+ * @date 2013-07-07
+ */
+#ifndef _WIN32
+#include <map>
+#include <cerrno>
+#include <limits>
+#include <string>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <algorithm>
+#include <exception>
+
+#include <poll.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+
+#include "BidirMMapPipe.h"
+
+#define BEGIN_NAMESPACE_ROOFIT namespace RooFit {
+#define END_NAMESPACE_ROOFIT }
+
+BEGIN_NAMESPACE_ROOFIT
+
+/// namespace for implementation details of BidirMMapPipe
+namespace BidirMMapPipe_impl {
+    /** @brief exception to throw if low-level OS calls go wrong
+     *
+     * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+     * @date 2013-07-07
+     */
+    class BidirMMapPipeException : public std::exception
+    {
+	private:
+	    enum {
+		s_sz = 256 ///< length of buffer
+	    };
+	    char m_buf[s_sz]; ///< buffer containing the error message
+
+	    /// for the POSIX version of strerror_r
+	    static int dostrerror_r(int err, char* buf, std::size_t sz,
+		    int (*f)(int, char*, std::size_t))
+	    { return f(err, buf, sz); }
+	    /// for the GNU version of strerror_r
+	    static int dostrerror_r(int, char*, std::size_t,
+		    char* (*f)(int, char*, std::size_t));
+	public:
+	    /// constructor taking error code, hint on operation (msg)
+	    BidirMMapPipeException(const char* msg, int err);
+	    /// return a destcription of what went wrong
+	    virtual const char* what() const throw() { return m_buf; }
+    };
+
+    BidirMMapPipeException::BidirMMapPipeException(const char* msg, int err)
+    {
+	std::size_t msgsz = std::strlen(msg);
+	if (msgsz) {
+	    msgsz = std::min(msgsz, std::size_t(s_sz));
+	    std::copy(msg, msg + msgsz, m_buf);
+	    if (msgsz < s_sz) { m_buf[msgsz] = ':'; ++msgsz; }
+	    if (msgsz < s_sz) { m_buf[msgsz] = ' '; ++msgsz; }
+	}
+	if (msgsz < s_sz) {
+	    // UGLY: GNU and POSIX cannot agree on prototype and behaviour, so
+	    // have to sort it out with overloads
+	    dostrerror_r(err, &m_buf[msgsz], s_sz - msgsz, ::strerror_r);
+	}
+	m_buf[s_sz - 1] = 0; // enforce zero-termination
+    }
+
+    int BidirMMapPipeException::dostrerror_r(int err, char* buf,
+	    std::size_t sz, char* (*f)(int, char*, std::size_t))
+    {
+	buf[0] = 0;
+	char *tmp = f(err, buf, sz);
+	if (tmp && tmp != buf) {
+	    std::strncpy(buf, tmp, sz);
+	    buf[sz - 1] = 0;
+	    if (std::strlen(tmp) > sz - 1) return ERANGE;
+	}
+	return 0;
+    }
+
+    /** @brief class representing the header structure in an mmapped page
+     *
+     * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+     * @date 2013-07-07
+     *
+     * contains a field to put pages into a linked list, a field for the size
+     * of the data being transmitted, and a field for the position until which
+     * the data has been read
+     */
+    class Page
+    {
+	private:
+	    // use as small a data type as possible to maximise payload area
+	    // of pages
+	    short m_next;		///< next page in list (in pagesizes)
+	    unsigned short m_size;	///< size of payload (in bytes)
+	    unsigned short m_pos;	///< index of next byte in payload area
+	    /// copy construction forbidden
+	    Page(const Page&) {}
+	    /// assertignment forbidden
+	    Page& operator=(const Page&)
+	    { return *reinterpret_cast<Page*>(0); }
+	public:
+	    /// constructor
+	    Page() : m_next(0), m_size(0), m_pos(0)
+	    {
+		// check that short is big enough - must be done at runtime
+		// because the page size is not known until runtime
+		assert(std::numeric_limits<unsigned short>::max() >=
+			PageChunk::pagesize());
+	    }
+	    /// set pointer to next page
+	    void setNext(const Page* p);
+	    /// return pointer to next page
+	    Page* next() const;
+	    /// return reference to size field
+	    unsigned short& size() { return m_size; }
+	    /// return size (of payload data)
+	    unsigned size() const { return m_size; }
+	    /// return reference to position field
+	    unsigned short& pos() { return m_pos; }
+	    /// return position
+	    unsigned pos() const { return m_pos; }
+	    /// return pointer to first byte in payload data area of page
+	    inline unsigned char* begin() const
+	    { return reinterpret_cast<unsigned char*>(const_cast<Page*>(this))
+		+ sizeof(Page); }
+	    /// return pointer to first byte in payload data area of page
+	    inline unsigned char* end() const
+	    { return reinterpret_cast<unsigned char*>(const_cast<Page*>(this))
+		+ PageChunk::pagesize(); }
+	    /// return the capacity of the page
+	    static unsigned capacity()
+	    { return PageChunk::pagesize() - sizeof(Page); }
+	    /// true if page empty
+	    bool empty() const { return !m_size; }
+	    /// true if page partially filled
+	    bool filled() const { return !empty(); }
+	    /// free space left (to be written to)
+	    unsigned free() const { return capacity() - m_size; }
+	    /// bytes remaining to be read
+	    unsigned remaining() const { return m_size - m_pos; }
+	    /// true if page completely full
+	    bool full() const { return !free(); }
+    };
+
+    void Page::setNext(const Page* p)
+    {
+	if (!p) {
+	    m_next = 0;
+	} else {
+	    const char* p1 = reinterpret_cast<char*>(this);
+	    const char* p2 = reinterpret_cast<const char*>(p);
+	    std::ptrdiff_t tmp = p2 - p1;
+	    // difference must be divisible by page size
+	    assert(!(tmp % PageChunk::pagesize()));
+	    tmp /= static_cast<std::ptrdiff_t>(PageChunk::pagesize());
+	    m_next = tmp;
+	    // no truncation when saving in a short
+	    assert(m_next == tmp);
+	    // final check: next() must return p
+	    assert(next() == p);
+	}
+    }
+
+    Page* Page::next() const
+    {
+	if (!m_next) return 0;
+	char* ptmp = reinterpret_cast<char*>(const_cast<Page*>(this));
+	ptmp += std::ptrdiff_t(m_next) * PageChunk::pagesize();
+	return reinterpret_cast<Page*>(ptmp);
+    }
+
+    /** @brief class representing a page pool
+     *
+     * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+     * @date 2013-07-24
+     *
+     * pool of mmapped pages (on systems which support it, on all others, the
+     * functionality is emulated with dynamically allocated memory)
+     *
+     * in most operating systems there is a limit to how many mappings any one
+     * process is allowed to request; for this reason, we mmap a relatively
+     * large amount up front, and then carve off little pieces as we need them
+     */
+    class PagePool {
+	private:
+	    /// convenience typedef
+	    typedef BidirMMapPipeException Exception;
+
+	    enum {
+		minsz = 7, ///< minimum chunk size (just below 1 << minsz bytes)
+		maxsz = 20, ///< maximum chunk size (just below 1 << maxsz bytes)
+		szincr = 1 ///< size class increment (sz = 1 << (minsz + k * szincr))
+	    };
+	    /// a chunk of memory in the pool
+	    typedef BidirMMapPipe_impl::PageChunk Chunk;
+	    /// list of chunks
+	    typedef std::list<Chunk*> ChunkList;
+
+	    friend class BidirMMapPipe_impl::PageChunk;
+	public:
+	    /// convenience typedef
+	    typedef PageChunk::MMapVariety MMapVariety;
+	    /// constructor
+	    PagePool(unsigned nPagesPerGroup);
+	    /// destructor
+	    ~PagePool();
+	    /// pop a free element out of the pool
+	    Pages pop();
+
+	    /// return page size of the system
+	    static unsigned pagesize() { return PageChunk::pagesize(); }
+	    /// return variety of mmap supported on the system
+	    static MMapVariety mmapVariety()
+	    { return PageChunk::mmapVariety(); }
+
+	    /// return number of pages per group (ie. as returned by pop())
+	    unsigned nPagesPerGroup() const { return m_nPgPerGrp; }
+
+	    /// zap the pool (unmap all but Pages p)
+	    void zap(Pages& p);
+
+	private:
+	    /// list of chunks used by the pool
+	    ChunkList m_chunks;
+	    /// list of chunks used by the pool which are not full
+	    ChunkList m_freelist;
+	    /// chunk size map (histogram of chunk sizes)
+	    unsigned m_szmap[(maxsz - minsz) / szincr];
+	    /// current chunk size
+	    int m_cursz;
+	    /// page group size
+	    unsigned m_nPgPerGrp;
+
+	    /// adjust _cursz to current largest block
+	    void updateCurSz(int sz, int incr);
+	    /// find size of next chunk to allocate (in a hopefully smart way)
+	    int nextChunkSz() const;
+	    /// release a chunk
+	    void putOnFreeList(Chunk* chunk);
+	    /// release a chunk
+	    void release(Chunk* chunk);
+    };
+
+    Pages::Pages(PageChunk* parent, Page* pages, unsigned npg) :
+	m_pimpl(new impl)
+    {
+	assert(npg < 256);
+	m_pimpl->m_parent = parent;
+	m_pimpl->m_pages = pages;
+	m_pimpl->m_refcnt = 1;
+	m_pimpl->m_npages = npg;
+	/// initialise pages
+	for (unsigned i = 0; i < m_pimpl->m_npages; ++i) new(page(i)) Page();
+    }
+
+    unsigned PageChunk::s_pagesize = PageChunk::getPageSize();
+    PageChunk::MMapVariety PageChunk::s_mmapworks = PageChunk::Unknown;
+
+    Pages::~Pages()
+    {
+	if (m_pimpl && !--(m_pimpl->m_refcnt)) {
+	    if (m_pimpl->m_parent) m_pimpl->m_parent->push(*this);
+	    delete m_pimpl;
+	}
+    }
+
+    Pages::Pages(const Pages& other) :
+	m_pimpl(other.m_pimpl)
+    { ++(m_pimpl->m_refcnt); }
+
+    Pages& Pages::operator=(const Pages& other)
+    {
+	if (&other == this) return *this;
+	if (--(m_pimpl->m_refcnt)) {
+	    if (m_pimpl->m_parent) m_pimpl->m_parent->push(*this);
+	    delete m_pimpl;
+	}
+	m_pimpl = other.m_pimpl;
+	++(m_pimpl->m_refcnt);
+	return *this;
+    }
+
+    unsigned Pages::pagesize() { return PageChunk::pagesize(); }
+
+    Page* Pages::page(unsigned pgno) const
+    {
+	assert(pgno < m_pimpl->m_npages);
+	unsigned char* pptr =
+	    reinterpret_cast<unsigned char*>(m_pimpl->m_pages);
+	pptr += pgno * pagesize();
+	return reinterpret_cast<Page*>(pptr);
+    }
+
+    unsigned Pages::pageno(Page* p) const
+    {
+	const unsigned char* pptr =
+	    reinterpret_cast<const unsigned char*>(p);
+	const unsigned char* bptr =
+	    reinterpret_cast<const unsigned char*>(m_pimpl->m_pages);
+	assert(0 == ((pptr - bptr) % pagesize()));
+	const unsigned nr = (pptr - bptr) / pagesize();
+	assert(nr < m_pimpl->m_npages);
+	return nr;
+    }
+
+    unsigned PageChunk::getPageSize()
+    {
+	// find out page size of system
+	long pgsz = sysconf(_SC_PAGESIZE);
+	if (-1 == pgsz) throw Exception("sysconf", errno);
+	if (pgsz > 512 && pgsz > long(sizeof(Page)))
+	    return pgsz;
+
+	// in case of failure or implausible value, use a safe default: 4k
+	// page size, and do not try to mmap
+	s_mmapworks = Copy;
+	return 1 << 12;
+    }
+
+    PageChunk::PageChunk(PagePool* parent,
+	    unsigned length, unsigned nPgPerGroup) :
+	m_begin(dommap(length)),
+	m_end(reinterpret_cast<void*>(
+		    reinterpret_cast<unsigned char*>(m_begin) + length)),
+	m_parent(parent), m_nPgPerGrp(nPgPerGroup), m_nUsedGrp(0)
+    {
+	// ok, push groups of pages onto freelist here
+	unsigned char* p = reinterpret_cast<unsigned char*>(m_begin);
+	unsigned char* pend = reinterpret_cast<unsigned char*>(m_end);
+	while (p < pend) {
+	    m_freelist.push_back(reinterpret_cast<void*>(p));
+	    p += nPgPerGroup * PagePool::pagesize();
+	}
+    }
+
+    PageChunk::~PageChunk()
+    {
+	if (m_parent) assert(empty());
+	if (m_begin) domunmap(m_begin, len());
+    }
+
+    bool PageChunk::contains(const Pages& p) const
+    { return p.m_pimpl->m_parent == this; }
+
+    Pages PageChunk::pop()
+    {
+	assert(!m_freelist.empty());
+	void* p = m_freelist.front();
+	m_freelist.pop_front();
+	++m_nUsedGrp;
+	return Pages(this, reinterpret_cast<Page*>(p), m_nPgPerGrp);
+    }
+
+    void PageChunk::push(const Pages& p)
+    {
+	assert(contains(p));
+	bool wasempty = m_freelist.empty();
+	m_freelist.push_front(reinterpret_cast<void*>(p[0u]));
+	--m_nUsedGrp;
+	if (m_parent) {
+	    // notify parent if we need to be put on the free list again
+	    if (wasempty) m_parent->putOnFreeList(this);
+	    // notify parent if we're empty
+	    if (empty()) return m_parent->release(this);
+	}
+    }
+
+    void* PageChunk::dommap(unsigned len)
+    {
+	assert(len && 0 == (len % s_pagesize));
+	// ok, the idea here is to try the different methods of mmapping, and
+	// choose the first one that works. we have four flavours:
+	// 1 - anonymous mmap (best)
+	// 2 - mmap of /dev/zero (about as good as anonymous mmap, but a tiny
+	//     bit more tedious to set up, since you need to open/close a
+	//     device file)
+	// 3 - mmap of a temporary file (very tedious to set up - need to
+	//     create a temporary file, delete it, make the underlying storage
+	//     large enough, then mmap the fd and close it)
+	// 4 - if all those fail, we malloc the buffers, and copy the data
+	//     through the OS (then we're no better than normal pipes)
+	static bool msgprinted = false;
+	if (Anonymous == s_mmapworks || Unknown == s_mmapworks) {
+#if defined(MAP_ANONYMOUS)
+#undef MYANONFLAG
+#define MYANONFLAG MAP_ANONYMOUS
+#elif defined(MAP_ANON)
+#undef MYANONFLAG
+#define MYANONFLAG MAP_ANON
+#else
+#undef MYANONFLAG
+#endif
+#ifdef MYANONFLAG
+	    void* retVal = ::mmap(0, len, PROT_READ | PROT_WRITE,
+		    MYANONFLAG | MAP_SHARED, -1, 0);
+	    if (MAP_FAILED == retVal) {
+		if (Anonymous == s_mmapworks) throw Exception("mmap", errno);
+	    } else {
+		assert(Unknown == s_mmapworks || Anonymous == s_mmapworks);
+		s_mmapworks = Anonymous;
+		if (!msgprinted) {
+		    std::cerr << "   INFO: In " << __func__ << " (" <<
+			__FILE__ << ", line " << __LINE__ <<
+			"): anonymous mmapping works, excellent!" <<
+			std::endl;
+		    msgprinted = true;
+		}
+		return retVal;
+	    }
+#endif
+#undef MYANONFLAG
+	}
+	if (DevZero == s_mmapworks || Unknown == s_mmapworks) {
+	    // ok, no anonymous mappings supported directly, so try to map
+	    // /dev/zero which has much the same effect on many systems
+	    int fd = ::open("/dev/zero", O_RDWR);
+	    if (-1 == fd)
+		throw Exception("open /dev/zero", errno);
+	    void* retVal = ::mmap(0, len,
+		    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	    if (MAP_FAILED == retVal) {
+		int errsv = errno;
+		::close(fd);
+		if (DevZero == s_mmapworks) throw Exception("mmap", errsv);
+	    } else {
+		assert(Unknown == s_mmapworks || DevZero == s_mmapworks);
+		s_mmapworks = DevZero;
+	    }
+	    if (-1 == ::close(fd))
+		throw Exception("close /dev/zero", errno);
+	    if (!msgprinted) {
+		std::cerr << "   INFO: In " << __func__ << " (" << __FILE__ <<
+		    ", line " << __LINE__ << "): mmapping /dev/zero works, "
+		    "very good!" << std::endl;
+		msgprinted = true;
+	    }
+	    return retVal;
+	}
+	if (FileBacked == s_mmapworks || Unknown == s_mmapworks) {
+	    char name[] = "/tmp/BidirMMapPipe-XXXXXX";
+	    int fd;
+	    // open temp file
+	    if (-1 == (fd = ::mkstemp(name))) throw Exception("mkstemp", errno);
+	    // remove it, but keep fd open
+	    if (-1 == ::unlink(name)) {
+		int errsv = errno;
+		::close(fd);
+		throw Exception("unlink", errsv);
+	    }
+	    // make it the right size: lseek
+	    if (-1 == ::lseek(fd, len - 1, SEEK_SET)) {
+		int errsv = errno;
+		::close(fd);
+		throw Exception("lseek", errsv);
+	    }
+	    // make it the right size: write a byte
+	    if (1 != ::write(fd, name, 1)) {
+		int errsv = errno;
+		::close(fd);
+		throw Exception("write", errsv);
+	    }
+	    // do mmap
+	    void* retVal = ::mmap(0, len,
+		    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	    if (MAP_FAILED == retVal) {
+		int errsv = errno;
+		::close(fd);
+		if (FileBacked == s_mmapworks) throw Exception("mmap", errsv);
+	    } else {
+		assert(Unknown == s_mmapworks || FileBacked == s_mmapworks);
+		s_mmapworks = FileBacked;
+	    }
+	    if (-1 == ::close(fd)) {
+		int errsv = errno;
+		::munmap(retVal, len);
+		throw Exception("close", errsv);
+	    }
+	    if (!msgprinted) {
+		std::cerr << "   INFO: In " << __func__ << " (" << __FILE__ <<
+		    ", line " << __LINE__ << "): mmapping temporary files "
+		    "works, good!" << std::endl;
+		msgprinted = true;
+	    }
+	    return retVal;
+	}
+	if (Copy == s_mmapworks || Unknown == s_mmapworks) {
+	    // fallback solution: mmap does not work on this OS (or does not
+	    // work for what we want to use it), so use a normal buffer of
+	    // memory instead, and collect data in that buffer - this needs an
+	    // additional write/read to/from the pipe(s), but there you go...
+	    if (!msgprinted) {
+		std::cerr << "WARNING: In " << __func__ << " (" << __FILE__ <<
+		    ", line " << __LINE__ << "): anonymous mmapping of "
+		    "shared buffers failed, falling back to read/write on "
+		    " pipes!" << std::endl;
+		msgprinted = true;
+	    }
+	    s_mmapworks = Copy;
+	    void* retVal = std::malloc(len);
+	    if (!retVal) throw Exception("malloc", errno);
+	    return retVal;
+	}
+	// should never get here
+	assert(false);
+	return 0;
+    }
+
+    void PageChunk::domunmap(void* addr, unsigned len)
+    {
+	assert(len && 0 == (len % s_pagesize));
+	if (addr) {
+	    assert(Unknown != s_mmapworks);
+	    if (Copy != s_mmapworks) {
+		if (-1 == ::munmap(addr, len))
+		    throw Exception("munmap", errno);
+	    } else {
+		std::free(addr);
+	    }
+	}
+    }
+
+    void PageChunk::zap(Pages& p)
+    {
+	// try to mprotect the other bits of the pool with no access...
+	// we'd really like a version of mremap here that can unmap all the
+	// other pages in the chunk, but that does not exist, so we protect
+	// the other pages in this chunk such that they may neither be read,
+	// written nor executed, only the pages we're interested in for
+	// communications stay readable and writable
+	//
+	// if an OS does not support changing the protection of a part of an
+	// mmapped area, the mprotect calls below should just fail and not
+	// change any protection, so we're a little less safe against
+	// corruption, but everything should still work
+	if (Copy != s_mmapworks) {
+	    unsigned char* p0 = reinterpret_cast<unsigned char*>(m_begin);
+	    unsigned char* p1 = reinterpret_cast<unsigned char*>(p[0u]);
+	    unsigned char* p2 = p1 + p.npages() * pagesize();
+	    unsigned char* p3 = reinterpret_cast<unsigned char*>(m_end);
+	    if (p1 != p0) ::mprotect(p0, p1 - p0, PROT_NONE);
+	    if (p2 != p3) ::mprotect(p2, p3 - p2, PROT_NONE);
+	}
+	m_parent = 0;
+	m_freelist.clear();
+	m_nUsedGrp = 1;
+	p.m_pimpl->m_parent = 0;
+	m_begin = m_end = 0;
+	// commit suicide
+	delete this;
+    }
+
+    PagePool::PagePool(unsigned nPgPerGroup) :
+	m_cursz(minsz), m_nPgPerGrp(nPgPerGroup)
+    { std::fill(m_szmap, m_szmap + ((maxsz - minsz) / szincr), 0); }
+
+    PagePool::~PagePool()
+    { 
+	m_freelist.clear();
+	for (ChunkList::iterator it = m_chunks.begin(); m_chunks.end() != it; ++it)
+	    delete *it;
+	m_chunks.clear();
+    }
+    
+    void PagePool::zap(Pages& p)
+    {
+	// unmap all pages but those pointed to by p
+	m_freelist.clear();
+	for (ChunkList::iterator it = m_chunks.begin(); m_chunks.end() != it; ++it) {
+	    if ((*it)->contains(p)) {
+		(*it)->zap(p);
+	    } else {
+		delete *it;
+	    }
+	}
+	m_chunks.clear();
+	std::fill(m_szmap, m_szmap + ((maxsz - minsz) / szincr), 0);
+	m_cursz = minsz;
+    }
+
+    Pages PagePool::pop()
+    { 
+	if (m_freelist.empty()) {
+	    // allocate and register new chunk and put it on the freelist
+	    const int sz = nextChunkSz();
+	    Chunk *c = new Chunk(this,
+		    sz * m_nPgPerGrp * pagesize(), m_nPgPerGrp);
+	    m_chunks.push_front(c);
+	    m_freelist.push_back(c);
+	    updateCurSz(sz, +1);
+	}
+	// get free element from first chunk on _freelist
+	Chunk* c = m_freelist.front();
+	Pages p(c->pop());
+	// full chunks are removed from _freelist
+	if (c->full()) m_freelist.pop_front();
+	return p;
+    }
+
+    void PagePool::release(PageChunk* chunk)
+    { 
+	assert(chunk->empty());
+	// find chunk on freelist and remove
+	ChunkList::iterator it = std::find(
+		m_freelist.begin(), m_freelist.end(), chunk);
+	if (m_freelist.end() == it)
+	    throw Exception("PagePool::release(PageChunk*)", EINVAL);
+	m_freelist.erase(it);
+	// find chunk in m_chunks and remove
+	it = std::find(m_chunks.begin(), m_chunks.end(), chunk);
+	if (m_chunks.end() == it)
+	    throw Exception("PagePool::release(PageChunk*)", EINVAL);
+	m_chunks.erase(it);
+	const unsigned sz = chunk->len() / (pagesize() * m_nPgPerGrp);
+	delete chunk;
+	updateCurSz(sz, -1);
+    }
+
+    void PagePool::putOnFreeList(PageChunk* chunk)
+    {
+	assert(!chunk->full());
+	m_freelist.push_back(chunk);
+    }
+
+    void PagePool::updateCurSz(int sz, int incr)
+    {
+	m_szmap[(sz - minsz) / szincr] += incr;
+	m_cursz = minsz;
+	for (int i = (maxsz - minsz) / szincr; i--; ) {
+	    if (m_szmap[i]) {
+		m_cursz += i * szincr;
+		break;
+	    }
+	}
+    }
+
+    int PagePool::nextChunkSz() const
+    {
+	// no chunks with space available, figure out chunk size
+	int sz = m_cursz;
+	if (m_chunks.empty()) {
+	    // if we start allocating chunks, we start from minsz
+	    sz = minsz;
+	} else {
+	    if (minsz >= sz) {
+		// minimal sized chunks are always grown
+		sz = minsz + szincr;
+	    } else {
+		if (1 != m_chunks.size()) {
+		    // if we have more than one completely filled chunk, grow
+		    sz += szincr;
+		} else {
+		    // just one chunk left, try shrinking chunk size
+		    sz -= szincr;
+		}
+	    }
+	}
+	// clamp size to allowed range
+	if (sz > maxsz) sz = maxsz;
+	if (sz < minsz) sz = minsz;
+	return sz;
+    }
+}
+
+// static BidirMMapPipe members
+pthread_mutex_t BidirMMapPipe::s_openpipesmutex = PTHREAD_MUTEX_INITIALIZER;
+std::list<BidirMMapPipe*> BidirMMapPipe::s_openpipes;
+BidirMMapPipe_impl::PagePool* BidirMMapPipe::s_pagepool = 0;
+unsigned BidirMMapPipe::s_pagepoolrefcnt = 0;
+
+BidirMMapPipe_impl::PagePool& BidirMMapPipe::pagepool()
+{
+    if (!s_pagepool)
+	s_pagepool = new BidirMMapPipe_impl::PagePool(TotPages);
+    return *s_pagepool;
+}
+
+void BidirMMapPipe::teardownall(void)
+{
+    pthread_mutex_lock(&s_openpipesmutex);
+    while (!s_openpipes.empty()) {
+	BidirMMapPipe *p = s_openpipes.front();
+	pthread_mutex_unlock(&s_openpipesmutex);
+	if (p->m_childPid) kill(p->m_childPid, SIGTERM);
+	p->doClose(true, true);
+	pthread_mutex_lock(&s_openpipesmutex);
+    }
+    pthread_mutex_unlock(&s_openpipesmutex);
+}
+
+BidirMMapPipe::BidirMMapPipe(const BidirMMapPipe&) :
+    m_pages(pagepool().pop())
+{
+    // free pages again
+    { BidirMMapPipe_impl::Pages p; p.swap(m_pages); }
+    if (!s_pagepoolrefcnt) {
+	delete s_pagepool;
+	s_pagepool = 0;
+    }
+}
+
+BidirMMapPipe::BidirMMapPipe(bool useExceptions, bool useSocketpair) :
+    m_pages(pagepool().pop()), m_busylist(0), m_freelist(0), m_dirtylist(0),
+    m_inpipe(-1), m_outpipe(-1), m_flags(failbit), m_childPid(0),
+    m_parentPid(::getpid())
+
+{
+    ++s_pagepoolrefcnt;
+    assert(TotPages && 0 == (TotPages & 1) && TotPages <= 256);
+    int fds[4] = { -1, -1, -1, -1 };
+    int myerrno;
+    static bool firstcall = true;
+    if (useExceptions) m_flags |= exceptionsbit;
+
+    try {
+	if (firstcall) {
+	    firstcall = false;
+	    // register a cleanup handler to make sure all BidirMMapPipes are torn
+	    // down, and child processes are sent a SIGTERM
+	    if (0 != atexit(BidirMMapPipe::teardownall))
+		throw Exception("atexit", errno);
+	}
+
+	// build free lists
+	for (unsigned i = 1; i < TotPages; ++i)
+	    m_pages[i - 1]->setNext(m_pages[i]);
+	m_pages[PagesPerEnd - 1]->setNext(0);
+	if (!useSocketpair) {
+	    // create pipes
+	    if (0 != ::pipe(&fds[0])) throw Exception("pipe", errno);
+	    if (0 != ::pipe(&fds[2])) throw Exception("pipe", errno);
+	} else {
+	    if (0 != ::socketpair(AF_UNIX, SOCK_STREAM, 0, &fds[0]))
+		throw Exception("socketpair", errno);
+	}
+	// fork the child
+	pthread_mutex_lock(&s_openpipesmutex);
+	char c;
+	switch ((m_childPid = ::fork())) {
+	    case -1: // error in fork()
+		myerrno = errno;
+		pthread_mutex_unlock(&s_openpipesmutex);
+		m_childPid = 0;
+		throw Exception("fork", myerrno);
+	    case 0: // child
+		// put the ends in the right place
+		if (-1 != fds[2]) {
+		    // pair of pipes
+		    if (-1 == ::close(fds[0]) || (-1 == ::close(fds[3]))) {
+			myerrno = errno;
+			pthread_mutex_unlock(&s_openpipesmutex);
+			throw Exception("close", myerrno);
+		    }
+		    fds[0] = fds[3] = -1;
+		    m_outpipe = fds[1];
+		    m_inpipe = fds[2];
+		} else {
+		    // socket pair
+		    if (-1 == ::close(fds[0])) {
+			myerrno = errno;
+			pthread_mutex_unlock(&s_openpipesmutex);
+			throw Exception("close", myerrno);
+		    }
+		    fds[0] = -1;
+		    m_inpipe = m_outpipe = fds[1];
+		}
+		// close other pipes our parent may have open - we have no business
+		// reading from/writing to those...
+		for (std::list<BidirMMapPipe*>::iterator it = s_openpipes.begin();
+			s_openpipes.end() != it; ) {
+		    BidirMMapPipe* p = *it;
+		    it = s_openpipes.erase(it);
+		    p->doClose(true, true);
+		}
+		pagepool().zap(m_pages);
+		s_pagepoolrefcnt = 0;
+		delete s_pagepool;
+		s_pagepool = 0;
+		s_openpipes.push_front(this);
+		pthread_mutex_unlock(&s_openpipesmutex);
+		// ok, put our pages on freelist
+		m_freelist = m_pages[PagesPerEnd];
+		// handshare with other end (to make sure it's alive)...
+		c = 'C'; // ...hild
+		if (1 != xferraw(m_outpipe, &c, 1, ::write))
+		    throw Exception("handshake: xferraw write", EPIPE);
+		if (1 != xferraw(m_inpipe, &c, 1, ::read))
+		    throw Exception("handshake: xferraw read", EPIPE);
+		if ('P' != c) throw Exception("handshake", EPIPE);
+		break;
+	    default: // parent
+		// put the ends in the right place
+		if (-1 != fds[2]) {
+		    // pair of pipes
+		    if (-1 == ::close(fds[1]) || -1 == ::close(fds[2])) {
+			myerrno = errno;
+			pthread_mutex_unlock(&s_openpipesmutex);
+			throw Exception("close", myerrno);
+		    }
+		    fds[1] = fds[2] = -1;
+		    m_outpipe = fds[3];
+		    m_inpipe = fds[0];
+		} else {
+		    // socketpair
+		    if (-1 == ::close(fds[1])) {
+			myerrno = errno;
+			pthread_mutex_unlock(&s_openpipesmutex);
+			throw Exception("close", myerrno);
+		    }
+		    fds[1] = -1;
+		    m_inpipe = m_outpipe = fds[0];
+		}
+		// put on list of open pipes (so we can kill child processes
+		// if things go wrong)
+		s_openpipes.push_front(this);
+		pthread_mutex_unlock(&s_openpipesmutex);
+		// ok, put our pages on freelist
+		m_freelist = m_pages[0u];
+		// handshare with other end (to make sure it's alive)...
+		c = 'P'; // ...arent
+		if (1 != xferraw(m_outpipe, &c, 1, ::write))
+		    throw Exception("handshake: xferraw write", EPIPE);
+		if (1 != xferraw(m_inpipe, &c, 1, ::read))
+		    throw Exception("handshake: xferraw read", EPIPE);
+		if ('C' != c) throw Exception("handshake", EPIPE);
+		break;
+	}
+	// mark file descriptors for close on exec (we do not want to leak the
+	// connection to anything we happen to exec)
+	int fdflags = 0;
+	if (-1 == ::fcntl(m_outpipe, F_GETFD, &fdflags))
+	    throw Exception("fcntl", errno);
+	fdflags |= FD_CLOEXEC;
+	if (-1 == ::fcntl(m_outpipe, F_SETFD, fdflags))
+	    throw Exception("fcntl", errno);
+	if (m_inpipe != m_outpipe) {
+	    if (-1 == ::fcntl(m_inpipe, F_GETFD, &fdflags))
+		throw Exception("fcntl", errno);
+	    fdflags |= FD_CLOEXEC;
+	    if (-1 == ::fcntl(m_inpipe, F_SETFD, fdflags))
+		throw Exception("fcntl", errno);
+	}
+	// ok, finally, clear the failbit
+	m_flags &= ~failbit;
+	// all done
+    } catch (const BidirMMapPipe::Exception& e) {
+	if (0 != m_childPid) kill(m_childPid, SIGTERM);
+	for (int i = 0; i < 4; ++i)
+	    if (-1 != fds[i] && 0 != fds[i]) ::close(fds[i]);
+	{
+	    // free resources associated with mmapped pages
+	    BidirMMapPipe_impl::Pages p; p.swap(m_pages);
+	}
+	if (!--s_pagepoolrefcnt) {
+	    delete s_pagepool;
+	    s_pagepool = 0;
+	}
+	throw e;
+    }
+}
+
+int BidirMMapPipe::close()
+{
+    assert(!(m_flags & failbit));
+    return doClose(false);
+}
+
+int BidirMMapPipe::doClose(bool force, bool holdlock)
+{
+    if (m_flags & failbit) return 0;
+    // flush data to be written
+    if (!force && -1 != m_outpipe && -1 != m_inpipe)
+	flush();
+    // close pipe ends
+    if (m_inpipe != m_outpipe) {
+	// close the write end first, so the other end can tell that the
+	// connection is going down because the its read end signals HUP
+	if (-1 != m_outpipe && -1 == ::close(m_outpipe))
+	    if (!force) throw Exception("close", errno);
+	m_outpipe = -1;
+	if (-1 != m_inpipe && -1 == ::close(m_inpipe))
+	    if (!force) throw Exception("close", errno);
+	m_inpipe = -1;
+    } else {
+	if (!force) {
+	    if (-1 != m_outpipe && -1 == ::shutdown(m_outpipe, SHUT_WR))
+		throw Exception("shutdown", errno);
+	    // **************** THIS IS EXTREMELY UGLY: ****************
+	    // POLLHUP is not set reliably on socket shutdown on all
+	    // platforms, unfortunately, so we poll for readability here until
+	    // the other end closes, too
+	    //
+	    // so, the read loop below ensures that the other end sees the
+	    // POLLIN that is set on shutdown instead, and goes ahead to close
+	    // its end
+	    //
+	    // if we don't do this, and close straight away, the other end
+	    // will catch a SIGPIPE or similar, and we don't want that
+	    int err;
+	    struct pollfd fds;
+	    fds.fd = m_outpipe;
+	    fds.events = POLLIN;
+	    fds.revents = 0;
+	    do {
+		while ((err = ::poll(&fds, 1, 1 << 20)) >= 0) {
+		    if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) break;
+		    if (fds.revents & POLLIN) {
+			char c;
+			if (1 > ::read(m_outpipe, &c, 1)) break;
+		    }
+		}
+	    } while (0 > err && EINTR == errno);
+	    // ignore all other poll errors
+	}
+	if (-1 != m_outpipe && -1 == ::close(m_outpipe))
+	    if (!force) throw Exception("close", errno);
+	m_inpipe = m_outpipe = -1;
+    }
+    // unmap memory
+    try {
+	{ BidirMMapPipe_impl::Pages p; p.swap(m_pages); }
+	if (!--s_pagepoolrefcnt) {
+	    delete s_pagepool;
+	    s_pagepool = 0;
+	}
+    } catch (const std::exception& e) {
+	if (!force) throw e;
+    }
+    m_busylist = m_freelist = m_dirtylist = 0;
+    // wait for child process
+    int retVal = 0;
+    if (isParent()) {
+	int tmp;
+	do {
+	    tmp = waitpid(m_childPid, &retVal, 0);
+	} while (-1 == tmp && EINTR == errno);
+	if (-1 == tmp)
+	    if (!force) throw Exception("waitpid", errno);
+	m_childPid = 0;
+    }
+    // remove from list of open pipes
+    if (!holdlock) pthread_mutex_lock(&s_openpipesmutex);
+    std::list<BidirMMapPipe*>::iterator it = std::find(
+	    s_openpipes.begin(), s_openpipes.end(), this);
+    if (s_openpipes.end() != it) s_openpipes.erase(it);
+    if (!holdlock) pthread_mutex_unlock(&s_openpipesmutex);
+    m_flags |= failbit;
+    return retVal;
+}
+
+BidirMMapPipe::~BidirMMapPipe()
+{ doClose(false); }
+
+BidirMMapPipe::size_type BidirMMapPipe::xferraw(
+	int fd, void* addr, size_type len,
+	ssize_t (*xferfn)(int, void*, std::size_t))
+{
+    size_type xferred = 0;
+    unsigned char* buf = reinterpret_cast<unsigned char*>(addr);
+    while (len) {
+	ssize_t tmp = xferfn(fd, buf, len);
+	if (tmp > 0) {
+	    xferred += tmp;
+	    len -= tmp;
+	    buf += tmp;
+	    continue;
+	} else if (0 == tmp) {
+	    // check for end-of-file on pipe
+	    break;
+	} else if (-1 == tmp) {
+	    // ok some error occurred, so figure out if we want to retry of throw
+	    switch (errno) {
+		default:
+		    // if anything was transferred, return number of bytes
+		    // transferred so far, we can start throwing on the next
+		    // transfer...
+		    if (xferred) return xferred;
+		    // else throw
+		    throw Exception("xferraw", errno);
+		case EAGAIN: // fallthrough intended
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+		case EWOULDBLOCK: // fallthrough intended
+#endif
+		    std::cerr << "  ERROR: In " << __func__ << " (" <<
+			__FILE__ << ", line " << __LINE__ <<
+			"): expect transfer to block!" << std::endl;
+		case EINTR:
+		    break;
+	    }
+	    continue;
+	} else {
+	    throw Exception("xferraw: unexpected return value from read/write",
+		    errno);
+	}
+    }
+    return xferred;
+}
+
+void BidirMMapPipe::sendpages(Page* plist)
+{
+    if (plist) {
+	unsigned char pg = m_pages[plist];
+	if (1 == xferraw(m_outpipe, &pg, 1, ::write)) {
+	    if (BidirMMapPipe_impl::PageChunk::Copy ==
+		    BidirMMapPipe_impl::PageChunk::mmapVariety()) {
+		// ok, have to copy pages through pipe
+		for (Page* p = plist; p; p = p->next()) {
+		    if (sizeof(Page) + p->size() !=
+			    xferraw(m_outpipe, p, sizeof(Page) + p->size(),
+				::write)) {
+			throw Exception("sendpages: short write", EPIPE);
+		    }
+		}
+	    }
+	} else {
+	    throw Exception("sendpages: short write", EPIPE);
+	}
+    } else { assert(plist); }
+}
+
+unsigned BidirMMapPipe::recvpages()
+{
+    unsigned char pg;
+    unsigned retVal = 0;
+    Page *plisthead = 0, *plisttail = 0;
+    if (1 == xferraw(m_inpipe, &pg, 1, ::read)) {
+	plisthead = plisttail = m_pages[pg];
+	// ok, have number of pages
+	if (BidirMMapPipe_impl::PageChunk::Copy ==
+		BidirMMapPipe_impl::PageChunk::mmapVariety()) {
+	    // ok, need to copy pages through pipe
+	    for (; plisttail; ++retVal) {
+		Page* p = plisttail;
+		if (sizeof(Page) == xferraw(m_inpipe, p, sizeof(Page),
+			    ::read)) {
+		    plisttail = p->next();
+		    if (!p->size()) continue;
+		    // break in case of read error
+		    if (p->size() != xferraw(m_inpipe, p->begin(), p->size(),
+				::read)) break;
+		}
+	    }
+	} else {
+	    retVal = lenPageList(plisthead);
+	}
+    }
+    // put list of pages we just received into correct lists (busy/free)
+    if (plisthead) feedPageLists(plisthead);
+    // ok, retVal contains the number of pages read, so put them on the
+    // correct lists
+    return retVal;
+}
+
+unsigned BidirMMapPipe::recvpages_nonblock()
+{
+    struct pollfd fds;
+    fds.fd = m_inpipe;
+    fds.events = POLLIN;
+    fds.revents = 0;
+    unsigned retVal = 0;
+    do {
+	int rc = ::poll(&fds, 1, 0);
+	if (0 > rc) {
+	    if (EINTR == errno) continue;
+	    break;
+	}
+	if (1 == retVal && fds.revents & POLLIN &&
+		!(fds.revents & (POLLNVAL | POLLERR))) {
+	    // ok, we can read without blocking, so the other end has
+	    // something for us
+	    return recvpages();
+	} else {
+	    break;
+	}
+    } while (true);
+    return retVal;
+}
+
+unsigned BidirMMapPipe::lenPageList(const Page* p)
+{
+    unsigned n = 0;
+    for ( ; p; p = p->next()) ++n;
+    return n;
+}
+
+void BidirMMapPipe::feedPageLists(Page* plist)
+{
+    assert(plist);
+    // get end of busy list
+    Page *blend = m_busylist;
+    while (blend && blend->next()) blend = blend->next();
+    // ok, might have to send free pages to other end, and (if we do have to
+    // send something to the other end) while we're at it, send any dirty
+    // pages which are completely full, too
+    Page *sendlisthead = 0, *sendlisttail = 0;
+    // loop over plist
+    while (plist) {
+	Page* p = plist;
+	plist = p->next();
+	p->setNext(0);
+	if (p->size()) {
+	    // busy page...
+	    p->pos() = 0;
+	    // put at end of busy list
+	    if (blend) blend->setNext(p);
+	    else m_busylist = p;
+	    blend = p;
+	} else {
+	    // free page...
+	    // Very simple algorithm: once we're done with a page, we send it back
+	    // where it came from. If it's from our end, we put it on the free list, if
+	    // it's from the other end, we send it back.
+	    if ((isParent() && m_pages[p] >= PagesPerEnd) ||
+		    (isChild() && m_pages[p] < PagesPerEnd)) {
+		// page "belongs" to other end
+		if (!sendlisthead) sendlisthead = p;
+		if (sendlisttail) sendlisttail->setNext(p);
+		sendlisttail = p;
+	    } else {
+		// add page to freelist
+		p->setNext(m_freelist);
+		m_freelist = p;
+	    }
+	}
+    }
+    // check if we have to send stuff to the other end
+    if (sendlisthead) {	
+	// go through our list of dirty pages, and see what we can
+	// send along
+	Page* dp;
+	while ((dp = m_dirtylist) && dp->full()) {
+	    Page* p = dp;
+	    // move head of dirty list
+	    m_dirtylist = p->next();
+	    // queue for sending
+	    p->setNext(0);
+	    sendlisttail->setNext(p);
+	    sendlisttail = p;
+	}
+	// poll if the other end is still alive - this needs that we first
+	// close the write pipe of the other end when the remote end of the
+	// connection is shutting down in doClose; we'll see that because we
+	// get a POLLHUP on our inpipe
+	const int nfds = (m_outpipe == m_inpipe) ? 1 : 2;
+	struct pollfd fds[2];
+	fds[0].fd = m_outpipe;
+	fds[0].events = fds[0].revents = 0;
+	if (m_outpipe != m_inpipe) {
+	    fds[1].fd = m_inpipe;
+	    fds[1].events = fds[1].revents = 0;
+	} else {
+	    fds[0].events |= POLLIN;
+	}
+	int retVal = 0;
+	do {
+	    retVal = ::poll(fds, nfds, 0);
+	    if (0 > retVal && EINTR == errno)
+		continue;
+	    break;
+	} while (true);
+	if (0 <= retVal) {
+	    bool ok = !(fds[0].revents & (POLLERR | POLLNVAL | POLLHUP));
+	    if (m_outpipe != m_inpipe) {
+		ok = ok && !(fds[1].revents & (POLLERR | POLLNVAL | POLLHUP));
+	    } else {
+		if (ok && fds[0].revents & POLLIN) {
+		    unsigned ret = recvpages();
+		    if (!ret) ok = false;
+		}
+	    }
+
+	    if (ok) sendpages(sendlisthead);
+	    // (if the pipe is dead already, we don't care that we leak the
+	    // contents of the pages on the send list here, so that is why
+	    // there's no else clause here)
+	} else {
+	    throw Exception("feedPageLists: poll", errno);
+	}
+    }
+}
+
+void BidirMMapPipe::markPageDirty(Page* p)
+{
+    assert(p);
+    assert(p == m_freelist);
+    // remove from freelist
+    m_freelist = p->next();
+    p->setNext(0);
+    // append to dirty list
+    Page* dl = m_dirtylist;
+    while (dl && dl->next()) dl = dl->next();
+    if (dl) dl->setNext(p);
+    else m_dirtylist = p;
+}
+
+BidirMMapPipe::Page* BidirMMapPipe::busypage()
+{
+    // queue any pages available for reading we can without blocking
+    recvpages_nonblock();
+    Page* p;
+    // if there are no busy pages, try to get them from the other end,
+    // block if we have to...
+    while (!(p = m_busylist)) if (!recvpages()) return 0;
+    return p;
+}
+
+BidirMMapPipe::Page* BidirMMapPipe::dirtypage()
+{
+    // queue any pages available for reading we can without blocking
+    recvpages_nonblock();
+    Page* p = m_dirtylist;
+    // go to end of dirty list
+    if (p) while (p->next()) p = p->next();
+    if (!p || p->full()) {
+	// need to append free page, so get one
+	while (!(p = m_freelist)) if (!recvpages()) return 0;
+	markPageDirty(p);
+    }
+    return p;
+}
+
+void BidirMMapPipe::flush()
+{ return doFlush(true); }
+
+void BidirMMapPipe::doFlush(bool forcePartialPages)
+{
+    assert(!(m_flags & failbit));
+    // build a list of pages to flush
+    Page *flushlisthead = 0, *flushlisttail = 0;
+    while (m_dirtylist) {
+	Page* p = m_dirtylist;
+	if (!forcePartialPages && !p->full()) break;
+	// remove dirty page from dirty list
+	m_dirtylist = p->next();
+	p->setNext(0);
+	// and send it to other end
+	if (!flushlisthead) flushlisthead = p;
+	if (flushlisttail) flushlisttail->setNext(p);
+	flushlisttail = p;
+    }
+    if (flushlisthead) sendpages(flushlisthead);
+}
+
+void BidirMMapPipe::purge()
+{
+    assert(!(m_flags & failbit));
+    // join busy and dirty lists
+    {
+	Page *l = m_busylist;
+	while (l && l->next()) l = l->next();
+	if (l) l->setNext(m_dirtylist);
+	else m_busylist = m_dirtylist;
+    }
+    // empty busy and dirty pages
+    for (Page* p = m_busylist; p; p = p->next()) p->size() = 0;
+    // put them on the free list
+    if (m_busylist) feedPageLists(m_busylist);
+    m_busylist = m_dirtylist = 0;
+}
+
+BidirMMapPipe::size_type BidirMMapPipe::bytesReadableNonBlocking()
+{
+    // queue all pages waiting for consumption in the pipe before we give an
+    // answer
+    recvpages_nonblock();
+    size_type retVal = 0;
+    for (Page* p = m_busylist; p; p = p->next())
+	retVal += p->size() - p->pos();
+    return retVal;
+}
+
+BidirMMapPipe::size_type BidirMMapPipe::bytesWritableNonBlocking()
+{
+    // queue all pages waiting for consumption in the pipe before we give an
+    // answer
+    recvpages_nonblock();
+    // check if we could write to the pipe without blocking (we need to know
+    // because we might need to check if flushing of dirty pages would block)
+    bool couldwrite = false;
+    {
+	struct pollfd fds;
+	fds.fd = m_outpipe;
+	fds.events = POLLOUT;
+	fds.revents = 0;
+	int retVal = 0;
+	do {
+	    retVal = ::poll(&fds, 1, 0);
+	    if (0 > retVal) {
+		if (EINTR == errno) continue;
+		throw Exception("bytesWritableNonBlocking: poll", errno);
+	    }
+	    if (1 == retVal && fds.revents & POLLOUT &&
+		    !(fds.revents & (POLLNVAL | POLLERR | POLLHUP)))
+		couldwrite = true;
+	    break;
+	} while (true);
+    }
+    // ok, start counting bytes
+    size_type retVal = 0;
+    unsigned npages = 0;
+    // go through the dirty list
+    for (Page* p = m_dirtylist; p; p = p->next()) {
+	++npages;
+	// if page only partially filled
+	if (!p->full())
+	    retVal += p->free();
+	if (npages >= FlushThresh && !couldwrite) break;
+    }
+    // go through the free list
+    for (Page* p = m_freelist; p && (!m_dirtylist ||
+		npages < FlushThresh || couldwrite); p = p->next()) {
+	++npages;
+	retVal += Page::capacity();
+    }
+    return retVal;
+}
+
+BidirMMapPipe::size_type BidirMMapPipe::read(void* addr, size_type sz)
+{
+    assert(!(m_flags & failbit));
+    size_type nread = 0;
+    unsigned char *ap = reinterpret_cast<unsigned char*>(addr);
+    try {
+	while (sz) {
+	    // find next page to read from
+	    Page* p = busypage();
+	    if (!p) {
+		m_flags |= eofbit;
+		return nread;
+	    }
+	    unsigned char* pp = p->begin() + p->pos();
+	    size_type csz = std::min(size_type(p->remaining()), sz);
+	    std::copy(pp, pp + csz, ap);
+	    nread += csz;
+	    ap += csz;
+	    sz -= csz;
+	    p->pos() += csz;
+	    assert(p->size() >= p->pos());
+	    if (p->size() == p->pos()) {
+		// if no unread data remains, page is free
+		m_busylist = p->next();
+		p->setNext(0);
+		p->size() = 0;
+		feedPageLists(p);
+	    }
+	}
+    } catch (const Exception& e) {
+	m_flags |= rderrbit;
+	if (m_flags & exceptionsbit) throw e;
+    }
+    return nread;
+}
+
+BidirMMapPipe::size_type BidirMMapPipe::write(const void* addr, size_type sz)
+{
+    assert(!(m_flags & failbit));
+    size_type written = 0;
+    const unsigned char *ap = reinterpret_cast<const unsigned char*>(addr);
+    try {
+	while (sz) {
+	    // find next page to write to
+	    Page* p = dirtypage();
+	    if (!p) {
+		m_flags |= eofbit;
+		return written;
+	    }
+	    unsigned char* pp = p->begin() + p->size();
+	    size_type csz = std::min(size_type(p->free()), sz);
+	    std::copy(ap, ap + csz, pp);
+	    written += csz;
+	    ap += csz;
+	    p->size() += csz;
+	    sz -= csz;
+	    assert(p->capacity() >= p->size());
+	    if (p->full()) {
+		// if page is full, see if we're above the flush threshold of
+		// 3/4 of our pages
+		if (lenPageList(m_dirtylist) >= FlushThresh)
+		    doFlush(false);
+	    }
+	}
+    } catch (const Exception& e) {
+	m_flags |= wrerrbit;
+	if (m_flags & exceptionsbit) throw e;
+    }
+    return written;
+}
+
+int BidirMMapPipe::poll(BidirMMapPipe::PollVector& pipes, int timeout)
+{
+    // go through pipes, and change flags where we already know without really
+    // polling - stuff where we don't need poll to wait for its timeout in the
+    // OS...
+    bool canskiptimeout = false;
+    std::vector<unsigned> masks(pipes.size(), ~(Readable | Writable));
+    std::vector<unsigned>::iterator mit = masks.begin();
+    for (PollVector::iterator it = pipes.begin(); pipes.end() != it;
+	    ++it, ++mit) {
+	PollEntry& pe = *it;
+	pe.revents = None;
+	// null pipe pointer or closed pipe is invalid
+	if (!pe.pipe || pe.pipe->closed()) pe.revents |= Invalid;
+	// check for error
+	if (pe.pipe->bad()) pe.revents |= Error;
+	// check for end of file
+	if (pe.pipe->eof()) pe.revents |= EndOfFile;
+	// check if readable
+	if (pe.events & Readable) {
+	    *mit |= Readable;
+	    if (pe.pipe->m_busylist) pe.revents |= Readable;
+	}
+	// check if writable
+	if (pe.events & Writable) {
+	    *mit |= Writable;
+	    if (pe.pipe->m_freelist) {
+		pe.revents |= Writable;
+	    } else {
+		Page *dl = pe.pipe->m_dirtylist;
+		while (dl && dl->next()) dl = dl->next();
+		if (dl && dl->pos() < Page::capacity())
+		    pe.revents |= Writable;
+	    }
+	}
+	if (pe.revents) canskiptimeout = true;
+    }
+    // set up the data structures required for the poll syscall
+    std::vector<pollfd> fds;
+    fds.reserve(2 * pipes.size());
+    std::map<int, PollEntry*> fds2pipes;
+    for (PollVector::const_iterator it = pipes.begin();
+	    pipes.end() != it; ++it) {
+	const PollEntry& pe = *it;
+	struct pollfd tmp;
+	fds2pipes.insert(std::make_pair((tmp.fd = pe.pipe->m_inpipe),
+		    const_cast<PollEntry*>(&pe)));
+	tmp.events = tmp.revents = 0;
+	// we always poll for readability; this allows us to queue pages
+	// early
+	tmp.events |= POLLIN;
+	if (pe.pipe->m_outpipe != tmp.fd) {
+	    // ok, it's a pair of pipes
+	    fds.push_back(tmp);
+	    fds2pipes.insert(std::make_pair(
+			unsigned(tmp.fd = pe.pipe->m_outpipe),
+			const_cast<PollEntry*>(&pe)));
+	    tmp.events = 0;
+
+	}
+	if (pe.events & Writable) tmp.events |= POLLOUT;
+	fds.push_back(tmp);
+    }
+    // poll
+    int retVal = 0;
+    do {
+	retVal = ::poll(&fds[0], fds.size(), canskiptimeout ? 0 : timeout);
+	if (0 > retVal) {
+	    if (EINTR == errno) continue;
+	    throw Exception("poll", errno);
+	}
+	break;
+    } while (true);
+    // fds may have changed state, so update...
+    for (std::vector<pollfd>::iterator it = fds.begin();
+	    fds.end() != it; ++it) {
+	pollfd& fe = *it;
+	//if (!fe.revents) continue;
+	--retVal;
+	PollEntry& pe = *fds2pipes[fe.fd];
+oncemore:
+	if (fe.revents & POLLNVAL && fe.fd == pe.pipe->m_inpipe)
+	    pe.revents |= ReadInvalid;
+	if (fe.revents & POLLNVAL && fe.fd == pe.pipe->m_outpipe)
+	    pe.revents |= WriteInvalid;
+	if (fe.revents & POLLERR && fe.fd == pe.pipe->m_inpipe)
+	    pe.revents |= ReadError;
+	if (fe.revents & POLLERR && fe.fd == pe.pipe->m_outpipe)
+	    pe.revents |= WriteError;
+	if (fe.revents & POLLHUP && fe.fd == pe.pipe->m_inpipe)
+	    pe.revents |= ReadEndOfFile;
+	if (fe.revents & POLLHUP && fe.fd == pe.pipe->m_outpipe)
+	    pe.revents |= WriteEndOfFile;
+	if ((fe.revents & POLLIN) && fe.fd == pe.pipe->m_inpipe &&
+		!(fe.revents & (POLLNVAL | POLLERR))) {
+	    // ok, there is at least one page for us to receive from the
+	    // other end
+	    if (0 == pe.pipe->recvpages()) continue;
+	    // more pages there?
+	    do {
+		int tmp = ::poll(&fe, 1, 0);
+		if (tmp > 0) goto oncemore; // yippie! I don't even feel bad!
+		if (0 > tmp) {
+		    if (EINTR == errno) continue;
+		    throw Exception("poll", errno);
+		}
+		break;
+	    } while (true);
+	}
+	if (pe.pipe->m_busylist) pe.revents |= Readable;
+	if (fe.revents & POLLOUT && fe.fd == pe.pipe->m_outpipe) {
+	    if (pe.pipe->m_freelist) {
+		pe.revents |= Writable;
+	    } else {
+		Page *dl = pe.pipe->m_dirtylist;
+		while (dl && dl->next()) dl = dl->next();
+		if (dl && dl->pos() < Page::capacity())
+		    pe.revents |= Writable;
+	    }
+	}
+    }
+    // apply correct masks, and count pipes with pending events
+    int npipes = 0;
+    mit = masks.begin();
+    for (PollVector::iterator it = pipes.begin();
+	    pipes.end() != it; ++it, ++mit)
+	if ((it->revents &= *mit)) ++npipes;
+    return npipes;
+}
+
+BidirMMapPipe& BidirMMapPipe::operator<<(const char* str)
+{
+    size_t sz = std::strlen(str);
+    *this << sz;
+    if (sz) write(str, sz);
+    return *this;
+}
+
+BidirMMapPipe& BidirMMapPipe::operator>>(char* (&str))
+{
+    size_t sz = 0;
+    *this >> sz;
+    if (good() && !eof()) {
+	str = reinterpret_cast<char*>(std::realloc(str, sz + 1));
+	if (!str) throw Exception("realloc", errno);
+	if (sz) read(str, sz);
+	str[sz] = 0;
+    }
+    return *this;
+}
+
+BidirMMapPipe& BidirMMapPipe::operator<<(const std::string& str)
+{
+    size_t sz = str.size();
+    *this << sz;
+    write(str.data(), sz);
+    return *this;
+}
+
+BidirMMapPipe& BidirMMapPipe::operator>>(std::string& str)
+{
+    str.clear();
+    size_t sz = 0;
+    *this >> sz;
+    if (good() && !eof()) {
+	str.reserve(sz);
+	for (unsigned char c; sz--; str.push_back(c)) *this >> c;
+    }
+    return *this;
+}
+
+END_NAMESPACE_ROOFIT
+
+#ifdef TEST_BIDIRMMAPPIPE
+using namespace RooFit;
+
+int simplechild(BidirMMapPipe& pipe)
+{
+    // child does an echo loop
+    while (pipe.good() && !pipe.eof()) {
+	// read a string
+	std::string str;
+	pipe >> str;
+	if (!pipe) return -1;
+	if (pipe.eof()) break;
+	if (!str.empty()) {
+	    std::cout << "[CHILD] :  read: " << str << std::endl;
+	    str = "... early in the morning?";
+	}
+	pipe << str << BidirMMapPipe::flush;
+	// did our parent tell us to shut down?
+	if (str.empty()) break;
+	if (!pipe) return -1;
+	if (pipe.eof()) break;
+	std::cout << "[CHILD] : wrote: " << str << std::endl;
+    }
+    pipe.close();
+    return 0;
+}
+
+#include <sstream>
+int randomchild(BidirMMapPipe& pipe)
+{
+    // child sends out something at random intervals
+    ::srand48(::getpid());
+    {
+	// wait for parent's go ahead signal
+	std::string s;
+	pipe >> s;
+    }
+    // no shutdown sequence needed on this side - we're producing the data,
+    // and the parent can just read until we're done (when it'll get EOF)
+    for (int i = 0; i < 5; ++i) {
+	// sleep a random time between 0 and .9 seconds
+	::usleep(int(1e6 * ::drand48()));
+	std::ostringstream buf;
+	buf << "child pid " << ::getpid() << " sends message " << i;
+	std::string str = buf.str();
+	std::cout << "[CHILD] : " << str << std::endl;
+	pipe << str << BidirMMapPipe::flush;
+	if (!pipe) return -1;
+	if (pipe.eof()) break;
+    }
+    // tell parent we're shutting down
+    pipe << "" << BidirMMapPipe::flush;
+    // wait for parent to acknowledge
+    std::string s;
+    pipe >> s;
+    pipe.close();
+    return 0;
+}
+
+int benchchildrtt(BidirMMapPipe& pipe)
+{
+    // child does the equivalent of listening for pings and sending the
+    // packet back
+    char* str = 0;
+    while (pipe && !pipe.eof()) {
+	pipe >> str;
+	if (!pipe) {
+	    std::free(str);
+	    pipe.close();
+	    return -1;
+	}
+	if (pipe.eof()) break;
+	pipe << str << BidirMMapPipe::flush;
+	// if we have just completed the shutdown handshake, we break here
+	if (!std::strlen(str)) break;
+    }
+    std::free(str);
+    pipe.close();
+    return 0;
+}
+
+int benchchildsink(BidirMMapPipe& pipe)
+{
+    // child behaves like a sink
+    char* str = 0;
+    while (pipe && !pipe.eof()) {
+	pipe >> str;
+	if (!std::strlen(str)) break;
+    }
+    pipe << "" << BidirMMapPipe::flush;
+    std::free(str);
+    pipe.close();
+    return 0;
+}
+
+int benchchildsource(BidirMMapPipe& pipe)
+{
+    // child behaves like a source
+    char* str = 0;
+    for (unsigned i = 0; i <= 24; ++i) {
+	str = reinterpret_cast<char*>(std::realloc(str, (1 << i) + 1));
+	std::memset(str, '4', 1 << i);
+	str[1 << i] = 0;
+	for (unsigned j = 0; j < 1 << 7; ++j) {
+	    pipe << str;
+	    if (!pipe || pipe.eof()) {
+		std::free(str);
+		pipe.close();
+		return -1;
+	    }
+	}
+	// tell parent we're done with this block size
+	pipe << "" << BidirMMapPipe::flush;
+    }
+    // tell parent to shut down
+    pipe << "" << BidirMMapPipe::flush;
+    std::free(str);
+    pipe.close();
+    return 0;
+}
+
+BidirMMapPipe* spawnChild(int (*childexec)(BidirMMapPipe&))
+{
+    // create a pipe with the given child at the remote end
+    BidirMMapPipe *p = new BidirMMapPipe();
+    if (p->isChild()) {
+	int retVal = childexec(*p);
+	delete p;
+	std::exit(retVal);
+    }
+    return p;
+}
+
+#include <sys/time.h>
+#include <iomanip>
+int main()
+{
+    // simple echo loop test
+    {
+	std::cout << "[PARENT]: simple challenge-response test, "
+	    "one child:" << std::endl;
+	BidirMMapPipe* pipe = spawnChild(simplechild);
+	for (int i = 0; i < 5; ++i) {
+	    std::string str("What shall we do with a drunken sailor...");
+	    *pipe << str << BidirMMapPipe::flush;
+	    if (!*pipe) return -1;
+	    std::cout << "[PARENT]: wrote: " << str << std::endl;
+	    *pipe >> str;
+	    if (!*pipe) return -1;
+	    std::cout << "[PARENT]:  read: " << str << std::endl;
+	}
+	// send shutdown string
+	*pipe << "" << BidirMMapPipe::flush;
+	// wait for shutdown handshake
+	std::string s;
+	*pipe >> s;
+	int retVal = pipe->close();
+	std::cout << "[PARENT]: exit status of child: " << retVal <<
+	    std::endl;
+	if (retVal) return retVal;
+	delete pipe;
+    }
+    // simple poll test - children send 5 results in random intervals
+    {
+	unsigned nch = 20;
+	std::cout << std::endl << "[PARENT]: polling test, " << nch <<
+	    " children:" << std::endl;
+	typedef BidirMMapPipe::PollEntry PollEntry;
+	// poll data structure
+	BidirMMapPipe::PollVector pipes;
+	pipes.reserve(nch);
+	// spawn children
+	for (unsigned i = 0; i < nch; ++i) {
+	    std::cout << "[PARENT]: spawning child " << i << std::endl;
+	    pipes.push_back(PollEntry(spawnChild(randomchild),
+			BidirMMapPipe::Readable));
+	}
+	// wake children up
+	std::cout << "[PARENT]: waking up children" << std::endl;
+	for (unsigned i = 0; i < nch; ++i)
+	    *pipes[i].pipe << "" << BidirMMapPipe::flush;
+	std::cout << "[PARENT]: waiting for events on children's pipes" << std::endl;
+	// while at least some children alive
+	while (!pipes.empty()) {
+	    // poll, wait until status change (infinite timeout)
+	    int npipes = BidirMMapPipe::poll(pipes, -1);
+	    // scan for pipes with changed status
+	    for (std::vector<PollEntry>::iterator it = pipes.begin();
+		    npipes && pipes.end() != it; ) {
+		if (!it->revents) {
+		    // unchanged, next one
+		    ++it;
+		    continue;
+		}
+		--npipes; // maybe we can stop early...
+		// read from pipes which are readable
+		if (it->revents & BidirMMapPipe::Readable) {
+		    std::string s;
+		    *(it->pipe) >> s;
+		    if (!s.empty()) {
+			std::cout << "[PARENT]: Read from pipe " << it->pipe <<
+			    ": " << s << std::endl;
+			++it;
+			continue;
+		    } else {
+			// child is shutting down...
+			*(it->pipe) << "" << BidirMMapPipe::flush;
+			goto childcloses;
+		    }
+		}
+		// retire pipes with error or end-of-file condition
+		if (it->revents & (BidirMMapPipe::Error |
+			    BidirMMapPipe::EndOfFile |
+			    BidirMMapPipe::Invalid)) {
+		    std::cerr << "[DEBUG]: Event on pipe " << it->pipe <<
+			" revents" <<
+			((it->revents & BidirMMapPipe::Readable) ? " Readable" : "") <<
+			((it->revents & BidirMMapPipe::Writable) ? " Writable" : "") <<
+			((it->revents & BidirMMapPipe::ReadError) ? " ReadError" : "") <<
+			((it->revents & BidirMMapPipe::WriteError) ? " WriteError" : "") <<
+			((it->revents & BidirMMapPipe::ReadEndOfFile) ? " ReadEndOfFile" : "") <<
+			((it->revents & BidirMMapPipe::WriteEndOfFile) ? " WriteEndOfFile" : "") <<
+			((it->revents & BidirMMapPipe::ReadInvalid) ? " ReadInvalid" : "") <<
+			((it->revents & BidirMMapPipe::WriteInvalid) ? " WriteInvalid" : "") <<
+			std::endl;
+childcloses:
+		    int retVal = it->pipe->close();
+		    std::cout << "[PARENT]:\tchild exit status: " <<
+			retVal << ", number of children still alive: " <<
+			(pipes.size() - 1) << std::endl;
+		    if (retVal) return retVal;
+		    delete it->pipe;
+		    it = pipes.erase(it);
+		    continue;
+		}
+	    }
+	}
+    }
+    // little benchmark - round trip time
+    {
+	std::cout << std::endl << "[PARENT]: benchmark: round-trip times vs block size" << std::endl;
+	for (unsigned i = 0; i <= 24; ++i) {
+	    char *s = new char[1 + (1 << i)];
+	    std::memset(s, 'A', 1 << i);
+	    s[1 << i] = 0;
+	    const unsigned n = 1 << 7;
+	    double avg = 0., min = 1e42, max = -1e42;
+	    BidirMMapPipe *pipe = spawnChild(benchchildrtt);
+	    for (unsigned j = n; j--; ) {
+		struct timeval t1;
+		::gettimeofday(&t1, 0);
+		*pipe << s << BidirMMapPipe::flush;
+		if (!*pipe || pipe->eof()) break;
+		*pipe >> s;
+		if (!*pipe || pipe->eof()) break;
+		struct timeval t2;
+		::gettimeofday(&t2, 0);
+		t2.tv_sec -= t1.tv_sec;
+		t2.tv_usec -= t1.tv_usec;
+		double dt = 1e-6 * double(t2.tv_usec) + double(t2.tv_sec);
+		if (dt < min) min = dt;
+		if (dt > max) max = dt;
+		avg += dt;
+	    }
+	    // send a shutdown string
+	    *pipe << "" << BidirMMapPipe::flush;
+	    // get child's shutdown ok
+	    *pipe >> s;
+	    avg /= double(n);
+	    avg *= 1e6; min *= 1e6; max *= 1e6;
+	    int retVal = pipe->close();
+	    if (retVal) {
+		std::cout << "[PARENT]: child exited with code " << retVal << std::endl;
+		return retVal;
+	    }
+	    delete pipe;
+	    // there is a factor 2 in the formula for the transfer rate below,
+	    // because we transfer data of twice the size of the block - once
+	    // to the child, and once for the return trip
+	    std::cout << "block size " << std::setw(9) << (1 << i) <<
+		" avg " << std::setw(7) << avg << " us min " <<
+		std::setw(7) << min << " us max " << std::setw(7) << max <<
+		"us speed " << std::setw(9) <<
+		2. * (double(1 << i) / double(1 << 20) / (1e-6 * avg)) <<
+		" MB/s" << std::endl;
+	    delete[] s;
+	}
+	std::cout << "[PARENT]: all children had exit code 0" << std::endl;
+    }
+    // little benchmark - child as sink
+    {
+	std::cout << std::endl << "[PARENT]: benchmark: raw transfer rate with child as sink" << std::endl;
+	for (unsigned i = 0; i <= 24; ++i) {
+	    char *s = new char[1 + (1 << i)];
+	    std::memset(s, 'A', 1 << i);
+	    s[1 << i] = 0;
+	    const unsigned n = 1 << 7;
+	    double avg = 0., min = 1e42, max = -1e42;
+	    BidirMMapPipe *pipe = spawnChild(benchchildsink);
+	    for (unsigned j = n; j--; ) {
+		struct timeval t1;
+		::gettimeofday(&t1, 0);
+		// streaming mode - we do not flush here
+		*pipe << s;
+		if (!*pipe || pipe->eof()) break;
+		struct timeval t2;
+		::gettimeofday(&t2, 0);
+		t2.tv_sec -= t1.tv_sec;
+		t2.tv_usec -= t1.tv_usec;
+		double dt = 1e-6 * double(t2.tv_usec) + double(t2.tv_sec);
+		if (dt < min) min = dt;
+		if (dt > max) max = dt;
+		avg += dt;
+	    }
+	    // send a shutdown string
+	    *pipe << "" << BidirMMapPipe::flush;
+	    // get child's shutdown ok
+	    *pipe >> s;
+	    avg /= double(n);
+	    avg *= 1e6; min *= 1e6; max *= 1e6;
+	    int retVal = pipe->close();
+	    if (retVal) {
+		std::cout << "[PARENT]: child exited with code " << retVal << std::endl;
+		return retVal;
+	    }
+	    delete pipe;
+	    std::cout << "block size " << std::setw(9) << (1 << i) <<
+		" avg " << std::setw(7) << avg << " us min " <<
+		std::setw(7) << min << " us max " << std::setw(7) << max <<
+		"us speed " << std::setw(9) <<
+		(double(1 << i) / double(1 << 20) / (1e-6 * avg)) <<
+		" MB/s" << std::endl;
+	    delete[] s;
+	}
+	std::cout << "[PARENT]: all children had exit code 0" << std::endl;
+    }
+    // little benchmark - child as source
+    {
+	std::cout << std::endl << "[PARENT]: benchmark: raw transfer rate with child as source" << std::endl;
+	char *s = 0;
+	double avg = 0., min = 1e42, max = -1e42;
+	unsigned n = 0, bsz = 0;
+	BidirMMapPipe *pipe = spawnChild(benchchildsource);
+	while (*pipe && !pipe->eof()) {
+	    struct timeval t1;
+	    ::gettimeofday(&t1, 0);
+	    // streaming mode - we do not flush here
+	    *pipe >> s;
+	    if (!*pipe || pipe->eof()) break;
+	    struct timeval t2;
+	    ::gettimeofday(&t2, 0);
+	    t2.tv_sec -= t1.tv_sec;
+	    t2.tv_usec -= t1.tv_usec;
+	    double dt = 1e-6 * double(t2.tv_usec) + double(t2.tv_sec);
+	    if (std::strlen(s)) {
+		++n;
+		if (dt < min) min = dt;
+		if (dt > max) max = dt;
+		avg += dt;
+		bsz = std::strlen(s);
+	    } else {
+		if (!n) break;
+		// next block size
+		avg /= double(n);
+		avg *= 1e6; min *= 1e6; max *= 1e6;
+
+		std::cout << "block size " << std::setw(9) << bsz <<
+		    " avg " << std::setw(7) << avg << " us min " <<
+		    std::setw(7) << min << " us max " << std::setw(7) <<
+		    max << "us speed " << std::setw(9) <<
+		    (double(bsz) / double(1 << 20) / (1e-6 * avg)) <<
+		    " MB/s" << std::endl;
+		n = 0;
+		avg = 0.;
+		min = 1e42;
+		max = -1e42;
+	    }
+	}
+	int retVal = pipe->close();
+	    std::cout << "[PARENT]: child exited with code " << retVal << std::endl;
+	if (retVal) return retVal;
+	delete pipe;
+	std::free(s);
+    }
+    return 0;
+}
+#endif // TEST_BIDIRMMAPPIPE
+#endif // _WIN32
+
+// vim: ft=cpp:sw=4:tw=78
diff --git a/roofit/roofitcore/src/BidirMMapPipe.h b/roofit/roofitcore/src/BidirMMapPipe.h
new file mode 100644
index 0000000..8d3cda4
--- /dev/null
+++ b/roofit/roofitcore/src/BidirMMapPipe.h
@@ -0,0 +1,974 @@
+/** @file BidirMMapPipe.h
+ *
+ * header file for BidirMMapPipe, a class which forks off a child process and
+ * serves as communications channel between parent and child
+ *
+ * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+ * @date 2013-07-07
+ */
+
+#ifndef BIDIRMMAPPIPE_H
+#define BIDIRMMAPPIPE_H
+
+#include <list>
+#include <vector>
+#include <cassert>
+
+#define BEGIN_NAMESPACE_ROOFIT namespace RooFit {
+#define END_NAMESPACE_ROOFIT }
+
+BEGIN_NAMESPACE_ROOFIT
+
+/// namespace for implementation details of BidirMMapPipe
+namespace BidirMMapPipe_impl {
+    // forward declarations
+    class BidirMMapPipeException;
+    class Page;
+    class PagePool;
+    class Pages;
+
+    /** @brief class representing a chunk of pages
+     *
+     * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+     * @date 2013-07-24
+     *
+     * allocating pages from the OS happens in chunks in order to not exhaust
+     * the maximum allowed number of memory mappings per process; this class
+     * takes care of such a chunk
+     *
+     * a page chunk allows callers to obtain or release pages in groups of
+     * continuous pages of fixed size
+     */
+    class PageChunk {
+	public:
+	    /// type of mmap support found
+	    typedef enum {
+		Unknown,	///< don't know yet what'll work
+		Copy,		///< mmap doesn't work, have to copy back and forth
+		FileBacked,	///< mmapping a temp file works
+		DevZero,	///< mmapping /dev/zero works
+		Anonymous	///< anonymous mmap works
+	    } MMapVariety;
+
+	private:
+	    static unsigned s_pagesize; ///< system page size (run-time determined)
+	    /// mmap variety that works on this system
+	    static MMapVariety s_mmapworks;
+	
+	    /// convenience typedef
+	    typedef BidirMMapPipeException Exception;
+
+	    void* m_begin;	///< pointer to start of mmapped area
+	    void* m_end;	///< pointer one behind end of mmapped area
+	    // FIXME: cannot keep freelist inline - other end may need that
+	    //        data, and we'd end up overwriting the page header
+	    std::list<void*> m_freelist; ///< free pages list
+	    PagePool* m_parent;	///< parent page pool
+	    unsigned m_nPgPerGrp; ///< number of pages per group
+	    unsigned m_nUsedGrp; ///< number of used page groups
+
+	    /// determine page size at run time
+	    static unsigned getPageSize();
+
+	    /// mmap pages, len is length of mmapped area in bytes
+	    static void* dommap(unsigned len);
+	    /// munmap pages p, len is length of mmapped area in bytes
+	    static void domunmap(void* p, unsigned len);
+	    /// forbid copying
+	    PageChunk(const PageChunk&) {}
+	    /// forbid assignment
+	    PageChunk& operator=(const PageChunk&) { return *this; }
+	public:
+	    /// return the page size of the system
+	    static unsigned pagesize() { return s_pagesize; }
+	    /// return mmap variety support found
+	    static MMapVariety mmapVariety() { return s_mmapworks; }
+
+	    /// constructor
+	    PageChunk(PagePool* parent, unsigned length, unsigned nPgPerGroup);
+
+	    /// destructor
+	    ~PageChunk();
+
+	    /// return if p is contained in this PageChunk
+	    bool contains(const Pages& p) const;
+
+	    /// pop a group of pages off the free list
+	    Pages pop();
+
+	    /// push a group of pages onto the free list
+	    void push(const Pages& p);
+
+	    /// return length of chunk
+	    unsigned len() const
+	    {
+		return reinterpret_cast<unsigned char*>(m_end) -
+		    reinterpret_cast<unsigned char*>(m_begin);
+	    }
+	    /// return number of pages per page group
+	    unsigned nPagesPerGroup() const { return m_nPgPerGrp; }
+
+	    /// return true if no used page groups in this chunk
+	    bool empty() const { return !m_nUsedGrp; }
+
+	    /// return true if no free page groups in this chunk
+	    bool full() const { return m_freelist.empty(); }
+
+	    /// free all pages except for those pointed to by p
+	    void zap(Pages& p);
+    };
+
+    /** @brief handle class for a number of Pages
+     *
+     * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+     * @date 2013-07-24
+     *
+     * the associated pages are continuous in memory
+     */
+    class Pages {
+	private:
+	    /// implementation
+	    typedef struct {
+		PageChunk *m_parent; ///< pointer to parent pool
+		Page* m_pages; ///< pointer to first page
+		unsigned m_refcnt; ///< reference counter
+		unsigned char m_npages; ///< length in pages
+	    } impl;
+	public:
+	    /// default constructor
+	    Pages() : m_pimpl(0) { }
+
+	    /// destructor
+	    ~Pages();
+
+	    /** @brief copy constructor
+	     *
+	     * copy Pages handle to new object - old object loses ownership,
+	     * and becomes a dangling handle
+	     */
+	    Pages(const Pages& other);
+
+	    /** @brief assignment operator
+	     *
+	     * assign Pages handle to new object - old object loses ownership,
+	     * and becomes a dangling handle
+	     */
+	    Pages& operator=(const Pages& other);
+
+	    /// return page size
+	    static unsigned pagesize();
+
+	    /// return number of pages accessible
+	    unsigned npages() const { return m_pimpl->m_npages; }
+
+	    /// return page number pageno
+	    Page* page(unsigned pgno) const;
+
+	    /// return page number pageno
+	    Page* operator[](unsigned pgno) const { return page(pgno); }
+
+	    /// perform page to page number mapping
+	    unsigned pageno(Page* p) const;
+
+	    /// perform page to page number mapping
+	    unsigned operator[](Page* p) const { return pageno(p); }
+
+	    /// swap with other's contents
+	    void swap(Pages& other)
+	    {
+		impl* tmp = other.m_pimpl;
+		other.m_pimpl = m_pimpl;
+		m_pimpl = tmp;
+	    }
+
+	private:
+	    /// page pool is our friend - it's allowed to construct Pages
+	    friend class BidirMMapPipe_impl::PageChunk;
+
+	    /// pointer to implementation
+	    impl* m_pimpl;
+
+	    /// constructor
+	    Pages(PageChunk* parent, Page* pages, unsigned npg);
+    };
+}
+
+/** @brief BidirMMapPipe creates a bidirectional channel between the current
+ * process and a child it forks.
+ *
+ * @author Manuel Schiller <manuel.schiller at nikhef.nl>
+ * @date 2013-07-07
+ *
+ * This class creates a bidirectional channel between this process and a child
+ * it creates with fork().
+ *
+ * The channel is comrised of a small shared pool of buffer memory mmapped into
+ * both process spaces, and two pipes to synchronise the exchange of data. The
+ * idea behind using the pipes at all is to have some primitive which we can
+ * block on without having to worry about atomic operations or polling, leaving
+ * these tasks to the OS. In case the anonymous mmap cannot be performed on the
+ * OS the code is running on (for whatever reason), the code falls back to
+ * mmapping /dev/zero, mmapping a temporary file, or (if those all fail), a
+ * dynamically allocated buffer which is then transmitted through the pipe(s),
+ * a slightly slower alternative (because the data is copied more often).
+ *
+ * The channel supports five major operations: read(), write(), flush(),
+ * purge() and close(). Reading and writing may block until the required buffer
+ * space is available. Writes may queue up data to be sent to the other end
+ * until either enough pages are full, or the user calls flush which forces
+ * any unsent buffers to be sent to the other end. flush forces any data that
+ * is to be sent to be sent. purge discards any buffered data waiting to be
+ * read and/or sent. Closing the channel on the child returns zero, closing it
+ * on the parent returns the child's exit status.
+ *
+ * The class also provides operator<< and operator>> for C++-style I/O for
+ * basic data types (bool, char, short, int, long, long long, float, double
+ * and their unsigned counterparts). Data is transmitted binary (i.e. no
+ * formatting to strings like std::cout does). There are also overloads to
+ * support C-style zero terminated strings and std::string. In terms of
+ * performance, the former is to be preferred.
+ *
+ * If the caller needs to multiplex input and output to/from several pipes, the
+ * class provides the poll() method which allows to block until an event occurs
+ * on any of the polled pipes.
+ *
+ * After the BidirMMapPipe is closed, no further operations may be performed on
+ * that object, save for the destructor which may still be called.
+ *
+ * If the BidirMMapPipe has not properly been closed, the destructor will call
+ * close. However, the exit code of the child is lost in that case.
+ *
+ * Closing the object causes the mmapped memory to be unmapped and the two
+ * pipes to be closed. We also install an atexit handler in the process of
+ * creating BidirMMapPipes. This ensures that when the current process
+ * terminates, a SIGTERM signal is sent to the child processes created for all
+ * unclosed pipes to avoid leaving zombie processes in the OS's process table.
+ *
+ * BidirMMapPipe creation, closing and destruction are thread safe. If the
+ * BidirMMapPipe is used in more than one thread, the other operations have to
+ * be protected with a mutex (or something similar), though.
+ *
+ * End of file (other end closed its pipe, or died) is indicated with the eof()
+ * method, serious I/O errors set a flags (bad(), fail()), and also throw
+ * exceptions. For normal read/write operations, they can be suppressed (i.e.
+ * error reporting only using flags) with a constructor argument.
+ *
+ * Technicalities:
+ * - there is a pool of mmapped pages, half the pages are allocated to the
+ *   parent process, half to the child 
+ * - when one side has accumulated enough data (or a flush forces dirty pages
+ *   out to the other end), it sends these pages to the other end by writing a
+ *   byte containing the page number into the pipe
+ * - the other end (which has the pages mmapped, too) reads the page number(s)
+ *   and puts the corresponding pages on its busy list
+ * - as the other ends reads, it frees busy pages, and eventually tries to put
+ *   them on the its list; if a page belongs to the other end of the
+ *   connection, it is sent back
+ * - lists of pages are sent across the pipe, not individual pages, in order
+ *   to minimise the number of read/write operations needed
+ * - when mmap works properly, only one bytes containing the page number of
+ *   the page list head is sent back and forth; the contents of that page
+ *   allow to access the rest of the page list sent, and page headers on the
+ *   list tell the receiving end if the page is free or has to be added to the
+ *   busy list
+ * - when mmap does not work, we transfer one byte to indicate the head of the
+ *   page list sent, and for each page on the list of sent pages, the page
+ *   header and the page payload is sent (if the page is free, we only
+ *   transmit the page header, and we never transmit more payload than
+ *   the page actually contains)
+ * - in the child, all open BidirMMapPipes but the current one are closed. this
+ *   is done for two reasons: first, to conserve file descriptors and address
+ *   space. second, if more than one process is meant to use such a
+ *   BidirMMapPipe, synchronisation issues arise which can lead to bugs that
+ *   are hard to find and understand. it's much better to come up with a design
+ *   which does not need pipes to be shared among more than two processes.
+ *
+ * Here is a trivial example of a parent and a child talking to each other over
+ * a BidirMMapPipe:
+ * @code
+ * #include <string>
+ * #include <iostream>
+ * #include <cstdlib>
+ *
+ * #include "BidirMMapPipe.h"
+ *
+ * int simplechild(BidirMMapPipe& pipe)
+ * {
+ *     // child does an echo loop
+ *     while (pipe.good() && !pipe.eof()) {
+ *         // read a string
+ *  	   std::string str;
+ *  	   pipe >> str;
+ *  	   if (!pipe) return -1;
+ *  	   if (pipe.eof()) break;
+ *  	   // check if parent wants us to shut down
+ *  	   if (!str.empty()) {
+ *  	       std::cout << "[CHILD] :  read: " << str << std::endl;
+ *  	       str = "... early in the morning?";
+ *  	   }
+ *         pipe << str << BidirMMapPipe::flush;
+ *         if (str.empty()) break;
+ *  	   if (!pipe) return -1;
+ *  	   std::cout << "[CHILD] : wrote: " << str << std::endl;
+ *     }
+ *     // send shutdown request acknowledged
+ *     pipe << "" << BidirMMapPipe::flush;
+ *     
+ *     pipe.close();
+ *     return 0;
+ * }
+ *  
+ * BidirMMapPipe* spawnChild(int (*childexec)(BidirMMapPipe&))
+ * {
+ *     BidirMMapPipe *p = new BidirMMapPipe();
+ *     if (p->isChild()) {
+ *         int retVal = childexec(*p);
+ *         delete p;
+ *         std::exit(retVal);
+ *     }
+ *     return p;
+ * }
+ *  
+ * int main()
+ * {
+ *     std::cout << "[PARENT]: simple challenge-response test, one child:" <<
+ *             std::endl;
+ *     BidirMMapPipe* pipe = spawnChild(simplechild);
+ *     for (int i = 0; i < 5; ++i) {
+ *         std::string str("What shall we do with a drunken sailor...");
+ *         *pipe << str << BidirMMapPipe::flush;
+ *         if (!*pipe) return -1;
+ *         std::cout << "[PARENT]: wrote: " << str << std::endl;
+ *         *pipe >> str;
+ *         if (!*pipe) return -1;
+ *         std::cout << "[PARENT]:  read: " << str << std::endl;
+ *     }
+ *     // ask child to shut down
+ *     pipe << "" << BidirMMapPipe::flush;
+ *     // wait for it to see the shutdown request
+ *     std::string s;
+ *     pipe >> s;
+ *     std::cout << "[PARENT]: exit status of child: " << pipe->close() <<
+ *             std::endl;
+ *     delete pipe;
+ *     return 0;
+ * }
+ * @endcode
+ *
+ * When designing your own protocols to use over the pipe, there are a few
+ * things to bear in mind:
+ * - Do as http does: When building a request, send all the options and
+ *   properties of that request with the request itself in a single go (one
+ *   flush). Then, the server has everything it needs, and hopefully, it'll
+ *   shut up for a while and to let the client do something useful in the
+ *   meantime... The same goes when the server replies to the request: include
+ *   everything there is to know about the result of the request in the reply.
+ * - The expensive operation should be the request that is made, all other
+ *   operations should somehow be formulated as options or properties to that
+ *   request.
+ * - Include a shutdown handshake in whatever protocol you send over the
+ *   pipe. That way, you can shut things down in a controlled way. Otherwise,
+ *   and depending on your OS's scheduling quirks, you may catch a SIGPIPE if
+ *   one end closes its pipe while the other is still trying to read.
+ */
+class BidirMMapPipe {
+#ifndef _WIN32
+    public:
+	/// type used to represent sizes
+	typedef std::size_t size_type;
+	/// convenience typedef for BidirMMapPipeException
+	typedef BidirMMapPipe_impl::BidirMMapPipeException Exception;
+	/// flag bits for partial C++ iostream compatibility
+	enum {
+	    eofbit = 1, ///< end of file reached
+	    failbit = 2, ///< logical failure (e.g. pipe closed)
+	    rderrbit = 4, ///< read error
+	    wrerrbit = 8, ///< write error
+	    badbit = rderrbit | wrerrbit, ///< general I/O error
+	    exceptionsbit = 16 ///< error reporting with exceptions
+	};
+
+	/** @brief constructor (forks!)
+	 *
+	 * Creates a bidirectional communications channel between this process
+	 * and a child the constructor forks. On return from the constructor,
+	 * isParent() and isChild() can be used to tell the parent end from the
+	 * child end of the pipe. In the child, all other open BidirMMapPipes
+	 * are closed.
+	 *
+	 * @param useExceptions	read()/write() error reporting also done using
+	 * 			exceptions
+	 * @param useSocketpair use a socketpair instead of a pair or pipes
+	 *
+	 * Normally, exceptions are thrown for all serious I/O errors (apart
+	 * from end of file). Setting useExceptions to false will force the
+	 * read() and write() methods to only report serious I/O errors using
+	 * flags.
+	 *
+	 * When useSocketpair is true, use a pair of Unix domain sockets
+	 * created using socketpair instead a pair of pipes. The advantage is
+	 * that only one pair of file descriptors is needed instead of two
+	 * pairs which are needed for the pipe pair. Performance should very
+	 * similar on most platforms, especially if mmap works, since only
+	 * very little data is sent through the pipe(s)/socketpair.
+	 */
+	BidirMMapPipe(bool useExceptions = true, bool useSocketpair = false);
+
+	/** @brief destructor
+	 *
+	 * closes this end of pipe
+	 */
+	~BidirMMapPipe();
+
+	/** @brief read from pipe
+	 *
+	 * @param addr	where to put read data
+	 * @param sz	size of data to read (in bytes)
+	 * @returns	size of data read, or 0 in case of end-of-file
+	 *
+	 * read may block until data from other end is available. It will
+	 * return 0 if the other end closed the pipe.
+	 */
+	size_type read(void* addr, size_type sz);
+
+	/** @brief wirte to pipe
+	 *
+	 * @param addr	where to get data to write from
+	 * @param sz	size of data to write (in bytes)
+	 * @returns	size of data written, or 0 in case of end-of-file
+	 *
+	 * write may block until data can be written to other end (depends a
+	 * bit on available buffer space). It will return 0 if the other end
+	 * closed the pipe. The data is queued to be written on the next
+	 * convenient occasion, or it can be forced out with flush().
+	 */
+	size_type write(const void* addr, size_type sz);
+
+	/** @brief flush buffers with unwritten data
+	 *
+	 * This forces unwritten data to be written to the other end. The call
+	 * will block until this has been done (or the attempt failed with an
+	 * error).
+	 */
+	void flush();
+
+	/** @brief purge buffered data waiting to be read and/or written
+	 *
+	 * Discards all internal buffers.
+	 */
+	void purge();
+
+	/** @brief number of bytes that can be read without blocking
+	 *
+	 * @returns number of bytes that can be read without blocking
+	 */
+	size_type bytesReadableNonBlocking();
+
+	/** @brief number of bytes that can be written without blocking
+	 *
+	 * @returns number of bytes that can be written without blocking
+	 */
+	size_type bytesWritableNonBlocking();
+
+	/** @brief flush buffers, close pipe
+	 *
+	 * Flush buffers, discard unread data, closes the pipe. If the pipe is
+	 * in the parent process, it waits for the child.
+	 *
+	 * @returns exit code of child process in parent, zero in child
+	 */
+	int close();
+
+	/** @brief return PID of the process on the other end of the pipe
+	 *
+	 * @returns PID of the process running on the remote end
+	 */
+	pid_t pidOtherEnd() const
+	{ return isChild() ? m_parentPid : m_childPid; }
+
+	/// condition flags for poll
+	enum PollFlags {
+	    None = 0,		///< nothing special on this pipe
+	    Readable = 1,	///< pipe has data for reading
+	    Writable = 2,	///< pipe can be written to
+	    ReadError = 4,	///< pipe error read end
+	    WriteError = 8,	///< pipe error Write end
+	    Error = ReadError | WriteError, ///< pipe error
+	    ReadEndOfFile = 32,	///< read pipe in end-of-file state
+	    WriteEndOfFile = 64,///< write pipe in end-of-file state
+	    EndOfFile = ReadEndOfFile | WriteEndOfFile, ///< end of file
+	    ReadInvalid = 64,	///< read end of pipe invalid
+	    WriteInvalid = 128,	///< write end of pipe invalid
+	    Invalid = ReadInvalid | WriteInvalid ///< invalid pipe
+	};
+
+	/// for poll() interface
+	class PollEntry {
+	    public:
+		BidirMMapPipe* pipe;	///< pipe of interest
+		unsigned events;	///< events of interest (or'ed bitmask)
+		unsigned revents;	///< events that happened (or'ed bitmask)
+		/// poll a pipe for all events
+		PollEntry(BidirMMapPipe* _pipe) :
+		    pipe(_pipe), events(None), revents(None) { }
+		/// poll a pipe for specified events
+		PollEntry(BidirMMapPipe* _pipe, int _events) :
+		    pipe(_pipe), events(_events), revents(None) { }
+	};
+	/// convenience typedef for poll() interface
+	typedef std::vector<PollEntry> PollVector;
+
+	/** @brief poll a set of pipes for events (ready to read from, ready to
+	 * write to, error)
+	 *
+	 * @param pipes		set of pipes to check
+	 * @param timeout	timeout in milliseconds
+	 * @returns		positive number: number of pipes which have
+	 * 			status changes, 0: timeout, or no pipes with
+	 * 			status changed, -1 on error
+	 *
+	 * Timeout can be zero (check for specified events, and return), finite
+	 * (wait at most timeout milliseconds before returning), or -1
+	 * (infinite). The poll method returns when the timeout has elapsed,
+	 * or if an event occurs on one of the pipes being polled, whichever
+	 * happens earlier.
+	 *
+	 * Pipes is a vector of one or more PollEntries, which each list a pipe
+	 * and events to poll for. If events is left empty (zero), all
+	 * conditions are polled for, otherwise only the indicated ones. On
+	 * return, the revents fields contain the events that occurred for each
+	 * pipe; error Error, EndOfFile or Invalid events are always set,
+	 * regardless of wether they were in the set of requested events.
+	 *
+	 * poll may block slightly longer than specified by timeout due to OS
+	 * timer granularity and OS scheduling. Due to its implementation, the
+	 * poll call can also return early if the remote end of the page sends
+	 * a free page while polling (which is put on that pipe's freelist),
+	 * while that pipe is polled for e.g Reading. The status of the pipe is
+	 * indicated correctly in revents, and the caller can simply poll
+	 * again. (The reason this is done this way is because it helps to
+	 * replenish the pool of free pages and queue busy pages without
+	 * blocking.)
+	 *
+	 * Here's a piece of example code waiting on two pipes; if they become
+	 * readable they are read:
+	 * @code
+	 * #include <unistd.h>
+	 * #include <cstdlib>
+	 * #include <string>
+	 * #include <sstream>
+	 * #include <iostream>
+	 *
+	 * #include "BidirMMapPipe.h"
+	 *
+	 * // what to execute in the child
+         * int randomchild(BidirMMapPipe& pipe)
+         * {
+         *     ::srand48(::getpid());
+         *     for (int i = 0; i < 5; ++i) {
+         *         // sleep a random time between 0 and .9 seconds
+         *        ::usleep(int(1e6 * ::drand48()));
+         *        std::ostringstream buf;
+         *        buf << "child pid " << ::getpid() << " sends message " << i;
+         *        std::cout << "[CHILD] : " << buf.str() << std::endl;
+         *        pipe << buf.str() << BidirMMapPipe::flush;
+         *        if (!pipe) return -1;
+         *        if (pipe.eof()) break;
+         *     }
+	 *     // tell parent we're done
+	 *     pipe << "" << BidirMMapPipe::flush;
+	 *     // wait for parent to acknowledge
+	 *     std::string s;
+	 *     pipe >> s;
+         *     pipe.close();
+         *     return 0;
+         * }
+         * 
+	 * // function to spawn a child
+         * BidirMMapPipe* spawnChild(int (*childexec)(BidirMMapPipe&))
+         * {
+         *     BidirMMapPipe *p = new BidirMMapPipe();
+         *     if (p->isChild()) {
+         *         int retVal = childexec(*p);
+         *         delete p;
+         *         std::exit(retVal);
+         *     }
+         *     return p;
+         * }
+         * 
+         * int main()
+         * {
+         *     typedef BidirMMapPipe::PollEntry PollEntry;
+         *     // poll data structure
+         *     BidirMMapPipe::PollVector pipes;
+	 *     pipes.reserve(3);
+         *     // spawn children
+         *     for (int i = 0; i < 3; ++i) {
+         *         pipes.push_back(PollEntry(spawnChild(randomchild),
+         *     		BidirMMapPipe::Readable));
+         *     }
+         *     // while at least some children alive
+         *     while (!pipes.empty()) {
+         *         // poll, wait until status change (infinite timeout)
+         *         int npipes = BidirMMapPipe::poll(pipes, -1);
+         *         // scan for pipes with changed status
+         *         for (std::vector<PollEntry>::iterator it = pipes.begin();
+         *     	           npipes && pipes.end() != it; ) {
+         *             if (!it->revents) {
+         *                 // unchanged, next one
+         *                 ++it;
+         *                 continue;
+         *             }
+         *             --npipes; // maybe we can stop early...
+         *             // read from pipes which are readable
+         *             if (it->revents & BidirMMapPipe::Readable) {
+         *                 std::string s;
+         *                 *(it->pipe) >> s;
+	 *                 if (!s.empty()) {
+         *                 std::cout << "[PARENT]: Read from pipe " <<
+	 *                     it->pipe << ": " << s << std::endl;
+         *                 ++it;
+         *                 continue;
+	 *                 } else {
+         *                     // child is shutting down...
+	 *                     *(it->pipe) << "" << BidirMMapPipe::flush;
+	 *                     goto childcloses;
+         *                 }
+         *             }
+         *             // retire pipes with error or end-of-file condition
+         *             if (it->revents & (BidirMMapPipe::Error |
+         *             	       BidirMMapPipe::EndOfFile |
+	 *             	       BidirMMapPipe::Invalid)) {
+         *                 std::cout << "[PARENT]: Error on pipe " <<
+         *                     it->pipe << " revents " << it->revents <<
+	 *                     std::endl;
+	 * childcloses:
+         *                 std::cout << "[PARENT]:\tchild exit status: " <<
+         *             	       it->pipe->close() << std::endl;
+	 *             	   if (retVal) return retVal;
+         *                 delete it->pipe;
+         *                 it = pipes.erase(it);
+         *                 continue;
+         *             }
+         *         }
+         *     }
+         *     return 0;
+         * }
+	 * @endcode
+	 */
+	static int poll(PollVector& pipes, int timeout);
+
+        /** @brief return if this end of the pipe is the parent end
+	 *
+	 * @returns true if parent end of pipe
+	 */
+	bool isParent() const { return m_childPid; }
+
+        /** @brief return if this end of the pipe is the child end
+	 *
+	 * @returns true if child end of pipe
+	 */
+	bool isChild() const { return !m_childPid; }
+
+	/** @brief if BidirMMapPipe uses a socketpair for communications
+	 *
+	 * @returns true if BidirMMapPipe uses a socketpair for communications
+	 */
+	bool usesSocketpair() const { return m_inpipe == m_outpipe; }
+
+	/** @brief if BidirMMapPipe uses a pipe pair for communications
+	 *
+	 * @returns true if BidirMMapPipe uses a pipe pair for communications
+	 */
+	bool usesPipepair() const { return m_inpipe != m_outpipe; }
+
+	/** @brief return flags (end of file, BidirMMapPipe closed, ...)
+	 *
+	 * @returns flags (end of file, BidirMMapPipe closed, ...)
+	 */
+	int rdstate() const { return m_flags; }
+
+	/** @brief true if end-of-file
+	 *
+	 * @returns true if end-of-file
+	 */
+	bool eof() const { return m_flags & eofbit; }
+
+	/** @brief logical failure (e.g. I/O on closed BidirMMapPipe)
+	 *
+	 * @returns true in case of grave logical error (I/O on closed pipe,...)
+	 */
+	bool fail() const { return m_flags & failbit; }
+
+	/** @brief true on I/O error
+	 *
+	 * @returns true on I/O error
+	 */
+	bool bad() const { return m_flags & badbit; }
+
+	/** @brief status of stream is good
+	 *
+	 * @returns true if pipe is good (no errors, eof, ...)
+	 */
+	bool good() const { return !(m_flags & (eofbit | failbit | badbit)); }
+
+	/** @brief true if closed
+	 *
+	 * @returns true if stream is closed
+	 */
+	bool closed() const { return m_flags & failbit; }
+
+	/** @brief return true if not serious error (fail/bad)
+	 *
+	 * @returns true if stream is does not have serious error (fail/bad)
+	 *
+	 * (if EOF, this is still true)
+	 */
+	operator bool() const { return !fail() && !bad(); }
+
+	/** @brief return true if serious error (fail/bad)
+	 *
+	 * @returns true if stream has a serious error (fail/bad)
+	 */
+	bool operator!() const { return fail() || bad(); }
+
+#ifdef STREAMOP
+#undef STREAMOP
+#endif
+#define STREAMOP(TYPE) \
+	BidirMMapPipe& operator<<(const TYPE& val) \
+	{ write(&val, sizeof(TYPE)); return *this; } \
+	BidirMMapPipe& operator>>(TYPE& val) \
+	{ read(&val, sizeof(TYPE)); return *this; }
+	STREAMOP(bool); ///< C++ style stream operators for bool
+	STREAMOP(char); ///< C++ style stream operators for char
+	STREAMOP(short); ///< C++ style stream operators for short
+	STREAMOP(int); ///< C++ style stream operators for int
+	STREAMOP(long); ///< C++ style stream operators for long
+	STREAMOP(long long); ///< C++ style stream operators for long long 
+	STREAMOP(unsigned char); ///< C++ style stream operators for unsigned char
+	STREAMOP(unsigned short); ///< C++ style stream operators for unsigned short
+	STREAMOP(unsigned int); ///< C++ style stream operators for unsigned int
+	STREAMOP(unsigned long); ///< C++ style stream operators for unsigned long
+	STREAMOP(unsigned long long); ///< C++ style stream operators for unsigned long long
+	STREAMOP(float); ///< C++ style stream operators for float
+	STREAMOP(double); ///< C++ style stream operators for double
+#undef STREAMOP
+
+	/** @brief write a C-style string
+	 *
+	 * @param str C-style string
+	 * @returns pipe written to
+	 */
+	BidirMMapPipe& operator<<(const char* str);
+
+	/** @brief read a C-style string
+	 *
+	 * @param str pointer to string (space allocated with malloc!)
+	 * @returns pipe read from
+	 *
+	 * since this is for C-style strings, we use malloc/realloc/free for
+	 * strings. passing in a NULL pointer is valid here, and the routine
+	 * will use realloc to allocate a chunk of memory of the right size.
+	 */
+	BidirMMapPipe& operator>>(char* (&str));
+
+	/** @brief write a std::string object
+	 *
+	 * @param str string to write
+	 * @returns pipe written to
+	 */
+	BidirMMapPipe& operator<<(const std::string& str);
+
+	/** @brief read a std::string object
+	 *
+	 * @param str string to be read
+	 * @returns pipe read from
+	 */
+	BidirMMapPipe& operator>>(std::string& str);
+
+	/** @brief write raw pointer to T to other side
+	 *
+	 * NOTE: This will not write the pointee! Only the value of the
+	 * pointer is transferred.
+	 *
+	 * @param tptr pointer to be written
+	 * @returns pipe written to
+	 */
+	template<class T> BidirMMapPipe& operator<<(const T* tptr)
+	{ write(&tptr, sizeof(tptr)); return *this; }
+
+	/** @brief read raw pointer to T from other side
+	 *
+	 * NOTE: This will not read the pointee! Only the value of the
+	 * pointer is transferred.
+	 *
+	 * @param tptr pointer to be read
+	 * @returns pipe read from
+	 */
+	template<class T> BidirMMapPipe& operator>>(T* &tptr)
+	{ read(&tptr, sizeof(tptr)); return *this; }
+
+	/** @brief I/O manipulator support
+	 *
+	 * @param f manipulator
+	 * @returns pipe with manipulator applied
+	 *
+	 * example:
+	 * @code
+	 * pipe << BidirMMapPipe::flush;
+	 * @endcode
+	 */
+	BidirMMapPipe& operator<<(BidirMMapPipe& (*manip)(BidirMMapPipe&))
+	{ return manip(*this); }
+
+	/** @brief I/O manipulator support
+	 *
+	 * @param f manipulator
+	 * @returns pipe with manipulator applied
+	 *
+	 * example:
+	 * @code
+	 * pipe >> BidirMMapPipe::purge;
+	 * @endcode
+	 */
+	BidirMMapPipe& operator>>(BidirMMapPipe& (*manip)(BidirMMapPipe&))
+	{ return manip(*this); }
+
+	/// for usage a la "pipe << flush;"
+	static BidirMMapPipe& flush(BidirMMapPipe& pipe) { pipe.flush(); return pipe; }
+	/// for usage a la "pipe << purge;"
+	static BidirMMapPipe& purge(BidirMMapPipe& pipe) { pipe.purge(); return pipe; }
+
+    private:
+	/// copy-construction forbidden
+	BidirMMapPipe(const BidirMMapPipe&);
+	/// assignment forbidden
+	BidirMMapPipe& operator=(const BidirMMapPipe&) { return *this; }
+
+	/// page is our friend
+	friend class BidirMMapPipe_impl::Page;
+	/// convenience typedef for Page
+	typedef BidirMMapPipe_impl::Page Page;
+	
+	/// tuning constants
+	enum {
+	    // TotPages = 16 will give 32k buffers at 4k page size for both
+	    // parent and child; if your average message to send is larger
+	    // than this, consider raising the value (max 256)
+	    TotPages = 16, ///< pages shared (child + parent)
+
+	    PagesPerEnd = TotPages / 2, ///< pages per pipe end
+
+	    // if FlushThresh pages are filled, the code forces a flush; 3/4
+	    // of the pages available seems to work quite well
+	    FlushThresh = (3 * PagesPerEnd) / 4 ///< flush threshold
+	};
+
+	// per-class members
+	static pthread_mutex_t s_openpipesmutex; ///< protects s_openpipes
+	/// list of open BidirMMapPipes
+	static std::list<BidirMMapPipe*> s_openpipes;
+	/// pool of mmapped pages
+	static BidirMMapPipe_impl::PagePool* s_pagepool;
+	/// page pool reference counter
+	static unsigned s_pagepoolrefcnt;
+
+	/// return page pool
+	static BidirMMapPipe_impl::PagePool& pagepool();
+
+	// per-instance members
+	BidirMMapPipe_impl::Pages m_pages; ///< mmapped pages
+	Page* m_busylist; ///< linked list: busy pages (data to be read)
+	Page* m_freelist; ///< linked list: free pages
+	Page* m_dirtylist; ///< linked list: dirty pages (data to be sent)
+	int m_inpipe; ///< pipe end from which data may be read
+	int m_outpipe; ///< pipe end to which data may be written
+	int m_flags; ///< flags (e.g. end of file)
+	pid_t m_childPid; ///< pid of the child (zero if we're child)
+	pid_t m_parentPid; ///< pid of the parent
+
+	/// cleanup routine - at exit, we want our children to get a SIGTERM...
+	static void teardownall(void);
+
+	/// return length of a page list
+	static unsigned lenPageList(const Page* list);
+
+	/** "feed" the busy and free lists with a list of pages
+	 *
+	 * @param plist linked list of pages
+	 *
+	 * goes through plist, puts free pages from plist onto the freelist
+	 * (or sends them to the remote end if they belong there), and puts
+	 * non-empty pages on plist onto the busy list
+	 */
+	void feedPageLists(Page* plist);
+
+	/// put on dirty pages list
+	void markPageDirty(Page* p);
+
+	/// transfer bytes through the pipe (reading, writing, may block)
+	static size_type xferraw(int fd, void* addr, size_type len,
+		ssize_t (*xferfn)(int, void*, std::size_t));
+	/// transfer bytes through the pipe (reading, writing, may block)
+	static size_type xferraw(int fd, void* addr, const size_type len,
+		ssize_t (*xferfn)(int, const void*, std::size_t))
+	{
+	    return xferraw(fd, addr, len,
+		    reinterpret_cast<ssize_t (*)(
+			int, void*, std::size_t)>(xferfn));
+	}
+
+	/** @brief send page(s) to the other end (may block)
+	 *
+	 * @param plist linked list of pages to send
+	 *
+	 * the implementation gathers the different write(s) whereever
+	 * possible; if mmap works, this results in a single write to transfer
+	 * the list of pages sent, if we need to copy things through the pipe,
+	 * we have one write to transfer which pages are sent, and then one
+	 * write per page.
+	 */
+	void sendpages(Page* plist);
+
+	/** @brief receive a pages from the other end (may block), queue them
+	 *
+	 * @returns number of pages received
+	 *
+	 * this is an application-level scatter read, which gets the list of
+	 * pages to read from the pipe. if mmap works, it needs only one read
+	 * call (to get the head of the list of pages transferred). if we need
+	 * to copy pages through the pipe, we need to add one read for each
+	 * empty page, and two reads for each non-empty page.
+	 */
+	unsigned recvpages();
+
+	/** @brief receive pages from other end (non-blocking)
+	 *
+	 * @returns number of pages received
+	 *
+	 * like recvpages(), but does not block if nothing is available for
+	 * reading
+	 */
+	unsigned recvpages_nonblock();
+
+	/// get a busy page to read data from (may block)
+	Page* busypage();
+	/// get a dirty page to write data to (may block)
+	Page* dirtypage();
+
+	/// close the pipe (no flush if forced)
+	int doClose(bool force, bool holdlock = false);
+	/// perform the flush
+	void doFlush(bool forcePartialPages = true);
+#endif //_WIN32
+};
+
+END_NAMESPACE_ROOFIT
+
+#undef BEGIN_NAMESPACE_ROOFIT
+#undef END_NAMESPACE_ROOFIT
+
+#endif // BIDIRMMAPPIPE_H
+
+// vim: ft=cpp:sw=4:tw=78
diff --git a/roofit/roofitcore/src/RooAbsArg.cxx b/roofit/roofitcore/src/RooAbsArg.cxx
index 439396b..e777bc9 100644
--- a/roofit/roofitcore/src/RooAbsArg.cxx
+++ b/roofit/roofitcore/src/RooAbsArg.cxx
@@ -1875,52 +1875,124 @@ TString RooAbsArg::cleanBranchName() const
 UInt_t RooAbsArg::crc32(const char* data)
 {
   // Calculate crc32 checksum on given string
-
-  // Calculate and extract length of string
-  Int_t len = strlen(data) ;
-  if (len<4) {
-    oocoutE((RooAbsArg*)0,InputArguments) << "RooAbsReal::crc32 cannot calculate checksum of less than 4 bytes of data" << endl ;
-    return 0 ;
-  }
-
-  // Initialize CRC table on first use
-  static Bool_t init(kFALSE) ;
-  static unsigned int crctab[256];
-  if (!init) {
-    int i, j;
-    unsigned int crc;
-    for (i = 0; i < 256; i++){
-      crc = i << 24;
-      for (j = 0; j < 8; j++) {
-	if (crc & 0x80000000) {
-	  crc = (crc << 1) ^ 0x04c11db7 ;
-	} else {
-	  crc = crc << 1;
-	}
-      }
-      crctab[i] = crc;
-    }
-    init = kTRUE ;
-  }
-
-  unsigned int        result(0);
-  int                 i(0);
-
-  result = *data++ << 24;
-  result |= *data++ << 16;
-  result |= *data++ << 8;
-  result |= *data++;
-  result = ~ result;
-  len -=4;
-
-  for (i=0; i<len; i++) {
-    result = (result << 8 | *data++) ^ crctab[result >> 24];
-  }
-
-  return ~result;
+  unsigned long sz = strlen(data);
+  switch (strlen(data)) {
+    case 0:
+      return 0;
+    case 1:
+      return data[0];
+    case 2:
+      return (data[0] << 8) | data[1];
+    case 3:
+      return (data[0] << 16) | (data[1] << 8) | data[2];
+    case 4:
+      return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+    default:
+      return crc32(data + 4, sz - 4, (data[0] << 24) | (data[1] << 16) |
+	  (data[2] << 8) | data[3]);
+  }
+}
+
+
+UInt_t RooAbsArg::crc32(const char* data, ULong_t sz, UInt_t crc)
+{
+  // update CRC32 with new data
+
+  // use precomputed table, rather than computing it on the fly
+  static const UInt_t crctab[256] = { 0x00000000,
+    0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+    0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
+    0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+    0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
+    0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
+    0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
+    0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+    0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
+    0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+    0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
+    0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+    0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
+    0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+    0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
+    0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+    0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
+    0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
+    0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
+    0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+    0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
+    0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+    0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
+    0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+    0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
+    0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+    0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
+    0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+    0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
+    0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
+    0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
+    0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+    0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
+    0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+    0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
+    0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+    0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
+    0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+    0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
+    0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+    0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
+    0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
+    0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
+    0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+    0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
+    0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+    0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
+    0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+    0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
+    0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+    0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
+    0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+  };
+
+  crc = ~crc;
+  while (sz--) crc = (crc << 8) ^ UInt_t(*data++) ^ crctab[crc >> 24];
+
+  return ~crc;
+}
+
+UInt_t RooAbsArg::fnv1a32(const char* data)
+{
+  // calculate 32 bit FNV1A hash of string
+  return fnv1a32(data, strlen(data));
+}
+
+UInt_t RooAbsArg::fnv1a32(const char* data, ULong_t sz, UInt_t hash)
+{
+  // update 32 bit FNV1A hash
+  const UInt_t fnv1a32mult = 16777619u;
+  while (sz--) {
+    hash ^= *data++;
+    hash *= fnv1a32mult;
+  }
+  return hash;
+}
+
+ULong64_t RooAbsArg::fnv1a64(const char* data)
+{
+  // calculate 64 bit FNV1A hash of string
+  return fnv1a64(data, strlen(data));
+}
+
+ULong64_t RooAbsArg::fnv1a64(const char* data, ULong_t sz, ULong64_t hash)
+{
+  // update 64 bit FNV1A hash
+  const ULong64_t fnv1a64mult = (ULong64_t(1) << 40) | ULong64_t(435);
+  while (sz--) {
+    hash ^= *data++;
+    hash *= fnv1a64mult;
+  }
+  return hash;
 }
 
-
 //_____________________________________________________________________________
 void RooAbsArg::printCompactTreeHook(ostream&, const char *)
 {
diff --git a/roofit/roofitcore/src/RooAbsData.cxx b/roofit/roofitcore/src/RooAbsData.cxx
index af8a193..9781622 100644
--- a/roofit/roofitcore/src/RooAbsData.cxx
+++ b/roofit/roofitcore/src/RooAbsData.cxx
@@ -1628,19 +1628,23 @@ TList* RooAbsData::split(const RooAbsCategory& splitCat, Bool_t createEmptyDataS
 
   
   // Loop over dataset and copy event to matching subset
-  Int_t i ;
-  for (i=0 ; i<numEntries() ; i++) {
-    const RooArgSet* row =  get(i) ;
-    RooAbsData* subset = (RooAbsData*) dsetList->FindObject(cloneCat->getLabel()) ;
+  const bool propWeightSquared = isWeighted();
+  for (Int_t i = 0; i < numEntries(); ++i) {
+    const RooArgSet* row =  get(i);
+    RooAbsData* subset = (RooAbsData*) dsetList->FindObject(cloneCat->getLabel());
     if (!subset) {
-      subset = emptyClone(cloneCat->getLabel(),cloneCat->getLabel(),&subsetVars,(addWV?"weight":0)) ;
-      dsetList->Add((RooAbsArg*)subset) ;
+      subset = emptyClone(cloneCat->getLabel(),cloneCat->getLabel(),&subsetVars,(addWV?"weight":0));
+      dsetList->Add((RooAbsArg*)subset);
+    }
+    if (!propWeightSquared) {
+	subset->add(*row, weight());
+    } else {
+	subset->add(*row, weight(), weightSquared());
     }
-    subset->add(*row,weight()) ;
   }
 
-  delete cloneSet ;
-  return dsetList ;
+  delete cloneSet;
+  return dsetList;
 }
 
 
diff --git a/roofit/roofitcore/src/RooAbsOptTestStatistic.cxx b/roofit/roofitcore/src/RooAbsOptTestStatistic.cxx
index 183c983..adf2282 100644
--- a/roofit/roofitcore/src/RooAbsOptTestStatistic.cxx
+++ b/roofit/roofitcore/src/RooAbsOptTestStatistic.cxx
@@ -449,13 +449,16 @@ Double_t RooAbsOptTestStatistic::combinedValue(RooAbsReal** array, Int_t n) cons
   // values
   
   // Default implementation returns sum of components
-  Double_t sum(0) ;
-  Int_t i ;
-  for (i=0 ; i<n ; i++) {
-    Double_t tmp = array[i]->getValV() ;
-    // if (tmp==0) return 0 ; WVE no longer needed
-    sum += tmp ;
+  Double_t sum(0), carry(0);
+  for (Int_t i = 0; i < n; ++i) {
+    Double_t y = array[i]->getValV();
+    carry += reinterpret_cast<RooAbsOptTestStatistic*>(array[i])->getCarry();
+    y -= carry;
+    const Double_t t = sum + y;
+    carry = (t - sum) - y;
+    sum = t;
   }
+  _evalCarry = carry;
   return sum ;
 }
 
diff --git a/roofit/roofitcore/src/RooAbsPdf.cxx b/roofit/roofitcore/src/RooAbsPdf.cxx
index 2c4da57..5e6fdd7 100644
--- a/roofit/roofitcore/src/RooAbsPdf.cxx
+++ b/roofit/roofitcore/src/RooAbsPdf.cxx
@@ -152,6 +152,7 @@
 #include "RooChi2Var.h"
 #include "RooMinimizer.h"
 #include "RooRealIntegral.h"
+#include "Math/CholeskyDecomp.h"
 #include <string>
 
 using namespace std;
@@ -964,7 +965,7 @@ RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooCmdArg& arg1, const Ro
 {
   // Fit PDF to given dataset. If dataset is unbinned, an unbinned maximum likelihood is performed. If the dataset
   // is binned, a binned maximum likelihood is performed. By default the fit is executed through the MINUIT
-  // commands MIGRAD, HESSE and MINOS in succession.
+  // commands MIGRAD, HESSE in succession.
   //
   // The following named arguments are supported
   //
@@ -1021,7 +1022,7 @@ RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooCmdArg& arg1, const Ro
   // InitialHesse(Bool_t flag)      -- Flag controls if HESSE before MIGRAD as well, off by default
   // Optimize(Bool_t flag)          -- Activate constant term optimization of test statistic during minimization (on by default)
   // Hesse(Bool_t flag)             -- Flag controls if HESSE is run after MIGRAD, on by default
-  // Minos(Bool_t flag)             -- Flag controls if MINOS is run after HESSE, on by default
+  // Minos(Bool_t flag)             -- Flag controls if MINOS is run after HESSE, off by default
   // Minos(const RooArgSet& set)    -- Only run MINOS on given subset of arguments
   // Save(Bool_t flag)              -- Flac controls if RooFitResult object is produced and returned, off by default
   // Strategy(Int_t flag)           -- Set Minuit strategy (0 through 2, default is 1)
@@ -1223,73 +1224,51 @@ RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooLinkedList& cmdList)
       }
       
       if (doSumW2==1 && m.getNPar()>0) {
-	
 	// Make list of RooNLLVar components of FCN
-	list<RooNLLVar*> nllComponents ;
-	RooArgSet* comps = nll->getComponents() ;
-	RooAbsArg* arg ;
-	TIterator* citer = comps->createIterator() ;
-	while((arg=(RooAbsArg*)citer->Next())) {
-	  RooNLLVar* nllComp = dynamic_cast<RooNLLVar*>(arg) ;
-	  if (nllComp) {
-	    nllComponents.push_back(nllComp) ;
-	  }
+	RooArgSet* comps = nll->getComponents();
+	vector<RooNLLVar*> nllComponents;
+	nllComponents.reserve(comps->getSize());
+	TIterator* citer = comps->createIterator();
+	RooAbsArg* arg;
+	while ((arg=(RooAbsArg*)citer->Next())) {
+	  RooNLLVar* nllComp = dynamic_cast<RooNLLVar*>(arg);
+	  if (!nllComp) continue;
+	  nllComponents.push_back(nllComp);
 	}
-	delete citer ;
-	delete comps ;  
+	delete citer;
+	delete comps; 
 	
 	// Calculated corrected errors for weighted likelihood fits
-	RooFitResult* rw = m.save() ;
-	for (list<RooNLLVar*>::iterator iter1=nllComponents.begin() ; iter1!=nllComponents.end() ; iter1++) {
-	  (*iter1)->applyWeightSquared(kTRUE) ;
+	RooFitResult* rw = m.save();
+	for (vector<RooNLLVar*>::iterator it = nllComponents.begin(); nllComponents.end() != it; ++it) {
+	  (*it)->applyWeightSquared(kTRUE);
 	}
 	coutI(Fitting) << "RooAbsPdf::fitTo(" << GetName() << ") Calculating sum-of-weights-squared correction matrix for covariance matrix" << endl ;
-	m.hesse() ;
-	RooFitResult* rw2 = m.save() ;
-	for (list<RooNLLVar*>::iterator iter2=nllComponents.begin() ; iter2!=nllComponents.end() ; iter2++) {
-	  (*iter2)->applyWeightSquared(kFALSE) ;
+	m.hesse();
+	RooFitResult* rw2 = m.save();
+	for (vector<RooNLLVar*>::iterator it = nllComponents.begin(); nllComponents.end() != it; ++it) {
+	  (*it)->applyWeightSquared(kFALSE);
 	}
 	
 	// Apply correction matrix
-	const TMatrixDSym& V = rw->covarianceMatrix() ;
-	TMatrixDSym  C = rw2->covarianceMatrix() ;
-	
-	// Invert C
-	Double_t det(0) ;
-	C.Invert(&det) ;
-	if (det==0) {
+	const TMatrixDSym& matV = rw->covarianceMatrix();
+	TMatrixDSym matC = rw2->covarianceMatrix();
+	using ROOT::Math::CholeskyDecompGenDim;
+	CholeskyDecompGenDim<Double_t> decomp(matC.GetNrows(), matC);
+	if (!decomp) {
 	  coutE(Fitting) << "RooAbsPdf::fitTo(" << GetName() 
 			 << ") ERROR: Cannot apply sum-of-weights correction to covariance matrix: correction matrix calculated with weight-squared is singular" <<endl ;
 	} else {
-	  
-	  // Calculate corrected covariance matrix = V C-1 V
-	  TMatrixD VCV(V,TMatrixD::kMult,TMatrixD(C,TMatrixD::kMult,V)) ; 
-	  
-	  // Make matrix explicitly symmetric
-	  Int_t n = VCV.GetNrows() ;
-	  TMatrixDSym VCVsym(n) ;
-	  for (Int_t i=0 ; i<n ; i++) {
-	    for (Int_t j=i ; j<n ; j++) {
-	      if (i==j) {
-		VCVsym(i,j) = VCV(i,j) ;
-	      }
-	      if (i!=j) {
-		Double_t deltaRel = (VCV(i,j)-VCV(j,i))/sqrt(VCV(i,i)*VCV(j,j)) ;
-		if (fabs(deltaRel)>1e-3) {
-		  coutW(Fitting) << "RooAbsPdf::fitTo(" << GetName() << ") WARNING: Corrected covariance matrix is not (completely) symmetric: V[" << i << "," << j << "] = " 
-				 << VCV(i,j) << " V[" << j << "," << i << "] = " << VCV(j,i) << " explicitly restoring symmetry by inserting average value" << endl ;
-		}
-		VCVsym(i,j) = (VCV(i,j)+VCV(j,i))/2 ;
-	      }
-	    }
-	  }
-	  
+	  // replace C by its inverse
+	  decomp.Invert(matC); 
+	  matC.Similarity(matV);
+	  // C now contiains V C^-1 V
 	  // Propagate corrected errors to parameters objects
-	  m.applyCovarianceMatrix(VCVsym) ;
+	  m.applyCovarianceMatrix(matC);
 	}
 	
-	delete rw ;
-	delete rw2 ;
+	delete rw;
+	delete rw2;
       }
       
       if (minos) {
diff --git a/roofit/roofitcore/src/RooAbsReal.cxx b/roofit/roofitcore/src/RooAbsReal.cxx
index 9cdd13a..0e1b530 100644
--- a/roofit/roofitcore/src/RooAbsReal.cxx
+++ b/roofit/roofitcore/src/RooAbsReal.cxx
@@ -2263,8 +2263,8 @@ RooPlot* RooAbsReal::plotAsymOn(RooPlot *frame, const RooAbsCategoryLValue& asym
   depPos.add(projDataVars) ;
   depNeg.add(projDataVars) ;
 
-  const RooAbsReal *posProj = funcPos->createPlotProjection(depPos, &projectedVars, posProjCompList) ;
-  const RooAbsReal *negProj = funcNeg->createPlotProjection(depNeg, &projectedVars, negProjCompList) ;
+  const RooAbsReal *posProj = funcPos->createPlotProjection(depPos, &projectedVars, posProjCompList, o.projectionRangeName) ;
+  const RooAbsReal *negProj = funcNeg->createPlotProjection(depNeg, &projectedVars, negProjCompList, o.projectionRangeName) ;
   if (!posProj || !negProj) {
     coutE(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() << ") Unable to create projections, abort" << endl ;
     return frame ; 
@@ -3356,34 +3356,6 @@ Double_t RooAbsReal::maxVal(Int_t /*code*/) const
 
 
 //_____________________________________________________________________________
-void RooAbsReal::EvalError::setMessage(const char* tmp) 
-{ 
-  if (strlen(tmp)<1023) {
-    strlcpy(_msg,tmp,1023) ; 
-  } else {
-    strncpy(_msg,tmp,1020); 
-    _msg[1020]='.' ; _msg[1021]='.' ; 
-    _msg[1022]='.' ; _msg[1023]=0 ;    
-  }
-}
-
-
-
-//_____________________________________________________________________________
-void RooAbsReal::EvalError::setServerValues(const char* tmp) 
-{ 
-  if (strlen(tmp)<1023) {
-    strlcpy(_srvval,tmp,1023) ; 
-  } else {
-    strncpy(_srvval,tmp,1020); 
-    _srvval[1020]='.' ; _srvval[1021]='.' ;
-    _srvval[1022]='.' ; _srvval[1023]=0 ;    
-  }
-}
-
-
-
-//_____________________________________________________________________________
 void RooAbsReal::logEvalError(const RooAbsReal* originator, const char* origName, const char* message, const char* serverValueString) 
 {
   // Interface to insert remote error logging messages received by RooRealMPFE into current error loggin stream
diff --git a/roofit/roofitcore/src/RooAbsTestStatistic.cxx b/roofit/roofitcore/src/RooAbsTestStatistic.cxx
index 73726ea..7fe8909 100644
--- a/roofit/roofitcore/src/RooAbsTestStatistic.cxx
+++ b/roofit/roofitcore/src/RooAbsTestStatistic.cxx
@@ -58,30 +58,14 @@ ClassImp(RooAbsTestStatistic)
 
 
 //_____________________________________________________________________________
-RooAbsTestStatistic::RooAbsTestStatistic()
+RooAbsTestStatistic::RooAbsTestStatistic() :
+  _func(0), _data(0), _projDeps(0), _splitRange(0), _simCount(0),
+  _verbose(kFALSE), _init(kFALSE), _gofOpMode(Slave), _nEvents(0), _setNum(0),
+  _numSets(0), _extSet(0), _nGof(0), _gofArray(0), _nCPU(1), _mpfeArray(0),
+  _mpinterl(RooFit::BulkPartition), _doOffset(kFALSE), _offset(0),
+  _offsetCarry(0), _evalCarry(0)
 {
-  // Default constructor
-  _func = 0 ;
-  _data = 0 ;
-  _projDeps = 0 ;
-  _init = kFALSE ;
-  _gofArray = 0 ;
-  _mpfeArray = 0 ;
-  _projDeps = 0 ;
-  _gofOpMode = Slave ;
-  _mpinterl = RooFit::BulkPartition ;
-  _nCPU = 1 ;
-  _nEvents = 0 ; 
-  _nGof = 0 ;
-  _numSets = 0 ;
-  _setNum = 0 ;
-  _extSet = 0 ;
-  _simCount = 0 ;
-  _splitRange = 0 ;
-  _verbose = kFALSE ;
-  _doOffset = kFALSE ;
-  _offset = 0 ;
-  _offsetCarry = 0;
+      // Default constructor
 }
 
 
@@ -107,7 +91,8 @@ RooAbsTestStatistic::RooAbsTestStatistic(const char *name, const char *title, Ro
   _mpinterl(interleave),
   _doOffset(kFALSE),
   _offset(0),
-  _offsetCarry(0)
+  _offsetCarry(0),
+  _evalCarry(0)
 {
   // Constructor taking function (real), a dataset (data), a set of projected observables (projSet). If
   // rangeName is not null, only events in the dataset inside the range will be used in the test
@@ -176,7 +161,8 @@ RooAbsTestStatistic::RooAbsTestStatistic(const RooAbsTestStatistic& other, const
   _mpinterl(other._mpinterl),
   _doOffset(other._doOffset),
   _offset(other._offset),
-  _offsetCarry(other._offsetCarry)
+  _offsetCarry(other._offsetCarry),
+  _evalCarry(other._evalCarry)
 {
   // Copy constructor
 
@@ -219,25 +205,17 @@ RooAbsTestStatistic::~RooAbsTestStatistic()
 {
   // Destructor
 
-  if (_gofOpMode==MPMaster && _init) {
-    Int_t i ;
-    for (i=0 ; i<_nCPU ; i++) {
-      delete _mpfeArray[i] ;
-    }
+  if (MPMaster == _gofOpMode && _init) {
+    for (Int_t i = 0; i < _nCPU; ++i) delete _mpfeArray[i];
     delete[] _mpfeArray ;
   }
 
-  if (_gofOpMode==SimMaster && _init) {
-    Int_t i ;
-    for (i=0 ; i<_nGof ; i++) {
-      delete _gofArray[i] ;
-    }
+  if (SimMaster == _gofOpMode && _init) {
+    for (Int_t i = 0; i < _nGof; ++i) delete _gofArray[i];
     delete[] _gofArray ;
   }
 
-  if (_projDeps) {
-    delete _projDeps ;
-  }
+  delete _projDeps ;
 
 }
 
@@ -257,51 +235,55 @@ Double_t RooAbsTestStatistic::evaluate() const
     const_cast<RooAbsTestStatistic*>(this)->initialize() ;
   }
 
-  if (_gofOpMode==SimMaster) {
-
+  if (SimMaster == _gofOpMode) {
     // Evaluate array of owned GOF objects
-    Double_t ret(0) ;
+    Double_t ret = 0.;
 
     if (_mpinterl == RooFit::BulkPartition || _mpinterl == RooFit::Interleave ) {
-      
-      ret = combinedValue((RooAbsReal**)_gofArray,_nGof) ;
-
+      ret = combinedValue((RooAbsReal**)_gofArray,_nGof);
     } else {
-
-      Double_t sum(0) ;
-      Int_t i ;
-      for (i=0 ; i<_nGof ; i++) {
+      Double_t sum = 0., carry = 0.;
+      for (Int_t i = 0 ; i < _nGof; ++i) {
 	if (i % _numSets == _setNum || (_mpinterl==RooFit::Hybrid && _gofSplitMode[i] != RooFit::SimComponents )) {
-	  Double_t tmp = _gofArray[i]->getValV() ;
-	  sum += tmp ;
+	  Double_t y = _gofArray[i]->getValV();
+	  carry += _gofArray[i]->getCarry();
+	  y -= carry;
+	  const Double_t t = sum + y;
+	  carry = (t - sum) - y;
+	  sum = t;
 	}
       }
       ret = sum ;
+      _evalCarry = carry;
     }
 
     // Only apply global normalization if SimMaster doesn't have MP master
     if (numSets()==1) {
-      ret /= globalNormalization() ;
+      const Double_t norm = globalNormalization();
+      ret /= norm;
+      _evalCarry /= norm;
     }
 
     return ret ;
 
-  } else if (_gofOpMode==MPMaster) {
+  } else if (MPMaster == _gofOpMode) {
     
     // Start calculations in parallel
-    Int_t i ;
-    for (i=0 ; i<_nCPU ; i++) {
-      _mpfeArray[i]->calculate() ;
-    }
+    for (Int_t i = 0; i < _nCPU; ++i) _mpfeArray[i]->calculate();
 
 
-    Double_t sum(0) ;
-    for (i=0 ; i<_nCPU ; i++) {
-      Double_t tmp = _mpfeArray[i]->getValV() ;
-      sum += tmp ;
+    Double_t sum(0), carry = 0.;
+    for (Int_t i = 0; i < _nCPU; ++i) {
+      Double_t y = _mpfeArray[i]->getValV();
+      carry += _mpfeArray[i]->getCarry();
+      y -= carry;
+      const Double_t t = sum + y;
+      carry = (t - sum) - y;
+      sum = t;
     }
 
     Double_t ret = sum ;
+    _evalCarry = carry;
     return ret ;
 
   } else {
@@ -333,10 +315,12 @@ Double_t RooAbsTestStatistic::evaluate() const
       break ;
     }
 
-    Double_t ret =  evaluatePartition(nFirst,nLast,nStep) ;
+    Double_t ret = evaluatePartition(nFirst,nLast,nStep);
 
     if (numSets()==1) {
-      ret /= globalNormalization() ;
+      const Double_t norm = globalNormalization();
+      ret /= norm;
+      _evalCarry /= norm;
     }
     
     return ret ;
@@ -353,15 +337,15 @@ Bool_t RooAbsTestStatistic::initialize()
   // infrastructure for simultaneous p.d.f processing and/or
   // parallelized processing if requested
   
-  if (_init) return kFALSE ;
+  if (_init) return kFALSE;
   
-  if (_gofOpMode==MPMaster) {
+  if (MPMaster == _gofOpMode) {
     initMPMode(_func,_data,_projDeps,_rangeName.size()?_rangeName.c_str():0,_addCoefRangeName.size()?_addCoefRangeName.c_str():0) ;
-  } else if (_gofOpMode==SimMaster) {
+  } else if (SimMaster == _gofOpMode) {
     initSimMode((RooSimultaneous*)_func,_data,_projDeps,_rangeName.size()?_rangeName.c_str():0,_addCoefRangeName.size()?_addCoefRangeName.c_str():0) ;
   }
-  _init = kTRUE ;
-  return kFALSE ;
+  _init = kTRUE;
+  return kFALSE;
 }
 
 
@@ -370,28 +354,23 @@ Bool_t RooAbsTestStatistic::initialize()
 Bool_t RooAbsTestStatistic::redirectServersHook(const RooAbsCollection& newServerList, Bool_t mustReplaceAll, Bool_t nameChange, Bool_t)
 {
   // Forward server redirect calls to component test statistics
-
-  if (_gofOpMode==SimMaster && _gofArray) {
+  if (SimMaster == _gofOpMode && _gofArray) {
     // Forward to slaves
-    Int_t i ;
-    for (i=0 ; i<_nGof ; i++) {
+    for (Int_t i = 0; i < _nGof; ++i) {
       if (_gofArray[i]) {
-	_gofArray[i]->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange) ;
+	_gofArray[i]->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange);
       }
     }
-  } else if (_gofOpMode==MPMaster && _mpfeArray) {
-
+  } else if (MPMaster == _gofOpMode&& _mpfeArray) {
     // Forward to slaves
-    Int_t i ;
-    for (i=0 ; i<_nCPU ; i++) {
+    for (Int_t i = 0; i < _nCPU; ++i) {
       if (_mpfeArray[i]) {
-	_mpfeArray[i]->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange) ;
-// 	cout << "redirecting servers on " << _mpfeArray[i]->GetName() << endl ;
+	_mpfeArray[i]->recursiveRedirectServers(newServerList,mustReplaceAll,nameChange);
+// 	cout << "redirecting servers on " << _mpfeArray[i]->GetName() << endl;
       }
     }
-
   }
-  return kFALSE ;
+  return kFALSE;
 }
 
 
@@ -401,20 +380,18 @@ void RooAbsTestStatistic::printCompactTreeHook(ostream& os, const char* indent)
 {
   // Add extra information on component test statistics when printing
   // itself as part of a tree structure
-
-  if (_gofOpMode==SimMaster) {
+  if (SimMaster == _gofOpMode) {
     // Forward to slaves
-    Int_t i ;
     os << indent << "RooAbsTestStatistic begin GOF contents" << endl ;
-    for (i=0 ; i<_nGof ; i++) {
+    for (Int_t i = 0; i < _nGof; ++i) {
       if (_gofArray[i]) {
-	TString indent2(indent) ;
-	indent2 += Form("[%d] ",i) ;
-	_gofArray[i]->printCompactTreeHook(os,indent2) ;
+	TString indent2(indent);
+	indent2 += Form("[%d] ",i);
+	_gofArray[i]->printCompactTreeHook(os,indent2);
       }
     }
-    os << indent << "RooAbsTestStatistic end GOF contents" << endl ;
-  } else if (_gofOpMode==MPMaster) {
+    os << indent << "RooAbsTestStatistic end GOF contents" << endl;
+  } else if (MPMaster == _gofOpMode) {
     // WVE implement this
   }
 }
@@ -426,20 +403,19 @@ void RooAbsTestStatistic::constOptimizeTestStatistic(ConstOpCode opcode, Bool_t
 {
   // Forward constant term optimization management calls to component
   // test statistics
-  Int_t i ;
-  initialize() ;
-  if (_gofOpMode==SimMaster) {
+  initialize();
+  if (SimMaster == _gofOpMode) {
     // Forward to slaves
-    for (i=0 ; i<_nGof ; i++) {
+    for (Int_t i = 0; i < _nGof; ++i) {
       // In SimComponents Splitting strategy only constOptimize the terms that are actually used
-      RooFit::MPSplit effSplit = (_mpinterl!=RooFit::Hybrid) ? _mpinterl : _gofSplitMode[i] ;
+      RooFit::MPSplit effSplit = (_mpinterl!=RooFit::Hybrid) ? _mpinterl : _gofSplitMode[i];
       if ( (i % _numSets == _setNum) || (effSplit != RooFit::SimComponents) ) {
-	if (_gofArray[i]) _gofArray[i]->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt) ;
+	if (_gofArray[i]) _gofArray[i]->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
       }
     }
-  } else if (_gofOpMode==MPMaster) {
-    for (i=0 ; i<_nCPU ; i++) {
-      _mpfeArray[i]->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt) ;
+  } else if (MPMaster == _gofOpMode) {
+    for (Int_t i = 0; i < _nCPU; ++i) {
+      _mpfeArray[i]->constOptimizeTestStatistic(opcode,doAlsoTrackingOpt);
     }
   }
 }
@@ -450,16 +426,14 @@ void RooAbsTestStatistic::constOptimizeTestStatistic(ConstOpCode opcode, Bool_t
 void RooAbsTestStatistic::setMPSet(Int_t inSetNum, Int_t inNumSets)
 {
   // Set MultiProcessor set number identification of this instance
-
-  _setNum = inSetNum ; _numSets = inNumSets ;
-  _extSet = _mpinterl==RooFit::SimComponents ? _setNum : crc32(Form("%sXXXX",GetName()))%_numSets ;
+  _setNum = inSetNum; _numSets = inNumSets;
+  _extSet = _mpinterl==RooFit::SimComponents ? _setNum : (_numSets - 1);
   
-  if (_gofOpMode==SimMaster) {
+  if (SimMaster == _gofOpMode) {
     // Forward to slaves
-    initialize() ;
-    Int_t i ;
-    for (i=0 ; i<_nGof ; i++) {
-      if (_gofArray[i]) _gofArray[i]->setMPSet(inSetNum,inNumSets) ;
+    initialize();
+    for (Int_t i = 0; i < _nGof; ++i) {
+      if (_gofArray[i]) _gofArray[i]->setMPSet(inSetNum,inNumSets);
     }
   }
 }
@@ -472,31 +446,27 @@ void RooAbsTestStatistic::initMPMode(RooAbsReal* real, RooAbsData* data, const R
   // Initialize multi-processor calculation mode. Create component test statistics in separate
   // processed that are connected to this process through a RooAbsRealMPFE front-end class.
 
-  Int_t i ;
-  _mpfeArray = new pRooRealMPFE[_nCPU] ;
+  _mpfeArray = new pRooRealMPFE[_nCPU];
 
   // Create proto-goodness-of-fit
-  RooAbsTestStatistic* gof = create(GetName(),GetTitle(),*real,*data,*projDeps,rangeName,addCoefRangeName,1,_mpinterl,_verbose,_splitRange) ;
-  gof->recursiveRedirectServers(_paramSet) ;
-
-  for (i=0 ; i<_nCPU ; i++) {
-
-    gof->setMPSet(i,_nCPU) ;
-    gof->SetName(Form("%s_GOF%d",GetName(),i)) ;
-    gof->SetTitle(Form("%s_GOF%d",GetTitle(),i)) ;
-
-    Bool_t doInline = (i==_nCPU-1) ;
-    if (!doInline) coutI(Eval) << "RooAbsTestStatistic::initMPMode: starting remote server process #" << i << endl ;
-    _mpfeArray[i] = new RooRealMPFE(Form("%s_%lx_MPFE%d",GetName(),(ULong_t)this,i),Form("%s_%lx_MPFE%d",GetTitle(),(ULong_t)this,i),*gof,doInline) ;
-    //_mpfeArray[i]->setVerbose(kTRUE,kTRUE) ;
-    _mpfeArray[i]->initialize() ;
-    if (doInline) {
-      _mpfeArray[i]->addOwnedComponents(*gof) ;
-    }
-    if (i>0) {
-      _mpfeArray[i]->followAsSlave(*_mpfeArray[0]) ;
+  RooAbsTestStatistic* gof = create(GetName(),GetTitle(),*real,*data,*projDeps,rangeName,addCoefRangeName,1,_mpinterl,_verbose,_splitRange);
+  gof->recursiveRedirectServers(_paramSet);
+
+  for (Int_t i = 0; i < _nCPU; ++i) {
+    gof->setMPSet(i,_nCPU);
+    gof->SetName(Form("%s_GOF%d",GetName(),i));
+    gof->SetTitle(Form("%s_GOF%d",GetTitle(),i));
+
+    ccoutD(Eval) << "RooAbsTestStatistic::initMPMode: starting remote server process #" << i << endl;
+    _mpfeArray[i] = new RooRealMPFE(Form("%s_%lx_MPFE%d",GetName(),(ULong_t)this,i),Form("%s_%lx_MPFE%d",GetTitle(),(ULong_t)this,i),*gof,false);
+    //_mpfeArray[i]->setVerbose(kTRUE,kTRUE);
+    _mpfeArray[i]->initialize();
+    if (i > 0) {
+      _mpfeArray[i]->followAsSlave(*_mpfeArray[0]);
     }
   }
+  _mpfeArray[_nCPU - 1]->addOwnedComponents(*gof);
+  coutI(Eval) << "RooAbsTestStatistic::initMPMode: started " << _nCPU << " remote server process." << endl;
   //cout << "initMPMode --- done" << endl ;
   return ;
 }
@@ -513,101 +483,99 @@ void RooAbsTestStatistic::initSimMode(RooSimultaneous* simpdf, RooAbsData* data,
   // each of them.
 
 
-  RooAbsCategoryLValue& simCat = (RooAbsCategoryLValue&) simpdf->indexCat() ;
+  RooAbsCategoryLValue& simCat = (RooAbsCategoryLValue&) simpdf->indexCat();
 
-  TString simCatName(simCat.GetName()) ;
-  TList* dsetList = const_cast<RooAbsData*>(data)->split(simCat,processEmptyDataSets()) ;
+  TString simCatName(simCat.GetName());
+  TList* dsetList = const_cast<RooAbsData*>(data)->split(simCat,processEmptyDataSets());
   if (!dsetList) {
-    coutE(Fitting) << "RooAbsTestStatistic::initSimMode(" << GetName() << ") ERROR: index category of simultaneous pdf is missing in dataset, aborting" << endl ;
-    throw std::string("RooAbsTestStatistic::initSimMode() ERROR, index category of simultaneous pdf is missing in dataset, aborting") ;
+    coutE(Fitting) << "RooAbsTestStatistic::initSimMode(" << GetName() << ") ERROR: index category of simultaneous pdf is missing in dataset, aborting" << endl;
+    throw std::string("RooAbsTestStatistic::initSimMode() ERROR, index category of simultaneous pdf is missing in dataset, aborting");
     //RooErrorHandler::softAbort() ;
   }
 
   // Count number of used states
-  Int_t n(0) ;
-  _nGof = 0 ;
-  RooCatType* type ;
-  TIterator* catIter = simCat.typeIterator() ;
-  while((type=(RooCatType*)catIter->Next())){
-
+  Int_t n = 0;
+  _nGof = 0;
+  RooCatType* type;
+  TIterator* catIter = simCat.typeIterator();
+  while ((type = (RooCatType*) catIter->Next())) {
     // Retrieve the PDF for this simCat state
-    RooAbsPdf* pdf =  simpdf->getPdf(type->GetName()) ;
-    RooAbsData* dset = (RooAbsData*) dsetList->FindObject(type->GetName()) ;
+    RooAbsPdf* pdf = simpdf->getPdf(type->GetName());
+    RooAbsData* dset = (RooAbsData*) dsetList->FindObject(type->GetName());
 
-    if (pdf && dset && (dset->sumEntries()!=0. || processEmptyDataSets() )) {
-      _nGof++ ;
+    if (pdf && dset && (0. != dset->sumEntries() || processEmptyDataSets())) {
+      ++_nGof;
     }
   }
 
   // Allocate arrays
-  _gofArray = new pRooAbsTestStatistic[_nGof] ;
-  _gofSplitMode.resize(_nGof) ;
+  _gofArray = new pRooAbsTestStatistic[_nGof];
+  _gofSplitMode.resize(_nGof);
 
   // Create array of regular fit contexts, containing subset of data and single fitCat PDF
-  catIter->Reset() ;
-  while((type=(RooCatType*)catIter->Next())){
-
+  catIter->Reset();
+  while ((type = (RooCatType*) catIter->Next())) {
     // Retrieve the PDF for this simCat state
-    RooAbsPdf* pdf =  simpdf->getPdf(type->GetName()) ;
-    RooAbsData* dset = (RooAbsData*) dsetList->FindObject(type->GetName()) ;
+    RooAbsPdf* pdf = simpdf->getPdf(type->GetName());
+    RooAbsData* dset = (RooAbsData*) dsetList->FindObject(type->GetName());
 
-    if (pdf && dset && (dset->sumEntries()!=0. || processEmptyDataSets())) {
-      coutI(Fitting) << "RooAbsTestStatistic::initSimMode: creating slave calculator #" << n << " for state " << type->GetName()
-		     << " (" << dset->numEntries() << " dataset entries)" << endl ;
+    if (pdf && dset && (0. != dset->sumEntries() || processEmptyDataSets())) {
+      ccoutD(Fitting) << "RooAbsTestStatistic::initSimMode: creating slave calculator #" << n << " for state " << type->GetName()
+		     << " (" << dset->numEntries() << " dataset entries)" << endl;
 
       if (_splitRange && rangeName) {
 	_gofArray[n] = create(type->GetName(),type->GetName(),*pdf,*dset,*projDeps,
-			      Form("%s_%s",rangeName,type->GetName()),addCoefRangeName,_nCPU*(_mpinterl?-1:1),_mpinterl,_verbose,_splitRange) ;
+			      Form("%s_%s",rangeName,type->GetName()),addCoefRangeName,_nCPU*(_mpinterl?-1:1),_mpinterl,_verbose,_splitRange);
       } else {
 	_gofArray[n] = create(type->GetName(),type->GetName(),*pdf,*dset,*projDeps,
-			      rangeName,addCoefRangeName,_nCPU,_mpinterl,_verbose,_splitRange) ;
+			      rangeName,addCoefRangeName,_nCPU,_mpinterl,_verbose,_splitRange);
       }
-      _gofArray[n]->setSimCount(_nGof) ;
+      _gofArray[n]->setSimCount(_nGof);
 
       // Fill per-component split mode with Bulk Partition for now so that Auto will map to bulk-splitting of all components
       if (_mpinterl==RooFit::Hybrid) {
 	if (dset->numEntries()<10) {
 	  //cout << "RAT::initSim("<< GetName() << ") MP mode is auto, setting split mode for component "<< n << " to SimComponents"<< endl ;
-	  _gofSplitMode[n] = RooFit::SimComponents ;
-	  _gofArray[n]->_mpinterl = RooFit::SimComponents ;
+	  _gofSplitMode[n] = RooFit::SimComponents;
+	  _gofArray[n]->_mpinterl = RooFit::SimComponents;
 	} else {
 	  //cout << "RAT::initSim("<< GetName() << ") MP mode is auto, setting split mode for component "<< n << " to BulkPartition"<< endl ;
-	  _gofSplitMode[n] = RooFit::BulkPartition ;
-	  _gofArray[n]->_mpinterl = RooFit::BulkPartition ;
+	  _gofSplitMode[n] = RooFit::BulkPartition;
+	  _gofArray[n]->_mpinterl = RooFit::BulkPartition;
 	}
       }
 
       // Servers may have been redirected between instantiation and (deferred) initialization
-      RooArgSet* actualParams = pdf->getParameters(dset) ;
-      RooArgSet* selTargetParams = (RooArgSet*) _paramSet.selectCommon(*actualParams) ;
+      RooArgSet* actualParams = pdf->getParameters(dset);
+      RooArgSet* selTargetParams = (RooArgSet*) _paramSet.selectCommon(*actualParams);
 
-      _gofArray[n]->recursiveRedirectServers(*selTargetParams) ;
+      _gofArray[n]->recursiveRedirectServers(*selTargetParams);
 
-      delete selTargetParams ;
-      delete actualParams ;
+      delete selTargetParams;
+      delete actualParams;
 
-      n++ ;
+      ++n;
     } else {
-      if ((!dset || (dset->sumEntries()==0. && !processEmptyDataSets()) ) && pdf) {
+      if ((!dset || (0. != dset->sumEntries() && !processEmptyDataSets())) && pdf) {
 	if (_verbose) {
-	  coutI(Fitting) << "RooAbsTestStatistic::initSimMode: state " << type->GetName()
-			 << " has no data entries, no slave calculator created" << endl ;
+	  ccoutD(Fitting) << "RooAbsTestStatistic::initSimMode: state " << type->GetName()
+			 << " has no data entries, no slave calculator created" << endl;
 	}
       }
     }
   }
+  coutI(Fitting) << "RooAbsTestStatistic::initSimMode: created " << n << " slave calculators." << endl;
   
   // Delete datasets by hand as TList::Delete() doesn't see our datasets as 'on the heap'...
-  TIterator* iter = dsetList->MakeIterator() ;
-  TObject* ds ;
-  while((ds=iter->Next())) {
-    delete ds ;
+  TIterator* iter = dsetList->MakeIterator();
+  TObject* ds;
+  while((ds = iter->Next())) {
+    delete ds;
   }
-  delete iter ;
-
-  delete dsetList ;
-  delete catIter ;
+  delete iter;
 
+  delete dsetList;
+  delete catIter;
 }
 
 
@@ -621,55 +589,50 @@ Bool_t RooAbsTestStatistic::setData(RooAbsData& indata, Bool_t cloneData)
 
   // Trigger refresh of likelihood offsets 
   if (isOffsetting()) {
-    enableOffsetting(kFALSE) ;
-    enableOffsetting(kTRUE) ;
+    enableOffsetting(kFALSE);
+    enableOffsetting(kTRUE);
   }
 
   switch(operMode()) {
-
   case Slave:
     // Delegate to implementation
-    return setDataSlave(indata,cloneData) ;
-
+    return setDataSlave(indata, cloneData);
   case SimMaster:
     // Forward to slaves
-    //     cout << "RATS::setData(" << GetName() << ") SimMaster, calling setDataSlave() on slave nodes" << endl ;
+    //     cout << "RATS::setData(" << GetName() << ") SimMaster, calling setDataSlave() on slave nodes" << endl;
     if (indata.canSplitFast()) {
-      for (Int_t i=0 ; i<_nGof ; i++) {
-	RooAbsData* compData = indata.getSimData(_gofArray[i]->GetName()) ;	
-	_gofArray[i]->setDataSlave(*compData,cloneData) ;
+      for (Int_t i = 0; i < _nGof; ++i) {
+	RooAbsData* compData = indata.getSimData(_gofArray[i]->GetName());
+	_gofArray[i]->setDataSlave(*compData, cloneData);
       }
-    } else if (indata.numEntries()==0) {
+    } else if (0 == indata.numEntries()) {
       // For an unsplit empty dataset, simply assign empty dataset to each component
-      for (Int_t i=0 ; i<_nGof ; i++) {
-	_gofArray[i]->setDataSlave(indata,cloneData) ;
+      for (Int_t i = 0; i < _nGof; ++i) {
+	_gofArray[i]->setDataSlave(indata, cloneData);
       }
     } else {
-//       cout << "NONEMPTY DATASET WITHOUT FAST SPLIT SUPPORT! "<< indata.GetName() << endl ;   
-      const RooAbsCategoryLValue* indexCat = & ((RooSimultaneous*)_func)->indexCat() ;
-      TList* dlist = indata.split(*indexCat,kTRUE) ;
-      for (Int_t i=0 ; i<_nGof ; i++) {
-	RooAbsData* compData = (RooAbsData*) dlist->FindObject(_gofArray[i]->GetName()) ;
-	// 	cout << "component data for index " << _gofArray[i]->GetName() << " is " << compData << endl ;
+//       cout << "NONEMPTY DATASET WITHOUT FAST SPLIT SUPPORT! "<< indata.GetName() << endl;
+      const RooAbsCategoryLValue* indexCat = & ((RooSimultaneous*)_func)->indexCat();
+      TList* dlist = indata.split(*indexCat, kTRUE);
+      for (Int_t i = 0; i < _nGof; ++i) {
+	RooAbsData* compData = (RooAbsData*) dlist->FindObject(_gofArray[i]->GetName());
+	// 	cout << "component data for index " << _gofArray[i]->GetName() << " is " << compData << endl;
 	if (compData) {
-	  _gofArray[i]->setDataSlave(*compData,kFALSE,kTRUE) ;
+	  _gofArray[i]->setDataSlave(*compData,kFALSE,kTRUE);
 	} else {
-	  coutE(DataHandling) << "RooAbsTestStatistic::setData(" << GetName() << ") ERROR: Cannot find component data for state " << _gofArray[i]->GetName() << endl ;
-	}	
+	  coutE(DataHandling) << "RooAbsTestStatistic::setData(" << GetName() << ") ERROR: Cannot find component data for state " << _gofArray[i]->GetName() << endl;
+	}
       }
-      
     }
-    break ;
-    
+    break;
   case MPMaster:
     // Not supported
-    coutF(DataHandling) << "RooAbsTestStatistic::setData(" << GetName() << ") FATAL: setData() is not supported in multi-processor mode" << endl ;
-    throw string("RooAbsTestStatistic::setData is not supported in MPMaster mode") ;
-    break ;
+    coutF(DataHandling) << "RooAbsTestStatistic::setData(" << GetName() << ") FATAL: setData() is not supported in multi-processor mode" << endl;
+    throw string("RooAbsTestStatistic::setData is not supported in MPMaster mode");
+    break;
   }
 
-
-  return kTRUE ;
+  return kTRUE;
 }
 
 
@@ -682,7 +645,6 @@ void RooAbsTestStatistic::enableOffsetting(Bool_t flag)
   }
   
   switch(operMode()) {
-    
   case Slave:
     _doOffset = flag ;
     // Clear offset if feature is disabled to that it is recalculated next time it is enabled
@@ -692,20 +654,21 @@ void RooAbsTestStatistic::enableOffsetting(Bool_t flag)
     }
     setValueDirty() ;
     break ;
-
   case SimMaster:
-    _doOffset = flag ;
-    for (Int_t i=0 ; i<_nGof ; i++) {
-      _gofArray[i]->enableOffsetting(flag) ;      
+    _doOffset = flag;
+    for (Int_t i = 0; i < _nGof; ++i) {
+      _gofArray[i]->enableOffsetting(flag);
     }
     break ;
-
   case MPMaster:    
-    _doOffset = flag ;
-    for (Int_t i=0 ; i<_nCPU ; i++) {
-      _mpfeArray[i]->enableOffsetting(flag) ;
+    _doOffset = flag;
+    for (Int_t i = 0; i < _nCPU; ++i) {
+      _mpfeArray[i]->enableOffsetting(flag);
     }
+    break;
   }
 }
 
 
+Double_t RooAbsTestStatistic::getCarry() const
+{ return _evalCarry; }
diff --git a/roofit/roofitcore/src/RooBanner.cxx b/roofit/roofitcore/src/RooBanner.cxx
index fe12111..850662b 100644
--- a/roofit/roofitcore/src/RooBanner.cxx
+++ b/roofit/roofitcore/src/RooBanner.cxx
@@ -12,7 +12,7 @@
 
 using namespace std;
 
-const char* VTAG="3.56" ;
+const char* VTAG="3.57" ;
 
 Int_t doBanner()
 
diff --git a/roofit/roofitcore/src/RooBinning.cxx b/roofit/roofitcore/src/RooBinning.cxx
index db959f6..35c01c1 100644
--- a/roofit/roofitcore/src/RooBinning.cxx
+++ b/roofit/roofitcore/src/RooBinning.cxx
@@ -15,16 +15,18 @@
  *****************************************************************************/
 
 //////////////////////////////////////////////////////////////////////////////
-// 
-// BEGIN_HTML 
+//
+// BEGIN_HTML
 // Class RooBinning is an implements RooAbsBinning in terms
 // of an array of boundary values, posing no constraints on the choice
 // of binning, thus allowing variable bin sizes. Various methods allow
 // the user to add single bin boundaries, mirrored pairs, or sets of
-// uniformly spaced boundaries.  
+// uniformly spaced boundaries.
 // END_HTML
 //
 
+#include <cmath>
+#include <algorithm>
 #include "RooFit.h"
 
 #include "Riostream.h"
@@ -44,371 +46,261 @@ ClassImp(RooBinning)
 
 
 //_____________________________________________________________________________
-RooBinning::RooBinning(Double_t xlo, Double_t xhi, const char* name) : 
-  RooAbsBinning(name), 
-  _xlo(0),
-  _xhi(0),
-  _ownBoundLo(kTRUE), 
-  _ownBoundHi(kTRUE), 
-  _array(0)
+RooBinning::RooBinning(Double_t xlo, Double_t xhi, const char* name) :
+  RooAbsBinning(name),
+  _xlo(0), _xhi(0), _ownBoundLo(kTRUE), _ownBoundHi(kTRUE),
+  _array(0), _blo(0)
 {
   // Constructor for an initially empty binning defining the range [xlo,xhi]
-
-  setRange(xlo,xhi) ;
+  setRange(xlo,xhi);
 }
 
-
-
 //_____________________________________________________________________________
-RooBinning::RooBinning(Int_t nbins, Double_t xlo, Double_t xhi, const char* name) : 
-  RooAbsBinning(name), 
-  _xlo(0),
-  _xhi(0),
-  _ownBoundLo(kTRUE), 
-  _ownBoundHi(kTRUE), 
-  _array(0)
+RooBinning::RooBinning(Int_t nbins, Double_t xlo, Double_t xhi, const char* name) :
+  RooAbsBinning(name),
+  _xlo(0), _xhi(0), _ownBoundLo(kTRUE), _ownBoundHi(kTRUE),
+  _array(0), _blo(0)
 {
   // Constructor for a uniform binning in 'nbins' bins in the range [xlo,xhi]
-
-  // Uniform bin size constructor
-  setRange(xlo,xhi) ;
-  addUniform(nbins,xlo,xhi) ;
+  _boundaries.reserve(1 + nbins);
+  setRange(xlo, xhi);
+  addUniform(nbins, xlo, xhi);
 }
 
-
-
-
 //_____________________________________________________________________________
-RooBinning::RooBinning(Int_t nbins, const Double_t* boundaries, const char* name) : 
+RooBinning::RooBinning(Int_t nbins, const Double_t* boundaries, const char* name) :
   RooAbsBinning(name),
-  _xlo(0),
-  _xhi(0),
-  _ownBoundLo(kTRUE), 
-  _ownBoundHi(kTRUE), 
-  _array(0)
+  _xlo(0), _xhi(0), _ownBoundLo(kTRUE), _ownBoundHi(kTRUE),
+  _array(0), _blo(0)
 {
   // Constructor for a binning in the range[xlo,xhi] with 'nbins' bin boundaries listed
   // array 'boundaries'
 
   // Variable bin size constructor
-  setRange(boundaries[0],boundaries[nbins]) ;
-  while(nbins--) addBoundary(boundaries[nbins]) ;
+  _boundaries.reserve(1 + nbins);
+  setRange(boundaries[0], boundaries[nbins]);
+  while (nbins--) addBoundary(boundaries[nbins]);
 }
 
-
-
 //_____________________________________________________________________________
-RooBinning::RooBinning(const RooBinning& other, const char* name) : 
-  RooAbsBinning(name),
-  _boundaries(other._boundaries),
-  _array(0)
-{ 
+RooBinning::RooBinning(const RooBinning& other, const char* name) :
+  RooAbsBinning(name), _xlo(other._xlo), _xhi(other._xhi),
+  _ownBoundLo(other._ownBoundLo), _ownBoundHi(other._ownBoundHi),
+  _nbins(other._nbins), _boundaries(other._boundaries), _array(0),
+  _blo(other._blo)
+{
   // Copy constructor
-  _xlo = other._xlo ;
-  _xhi = other._xhi ;
-  _ownBoundLo = other._ownBoundLo ;
-  _ownBoundHi = other._ownBoundHi ;
-  _nbins = other._nbins ;
 }
 
-
-
 //_____________________________________________________________________________
-RooBinning::~RooBinning() 
+RooBinning::~RooBinning()
 {
   // Destructor
-
-  if (_array) delete[] _array ;
-
+  delete[] _array;
 }
 
-
 //_____________________________________________________________________________
-Bool_t RooBinning::addBoundary(Double_t boundary) 
-{  
+Bool_t RooBinning::addBoundary(Double_t boundary)
+{
   // Add bin boundary at given value
-
-  if (_boundaries.find(boundary)!=_boundaries.end()) {
-    // If boundary previously existed as range delimiter, 
+  std::vector<Double_t>::iterator it =
+      std::lower_bound(_boundaries.begin(), _boundaries.end(), boundary);
+  if (_boundaries.end() != it && *it == boundary) {
+    // If boundary previously existed as range delimiter,
     //                    convert to regular boundary now
-    if (boundary==_xlo) _ownBoundLo = kFALSE ;
-    if (boundary==_xhi) _ownBoundHi = kFALSE ;
-    return kFALSE ;    
+    if (boundary == _xlo) _ownBoundLo = kFALSE;
+    if (boundary == _xhi) _ownBoundHi = kFALSE;
+    return kFALSE;
   }
-
   // Add a new boundary
-  _boundaries.insert(boundary) ;
-  updateBinCount() ;
-  return kTRUE ;
+  _boundaries.insert(it, boundary);
+  updateBinCount();
+  return kTRUE;
 }
 
-
-
 //_____________________________________________________________________________
-void RooBinning::addBoundaryPair(Double_t boundary, Double_t mirrorPoint) 
+void RooBinning::addBoundaryPair(Double_t boundary, Double_t mirrorPoint)
 {
   // Add pair of boundaries: one at 'boundary' and one at 2*mirrorPoint-boundary
-
-  addBoundary(boundary) ;
-  addBoundary(2*mirrorPoint-boundary) ;
+  addBoundary(boundary);
+  addBoundary(2. * mirrorPoint - boundary);
 }
 
-
-
 //_____________________________________________________________________________
 Bool_t RooBinning::removeBoundary(Double_t boundary)
 {
   // Remove boundary at given value
-
-  if (_boundaries.find(boundary)!=_boundaries.end()) {
-    _boundaries.erase(boundary) ;
-    return kFALSE ;
+  std::vector<Double_t>::iterator it = std::lower_bound(_boundaries.begin(),
+      _boundaries.end(), boundary);
+  if  (_boundaries.end() != it && *it == boundary) {
+    _boundaries.erase(it);
+    // if some moron deletes the boundaries corresponding to the current
+    // range, we need to make sure that we do not get into an undefined state,
+    // so _xlo and _xhi need to be set to some valid values
+    if (_boundaries.empty()) {
+      _xlo = _xhi = 0.;
+    } else {
+      if (boundary == _xlo) _xlo = _boundaries.front();
+      if (boundary == _xhi) _xhi = _boundaries.back();
+    }
+    updateBinCount();
+    return kFALSE;
   }
-
   // Return error status - no boundary found
-  return kTRUE ;
+  return kTRUE;
 }
 
-
-
 //_____________________________________________________________________________
 Bool_t RooBinning::hasBoundary(Double_t boundary)
 {
   // Check if boundary exists at given value
-
-  return (_boundaries.find(boundary)!=_boundaries.end()) ;
+  return std::binary_search(_boundaries.begin(), _boundaries.end(), boundary);
 }
 
-
-
 //_____________________________________________________________________________
 void RooBinning::addUniform(Int_t nbins, Double_t xlo, Double_t xhi)
 {
   // Add array of nbins uniformly sized bins in range [xlo,xhi]
-
-  Int_t i ;
-  Double_t binw = (xhi-xlo)/nbins ;
-  for (i=0 ; i<=nbins ; i++) 
-    addBoundary(xlo+i*binw) ;  
+  _boundaries.reserve(_boundaries.size() + nbins + 1);
+  for (Int_t i = 0; i <= nbins; ++i)
+    addBoundary((double(nbins - i) / double(nbins)) * xlo +
+	(double(i) / double(nbins)) * xhi);
 }
 
-
-
 //_____________________________________________________________________________
 Int_t RooBinning::binNumber(Double_t x) const
 {
   // Return sequential bin number that contains value x where bin
   // zero is the first bin with an upper boundary above the lower bound
   // of the range
-
-  Int_t n(0) ;
-  for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {
-    if (x<*iter) {
-      return n ;
-    }
-
-    // Only increment counter in valid range
-    if (*iter> _xlo && n<_nbins-1) n++ ;    
-  }  
-  return n;
+  return std::max(0, std::min(_nbins, rawBinNumber(x) - _blo));
 }
 
-
-
 //_____________________________________________________________________________
-Int_t RooBinning::rawBinNumber(Double_t x) const 
+Int_t RooBinning::rawBinNumber(Double_t x) const
 {
   // Return sequential bin number that contains value x where bin
   // zero is the first bin that is defined, regardless if that bin
   // is outside the current defined range
-  
- 
-  // Determine 'raw' bin number (i.e counting all defined boundaries) for given value
-  Int_t n(0) ;
-
-  for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {    
-    if (x<*iter) return n>0?n-1:0 ;
-    n++ ;
-  }
-  return n-1;
+  std::vector<Double_t>::const_iterator it = std::lower_bound(
+      _boundaries.begin(), _boundaries.end(), x);
+  // always return valid bin number
+  while (_boundaries.begin() != it &&
+	  (_boundaries.end() == it || _boundaries.end() == it + 1 || x < *it)) --it;
+  return it - _boundaries.begin();
 }
 
-
-
 //_____________________________________________________________________________
-Double_t RooBinning::nearestBoundary(Double_t x) const 
+Double_t RooBinning::nearestBoundary(Double_t x) const
 {
   // Return the value of the nearest boundary to x
-
-  Int_t bn = binNumber(x) ;
-  if (fabs(binLow(bn)-x)<fabs(binHigh(bn)-x)) {
-    return binLow(bn) ;
-  } else {
-    return binHigh(bn) ;
-  }
+  Double_t xl, xh;
+  binEdges(binNumber(x), xl, xh);
+  return (std::abs(xl - x) < std::abs(xh - x)) ? xl : xh;
 }
 
-
-
 //_____________________________________________________________________________
 Double_t* RooBinning::array() const
 {
   // Return array of boundary values
 
-  if (_array) delete[] _array ;
-  _array = new Double_t[numBoundaries()] ;
-
-  Int_t i(0) ;
-  for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {
-    if (*iter>=_xlo && *iter <=_xhi) {
-      _array[i++] = *iter ;
-    }
-  }
-  return _array ;
+  delete[] _array;
+  _array = new Double_t[numBoundaries()];
+  std::copy(&_boundaries[_blo], &_boundaries[_blo + _nbins + 1], _array);
+  return _array;
 }
 
-
-
 //_____________________________________________________________________________
-void RooBinning::setRange(Double_t xlo, Double_t xhi) 
+void RooBinning::setRange(Double_t xlo, Double_t xhi)
 {
   // Change the defined range associated with this binning.
   // Bins that lie outside the new range [xlo,xhi] will not be
   // removed, but will be 'inactive', i.e. the new 0 bin will
   // be the first bin with an upper boundarie > xlo
-
-  if (xlo>xhi) {
-    coutE(InputArguments) << "RooUniformBinning::setRange: ERROR low bound > high bound" << endl ;
-    return ;
-  }
-  
-  // Remove previous boundaries 
-  
-  for (set<Double_t>::iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ;) {    
-    if ((*iter == _xlo && _ownBoundLo) || (*iter == _xhi && _ownBoundHi)) {
-      _boundaries.erase(iter++) ;
-    } else {
-      ++iter ;
-    }
-  }
-
-  // Insert boundaries at range delimiter, if necessary 
-  _ownBoundLo = kFALSE ;
-  _ownBoundHi = kFALSE ;
-  if (!hasBoundary(xlo)) {
-    addBoundary(xlo) ;
-    _ownBoundLo = kTRUE ;
+  if (xlo > xhi) {
+    coutE(InputArguments) << "RooBinning::setRange: ERROR low bound > high bound" << endl;
+    return;
   }
-  if (!hasBoundary(xhi)) {
-    addBoundary(xhi) ;
-    _ownBoundHi = kTRUE ;
-  }
-
-  _xlo = xlo ;
-  _xhi = xhi ;
-  
-  // Count number of bins with new range 
-  updateBinCount() ;
+  // Remove previous boundaries
+  if (_ownBoundLo) removeBoundary(_xlo);
+  if (_ownBoundHi) removeBoundary(_xhi);
+  // Insert boundaries at range delimiter, if necessary
+  _ownBoundLo = addBoundary(xlo);
+  _ownBoundHi = addBoundary(xhi);
+  _xlo = xlo, _xhi = xhi;
+  // Count number of bins with new range
+  updateBinCount();
 }
 
-
-
-
 //_____________________________________________________________________________
 void RooBinning::updateBinCount()
 {
   // Update the internal bin counter
-
-  Int_t i(-1) ;
-  for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {    
-    if (*iter>=_xlo && *iter <=_xhi) {
-      i++ ;
-    }
+  if (_boundaries.size() <= 1) {
+      _nbins = -1;
+      return;
   }
-  _nbins = i ;
+  _blo = rawBinNumber(_xlo);
+  std::vector<Double_t>::const_iterator it = std::lower_bound(
+      _boundaries.begin(), _boundaries.end(), _xhi);
+  if (_boundaries.begin() != it && (_boundaries.end() == it || _xhi < *it)) --it;
+  const Int_t bhi = it - _boundaries.begin();
+  _nbins = bhi - _blo;
 }
 
-
-
 //_____________________________________________________________________________
-Bool_t RooBinning::binEdges(Int_t bin, Double_t& xlo, Double_t& xhi) const 
+Bool_t RooBinning::binEdges(Int_t bin, Double_t& xlo, Double_t& xhi) const
 {
   // Return upper and lower bound of bin 'bin'. If the return value
   // is true an error occurred
-
-  if (bin<0 || bin>= _nbins) {
-    coutE(InputArguments) << "RooBinning::binEdges ERROR: bin number must be in range (0," << _nbins << ")" << endl ; 
-    return kTRUE ;
+  if (0 > bin || bin >= _nbins) {
+    coutE(InputArguments) << "RooBinning::binEdges ERROR: bin number must be in range (0," << _nbins << ")" << endl;
+    return kTRUE;
   }
-  
-  // Determine sequential bin number for given value
-  Int_t n(0) ;
-  for (set<Double_t>::const_iterator iter = _boundaries.begin() ; iter!=_boundaries.end() ; ++iter) {    
-
-    if (n==bin && *iter>=_xlo) {
-      xlo = *iter ;
-      iter++ ;
-      xhi = *iter ;
-      return kFALSE ;
-    }
-
-    // Only increment counter in valid range
-    if (*iter>= _xlo && n<_nbins-1) n++ ;
-  }
-
-  return kTRUE ;
+  xlo = _boundaries[bin + _blo], xhi = _boundaries[bin + _blo + 1];
+  return kFALSE;
 }
 
-
-
 //_____________________________________________________________________________
-Double_t RooBinning::binCenter(Int_t bin) const 
+Double_t RooBinning::binCenter(Int_t bin) const
 {
   // Return the position of the center of bin 'bin'
 
-  Double_t xlo,xhi ;
-  if (binEdges(bin,xlo,xhi)) return 0 ;
-  return (xlo+xhi)/2 ;
+  Double_t xlo, xhi;
+  if (binEdges(bin, xlo, xhi)) return 0;
+  return 0.5 * (xlo + xhi);
 }
 
-
-
 //_____________________________________________________________________________
-Double_t RooBinning::binWidth(Int_t bin) const 
+Double_t RooBinning::binWidth(Int_t bin) const
 {
   // Return the width of the requested bin
 
-  Double_t xlo,xhi ;
-  if (binEdges(bin,xlo,xhi)) return 0 ;
-  return (xhi-xlo);
+  Double_t xlo, xhi;
+  if (binEdges(bin, xlo, xhi)) return 0;
+  return (xhi - xlo);
 }
 
-
-
 //_____________________________________________________________________________
-Double_t RooBinning::binLow(Int_t bin) const 
+Double_t RooBinning::binLow(Int_t bin) const
 {
   // Return the lower bound of the requested bin
 
-  Double_t xlo,xhi ;
-  if (binEdges(bin,xlo,xhi)) return 0 ;
-  return xlo ;
+  Double_t xlo, xhi;
+  if (binEdges(bin, xlo, xhi)) return 0;
+  return xlo;
 }
 
-
-
 //_____________________________________________________________________________
-Double_t RooBinning::binHigh(Int_t bin) const  
+Double_t RooBinning::binHigh(Int_t bin) const
 {
   // Return the upper bound of the requested bin
 
-  Double_t xlo,xhi ;
-  if (binEdges(bin,xlo,xhi)) return  0 ;
-  return xhi ;
+  Double_t xlo, xhi;
+  if (binEdges(bin, xlo, xhi)) return  0;
+  return xhi;
 }
 
-
-
 //______________________________________________________________________________
 void RooBinning::Streamer(TBuffer &R__b)
 {
@@ -418,31 +310,45 @@ void RooBinning::Streamer(TBuffer &R__b)
 
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
-     if (R__v>1) {
-       R__b.ReadClassBuffer(RooBinning::Class(),this,R__v,R__s,R__c);
-     } else {
-       RooAbsBinning::Streamer(R__b);
-       R__b >> _xlo;
-       R__b >> _xhi;
-       R__b >> _ownBoundLo;
-       R__b >> _ownBoundHi;
-       R__b >> _nbins;
-       
-       // Convert TList to set<double>
-       TList boundaries ;
-       boundaries.Streamer(R__b);
-       TIterator* iter = boundaries.MakeIterator() ;
-       RooDouble* elem ;
-       while((elem=(RooDouble*)iter->Next())) {
-	 _boundaries.insert(*elem) ;
-       }
-       delete iter ;
-       
-       R__b.CheckByteCount(R__s, R__c, RooBinning::IsA());
+     switch (R__v) {
+       case 3:
+	 // current version - fallthrough intended
+       case 2:
+	 // older version with std::set<Double_t> instead of
+	 // std::vector<Double_t>, apparently ROOT is clever enough to not care
+	 // about set vs vector
+	 R__b.ReadClassBuffer(RooBinning::Class(), this, R__v, R__s, R__c);
+	 break;
+       case 1:
+	 {
+	   RooAbsBinning::Streamer(R__b);
+	   R__b >> _xlo;
+	   R__b >> _xhi;
+	   R__b >> _ownBoundLo;
+	   R__b >> _ownBoundHi;
+	   R__b >> _nbins;
+
+	   _boundaries.clear();
+	   // Convert TList to std::vector<Double_t>
+	   TList tmp;
+	   tmp.Streamer(R__b);
+	   _boundaries.reserve(tmp.GetSize());
+	   TIterator* it = tmp.MakeIterator();
+	   for (RooDouble* el = (RooDouble*) it->Next(); el;
+	       el = (RooDouble*) it->Next()) _boundaries.push_back(*el);
+	   delete it;
+	 }
+	 R__b.CheckByteCount(R__s, R__c, RooBinning::IsA());
+	 break;
+       default:
+	 throw std::string("Unknown class version!");
+     }
+     if (_boundaries.size() > 2) {
+       std::sort(_boundaries.begin(), _boundaries.end());
+       _boundaries.erase(std::unique(_boundaries.begin(), _boundaries.end()),
+	   _boundaries.end());
      }
    } else {
      R__b.WriteClassBuffer(RooBinning::Class(),this);
    }
 }
-
-
diff --git a/roofit/roofitcore/src/RooChi2Var.cxx b/roofit/roofitcore/src/RooChi2Var.cxx
index 1c4c847..eb8a6b3 100644
--- a/roofit/roofitcore/src/RooChi2Var.cxx
+++ b/roofit/roofitcore/src/RooChi2Var.cxx
@@ -273,6 +273,7 @@ Double_t RooChi2Var::evaluatePartition(Int_t firstEvent, Int_t lastEvent, Int_t
     result = t;
   }
     
+  _evalCarry = carry;
   return result ;
 }
 
diff --git a/roofit/roofitcore/src/RooComplex.cxx b/roofit/roofitcore/src/RooComplex.cxx
index 957c6ca..f6f02c9 100644
--- a/roofit/roofitcore/src/RooComplex.cxx
+++ b/roofit/roofitcore/src/RooComplex.cxx
@@ -23,7 +23,7 @@
 
 #include "RooFit.h"
 
-#include "RooComplex.h"
+#define ROO_COMPLEX_CXX
 #include "RooComplex.h"
 #include "Riostream.h"
 #include <iomanip>
@@ -32,6 +32,14 @@ using namespace std;
 
 ClassImp(RooComplex)
 
+void RooComplex::warn() const
+{
+    static int nwarns = 0;
+    if (nwarns < 1<<12) {
+	cout << "[#0] WARN: RooComplex is deprecated. Please use std::complex<Double_t> in your code instead." << std::endl;
+	++nwarns;
+    }
+}
 
 //_____________________________________________________________________________
 void RooComplex::Print() const {
diff --git a/roofit/roofitcore/src/RooMath.cxx b/roofit/roofitcore/src/RooMath.cxx
index 1f8199a..21c6c72 100644
--- a/roofit/roofitcore/src/RooMath.cxx
+++ b/roofit/roofitcore/src/RooMath.cxx
@@ -27,13 +27,8 @@
 #include "RooFit.h"
 
 #include "RooMath.h"
-#include "RooMath.h"
-#include "TMath.h"
-#include <math.h>
 #include "Riostream.h"
 #include "RooMsgService.h"
-#include "RooSentinel.h"
-#include "TSystem.h"
 
 using namespace std;
 
@@ -109,7 +104,7 @@ namespace faddeeva_impl {
 #endif
     }
 
-    template <class T, unsigned N, unsigned NTAYLOR>
+    template <class T, unsigned N, unsigned NTAYLOR, unsigned NCF>
     static inline std::complex<T> faddeeva_smabmq_impl(
 	    T zre, T zim, const T tm,
 	    const T (&a)[N], const T (&npi)[N],
@@ -130,7 +125,7 @@ namespace faddeeva_impl {
 		// we're in the interesting range of the real axis as well...
 		// deal with Re(z) < 0 so we only need N different Taylor
 		// expansions; use w(-x+iy) = conj(w(x+iy))
-		const bool negrez = zre < 0.;
+		const bool negrez = zre < T(0);
 		// figure out closest singularity
 		const int nsing = int(std::abs(dnsing) + T(1) / T(2));
 		// and calculate just how far we are from it
@@ -158,17 +153,41 @@ namespace faddeeva_impl {
 	}
 	// negative Im(z) is treated by calculating for -z, and using the
 	// symmetry properties of erfc(z)
-	const bool negimz = zim < 0.;
+	const bool negimz = zim < T(0);
 	if (negimz) {
 	    zre = -zre;
 	    zim = -zim;
 	}
+        const T znorm = zre * zre + zim2;
+	if (znorm > tm * tm) {
+	    // use continued fraction approximation for |z| large
+	    const T isqrtpi = 5.64189583547756287e-01;
+	    const T z2re = (zre + zim) * (zre - zim);
+	    const T z2im = T(2) * zre * zim;
+	    T cfre = T(1), cfim = T(0), cfnorm = T(1);
+	    for (unsigned k = NCF; k; --k) {
+		cfre = +(T(k) / T(2)) * cfre / cfnorm;
+		cfim = -(T(k) / T(2)) * cfim / cfnorm;
+		if (k & 1) cfre -= z2re, cfim -= z2im;
+		else cfre += T(1);
+		cfnorm = cfre * cfre + cfim * cfim;
+	    }
+	    T sumre =  (zim * cfre - zre * cfim) * isqrtpi / cfnorm;
+	    T sumim = -(zre * cfre + zim * cfim) * isqrtpi / cfnorm;
+	    if (negimz) {
+		// use erfc(-z) = 2 - erfc(z) to get good accuracy for
+		// Im(z) < 0: 2 / exp(z^2) - w(z)
+		T ez2re = -z2re, ez2im = -z2im;
+		faddeeva_impl::cexp(ez2re, ez2im);
+		return std::complex<T>(T(2) * ez2re - sumre,
+			T(2) * ez2im - sumim);
+	    } else {
+		return std::complex<T>(sumre, sumim);
+	    }
+	}
 	const T twosqrtpi = 3.54490770181103205e+00;
 	const T tmzre = tm * zre, tmzim = tm * zim;
 	// calculate exp(i tm z)
-	/*const T ere = std::exp(-tmzim);
-	const T eitmzreref = ere * std::cos(tmzre);
-	const T eitmzimref = ere * std::sin(tmzre);*/
 	T eitmzre = -tmzim, eitmzim = tmzre;
 	faddeeva_impl::cexp(eitmzre, eitmzim);
 	// form 1 +/- exp (i tm z)
@@ -197,7 +216,6 @@ namespace faddeeva_impl {
 	defined(__OPTIMIZE_SIZE__) || defined(__INTEL_COMPILER) || \
 	defined(__clang__) || defined(__OPEN64__) || \
 	defined(__PATHSCALE__) || !defined(__GNUC__)
-        const T znorm = zre * zre + zim2;
         T sumre = (-a[0] / znorm) * (numerarr[0] * zre + numerarr[1] * zim);
         T sumim = (-a[0] / znorm) * (numerarr[1] * zre - numerarr[0] * zim);
         for (unsigned i = 0; i < N; ++i) {
@@ -234,7 +252,6 @@ namespace faddeeva_impl {
 	    tmp[2 * (N - 1) + 0] = -f * (numertmz[0] * wk + numertmz[1] * reimtmzm2);
 	    tmp[2 * (N - 1) + 1] = -f * (numertmz[1] * wk - numertmz[0] * reimtmzm2);
 	}
-	const T znorm = zre * zre + zim2;
 	T sumre = (-a[0] / znorm) * (numerarr[0] * zre + numerarr[1] * zim);
 	T sumim = (-a[0] / znorm) * (numerarr[1] * zre - numerarr[0] * zim);
 	for (unsigned i = 0; i < N; ++i) {
@@ -247,13 +264,12 @@ namespace faddeeva_impl {
 	if (negimz) {
 	    // use erfc(-z) = 2 - erfc(z) to get good accuracy for
 	    // Im(z) < 0: 2 / exp(z^2) - w(z)
-	    const T z2im = T(2) * zre * zim;
-	    const T z2re = (zre + zim) * (zre - zim);
+	    const T z2im = -T(2) * zre * zim;
+	    const T z2re = -(zre + zim) * (zre - zim);
 	    T ez2re = z2re, ez2im = z2im;
 	    faddeeva_impl::cexp(ez2re, ez2im);
-	    const T twoez2norm = T(2) / (ez2re * ez2re + ez2im * ez2im);
-	    return std::complex<T>(twoez2norm * ez2re + sumim / twosqrtpi,
-		    -twoez2norm * ez2im - sumre / twosqrtpi);
+	    return std::complex<T>(T(2) * ez2re + sumim / twosqrtpi,
+		    T(2) * ez2im - sumre / twosqrtpi);
 	} else {
 	    return std::complex<T>(-sumim / twosqrtpi, sumre / twosqrtpi);
 	}
@@ -514,14 +530,14 @@ namespace faddeeva_impl {
 
 std::complex<double> RooMath::faddeeva(std::complex<double> z)
 {
-    return faddeeva_impl::faddeeva_smabmq_impl<double, 24, 6>(
+    return faddeeva_impl::faddeeva_smabmq_impl<double, 24, 6, 9>(
 	    z.real(), z.imag(), 12., faddeeva_impl::a24,
 	    faddeeva_impl::npi24, faddeeva_impl::taylorarr24);
 }
 
 std::complex<double> RooMath::faddeeva_fast(std::complex<double> z)
 {
-    return faddeeva_impl::faddeeva_smabmq_impl<double, 11, 3>(
+    return faddeeva_impl::faddeeva_smabmq_impl<double, 11, 3, 3>(
 	    z.real(), z.imag(), 8., faddeeva_impl::a11,
 	    faddeeva_impl::npi11, faddeeva_impl::taylorarr11);
 }
@@ -575,59 +591,6 @@ std::complex<double> RooMath::erf_fast(const std::complex<double> z)
 }
 
 
-RooComplex RooMath::FastComplexErrFunc(const RooComplex& z)
-{
-  const std::complex<double> w = faddeeva_fast(std::complex<double>(z.re(), z.im()));
-  return RooComplex(w.real(), w.imag());
-}
-  
-Double_t RooMath::FastComplexErrFuncRe(const RooComplex& z) 
-{ return faddeeva_fast(std::complex<double>(z.re(), z.im())).real(); }
-
-Double_t RooMath::FastComplexErrFuncIm(const RooComplex& z) 
-{ return faddeeva_fast(std::complex<double>(z.re(), z.im())).imag(); }
-
-void RooMath::cacheCERF(Bool_t /* flag */) 
-{ }
-
-
-RooComplex RooMath::ComplexErrFunc(Double_t re, Double_t im)
-{
-  const std::complex<double> z = faddeeva(std::complex<double>(re, im));
-  return RooComplex(z.real(),z.imag());
-}
-
-RooComplex RooMath::ComplexErrFunc(const RooComplex& Z) {
-  const std::complex<double> w = faddeeva(std::complex<double>(Z.re(), Z.im()));
-  return RooComplex(w.real(), w.imag());
-}
-
-
-
-void RooMath::initFastCERF(
-	Int_t /* reBins */, Double_t /* reMin */, Double_t /* reMax */,
-	Int_t /* imBins */, Double_t /* imMin */, Double_t /* imMax */)
-{
-}
-
-
-
-void RooMath::cleanup()
-{ }
-
-
-RooComplex RooMath::ITPComplexErrFunc(const RooComplex& z, Int_t /* nOrder */)
-{
-  const std::complex<double> w = faddeeva_fast(std::complex<double>(z.re(), z.im()));
-  return RooComplex(w.real(), w.imag());
-}
-
-Double_t RooMath::ITPComplexErrFuncRe(const RooComplex& z, Int_t /* nOrder */)
-{ return faddeeva_fast(std::complex<double>(z.re(), z.im())).real(); }
-
-Double_t RooMath::ITPComplexErrFuncIm(const RooComplex& z, Int_t /* nOrder */)
-{ return faddeeva_fast(std::complex<double>(z.re(), z.im())).imag(); }
-
 Double_t RooMath::interpolate(Double_t ya[], Int_t n, Double_t x) 
 {
   // Interpolate array 'ya' with 'n' elements for 'x' (between 0 and 'n'-1)
@@ -707,13 +670,21 @@ Double_t RooMath::interpolate(Double_t xa[], Double_t ya[], Int_t n, Double_t x)
 }
 
 
-
-Double_t RooMath::erf(Double_t x) 
-{
-  return TMath::Erf(x) ;
-}
-
-Double_t RooMath::erfc(Double_t x)
+#include <map>
+void RooMath::warn(const char* oldfun, const char* newfun)
 {
-  return TMath::Erfc(x) ;
+    static std::map<const char*, int> nwarn;
+    if (nwarn[oldfun] < 1<<12) {
+	++nwarn[oldfun];
+	if (newfun) {
+	    std::cout << "[#0] WARN: RooMath::" << oldfun <<
+		" is deprecated, please use " <<
+		newfun << " instead." << std::endl;
+	} else {
+	    std::cout << "[#0] WARN: RooMath::" << oldfun <<
+		" is deprecated, and no longer needed, "
+		"you can remove the call to " <<
+		oldfun << " entirely." << std::endl;
+	}
+    }
 }
diff --git a/roofit/roofitcore/src/RooMinimizer.cxx b/roofit/roofitcore/src/RooMinimizer.cxx
index 6547422..ffa2507 100644
--- a/roofit/roofitcore/src/RooMinimizer.cxx
+++ b/roofit/roofitcore/src/RooMinimizer.cxx
@@ -186,6 +186,28 @@ void RooMinimizer::setStrategy(Int_t istrat)
 
 
 //_____________________________________________________________________________
+void RooMinimizer::setMaxIterations(Int_t n) 
+{
+  // Change maximum number of MINUIT iterations 
+  // (RooMinimizer default 500 * #parameters)
+  _theFitter->Config().MinimizerOptions().SetMaxIterations(n);
+}
+
+
+
+
+//_____________________________________________________________________________
+void RooMinimizer::setMaxFunctionCalls(Int_t n) 
+{
+  // Change maximum number of likelihood function calss from MINUIT
+  // (RooMinimizer default 500 * #parameters)
+  _theFitter->Config().MinimizerOptions().SetMaxFunctionCalls(n);
+}
+
+
+
+
+//_____________________________________________________________________________
 void RooMinimizer::setErrorLevel(Double_t level)
 {
   // Set the level for MINUIT error analysis to the given
@@ -230,6 +252,23 @@ void RooMinimizer::setMinimizerType(const char* type)
 
 
 //_____________________________________________________________________________
+ROOT::Fit::Fitter* RooMinimizer::fitter()
+{
+  // Return underlying ROOT fitter object 
+  return _theFitter ;
+}
+
+
+//_____________________________________________________________________________
+const ROOT::Fit::Fitter* RooMinimizer::fitter() const 
+{
+  // Return underlying ROOT fitter object 
+  return _theFitter ;
+}
+
+
+
+//_____________________________________________________________________________
 RooFitResult* RooMinimizer::fit(const char* options)
 {
   // Parse traditional RooAbsPdf::fitTo driver options
diff --git a/roofit/roofitcore/src/RooNLLVar.cxx b/roofit/roofitcore/src/RooNLLVar.cxx
index dce874b..941fd1d 100644
--- a/roofit/roofitcore/src/RooNLLVar.cxx
+++ b/roofit/roofitcore/src/RooNLLVar.cxx
@@ -26,6 +26,8 @@
 // END_HTML
 //
 
+#include <algorithm>
+
 #include "RooFit.h"
 #include "Riostream.h"
 
@@ -84,7 +86,10 @@ RooNLLVar::RooNLLVar(const char *name, const char* title, RooAbsPdf& pdf, RooAbs
   _extended = pc.getInt("extended") ;
   _weightSq = kFALSE ;
   _first = kTRUE ;
-  _offset = 0 ;
+  _offset = 0.;
+  _offsetCarry = 0.;
+  _offsetSaveW2 = 0.;
+  _offsetCarrySaveW2 = 0.;
 
 }
 
@@ -97,7 +102,7 @@ RooNLLVar::RooNLLVar(const char *name, const char *title, RooAbsPdf& pdf, RooAbs
   RooAbsOptTestStatistic(name,title,pdf,indata,RooArgSet(),rangeName,addCoefRangeName,nCPU,interleave,verbose,splitRange,cloneData),
   _extended(extended),
   _weightSq(kFALSE),
-  _first(kTRUE)
+  _first(kTRUE), _offsetSaveW2(0.), _offsetCarrySaveW2(0.)
 {
   // Construct likelihood from given p.d.f and (binned or unbinned dataset)
   // For internal use.
@@ -113,7 +118,7 @@ RooNLLVar::RooNLLVar(const char *name, const char *title, RooAbsPdf& pdf, RooAbs
   RooAbsOptTestStatistic(name,title,pdf,indata,projDeps,rangeName,addCoefRangeName,nCPU,interleave,verbose,splitRange,cloneData),
   _extended(extended),
   _weightSq(kFALSE),
-  _first(kTRUE)
+  _first(kTRUE), _offsetSaveW2(0.), _offsetCarrySaveW2(0.)
 {
   // Construct likelihood from given p.d.f and (binned or unbinned dataset)
   // For internal use.  
@@ -128,8 +133,8 @@ RooNLLVar::RooNLLVar(const RooNLLVar& other, const char* name) :
   RooAbsOptTestStatistic(other,name),
   _extended(other._extended),
   _weightSq(other._weightSq),
-  _first(kTRUE)
-{
+  _first(kTRUE), _offsetSaveW2(other._offsetSaveW2),
+  _offsetCarrySaveW2(other._offsetCarrySaveW2) {
   // Copy constructor
 }
 
@@ -149,21 +154,18 @@ RooNLLVar::~RooNLLVar()
 void RooNLLVar::applyWeightSquared(Bool_t flag) 
 { 
   if (_gofOpMode==Slave) {
-    _weightSq = flag ; 
-    setValueDirty() ; 
-
+    if (flag != _weightSq) {
+      _weightSq = flag;
+      std::swap(_offset, _offsetSaveW2);
+      std::swap(_offsetCarry, _offsetCarrySaveW2);
+    }
+    setValueDirty();
   } else if ( _gofOpMode==MPMaster) {
-
-    for (Int_t i=0 ; i<_nCPU ; i++) {
-      _mpfeArray[i]->applyNLLWeightSquared(flag) ;
-    }    
-
+    for (Int_t i=0 ; i<_nCPU ; i++)
+      _mpfeArray[i]->applyNLLWeightSquared(flag);
   } else if ( _gofOpMode==SimMaster) {
-
-    for (Int_t i=0 ; i<_nGof ; i++) {
-      ((RooNLLVar*)_gofArray[i])->applyWeightSquared(flag) ;
-    }
-
+    for (Int_t i=0 ; i<_nGof ; i++)
+      ((RooNLLVar*)_gofArray[i])->applyWeightSquared(flag);
   }
 } 
 
@@ -282,6 +284,7 @@ Double_t RooNLLVar::evaluatePartition(Int_t firstEvent, Int_t lastEvent, Int_t s
     result = t;
   }
     
+  _evalCarry = carry;
   return result ;
 }
 
diff --git a/roofit/roofitcore/src/RooRealMPFE.cxx b/roofit/roofitcore/src/RooRealMPFE.cxx
index fb84e3d..6066f55 100644
--- a/roofit/roofitcore/src/RooRealMPFE.cxx
+++ b/roofit/roofitcore/src/RooRealMPFE.cxx
@@ -45,12 +45,10 @@
 #include "RooFit.h"
 
 #ifndef _WIN32
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
+#include "BidirMMapPipe.h"
 #endif
 
-#include <errno.h>
+#include <cstdlib>
 #include <sstream>
 #include "RooRealMPFE.h"
 #include "RooArgSet.h"
@@ -67,6 +65,7 @@
 RooMPSentinel RooRealMPFE::_sentinel ;
 
 using namespace std;
+using namespace RooFit;
 
 ClassImp(RooRealMPFE)
   ;
@@ -83,9 +82,9 @@ RooRealMPFE::RooRealMPFE(const char *name, const char *title, RooAbsReal& arg, B
   _verboseServer(kFALSE),
   _inlineMode(calcInline),
   _remoteEvalErrorLoggingState(RooAbsReal::PrintErrors),
-  _pid(0),
+  _pipe(0),
   _updateMaster(0),
-  _retrieveDispatched(kFALSE)
+  _retrieveDispatched(kFALSE), _evalCarry(0.)
 {  
   // Construct front-end object for object 'arg' whose evaluation will be calculated
   // asynchronously in a separate process. If calcInline is true the value of 'arg'
@@ -112,9 +111,9 @@ RooRealMPFE::RooRealMPFE(const RooRealMPFE& other, const char* name) :
   _inlineMode(other._inlineMode),
   _forceCalc(other._forceCalc),
   _remoteEvalErrorLoggingState(other._remoteEvalErrorLoggingState),
-  _pid(0),
+  _pipe(0),
   _updateMaster(0),
-  _retrieveDispatched(kFALSE)
+  _retrieveDispatched(kFALSE), _evalCarry(other._evalCarry)
 {
   // Copy constructor. Initializes in clean state so that upon eval
   // this instance will create its own server processes
@@ -130,11 +129,8 @@ RooRealMPFE::~RooRealMPFE()
 {
   // Destructor
 
-  if (_state==Client) {
-    standby() ;
-  }
-  _sentinel.remove(*this) ;
-
+  if (_state==Client) standby();
+  _sentinel.remove(*this);
 }
 
 
@@ -166,7 +162,16 @@ void RooRealMPFE::initVars()
   //delete ncVars ;
 }
 
-
+Double_t RooRealMPFE::getCarry() const
+{
+  if (_inlineMode) {
+    RooAbsTestStatistic* tmp = dynamic_cast<RooAbsTestStatistic*>(_arg.absArg());
+    if (tmp) return tmp->getCarry();
+    else return 0.;
+  } else {
+    return _evalCarry;
+  }
+}
 
 //_____________________________________________________________________________
 void RooRealMPFE::initialize() 
@@ -181,45 +186,32 @@ void RooRealMPFE::initialize()
   }
 
 #ifndef _WIN32
-  // Fork server process and setup IPC
-  
-  // Make client/server pipes
-  UInt_t tmp1 = pipe(_pipeToClient) ;
-  UInt_t tmp2 = pipe(_pipeToServer) ;
-  if (tmp1 || tmp2) perror("pipe") ;
-  
   // Clear eval error log prior to forking
   // to avoid confusions...
   clearEvalErrorLog() ;
-
-  _pid = fork() ;
-
-  if (_pid==0) {
-
+  // Fork server process and setup IPC
+  _pipe = new BidirMMapPipe();
+  
+  if (_pipe->isChild()) {
     // Start server loop 
     RooTrace::callgrind_zero() ;
     _state = Server ;
-    serverLoop() ;
+    serverLoop();
 
     // Kill server at end of service
-    coutI(Minimization) << "RooRealMPFE::initialize(" << GetName() 
-			<< ") server process terminating" << endl ;
+    if (_verboseServer) ccoutD(Minimization) << "RooRealMPFE::initialize(" <<
+	GetName() << ") server process terminating" << endl ;
 
-    delete _arg.absArg() ;
+    delete _arg.absArg();
+    delete _pipe;
     _exit(0) ;
-
-  } else if (_pid>0) {
- 
+  } else {
     // Client process - fork successul
-    coutI(Minimization) << "RooRealMPFE::initialize(" << GetName() 
-			<< ") successfully forked server process " << _pid << endl ;
+    if (_verboseClient) ccoutD(Minimization) << "RooRealMPFE::initialize(" <<
+	GetName() << ") successfully forked server process " <<
+	    _pipe->pidOtherEnd() << endl ;
     _state = Client ;
     _calcInProgress = kFALSE ;
-
-  } else {
-    // Client process - fork failed    
-    coutE(Minimization) << "RooRealMPFE::initialize(" << GetName() << ") ERROR fork() failed" << endl ; 
-    _state = Inline ;
   }
 #endif // _WIN32
 }
@@ -233,8 +225,7 @@ void RooRealMPFE::serverLoop()
   // only when an incoming TERMINATE message is received.
 
 #ifndef _WIN32
-  Bool_t doLoop(kTRUE) ;
-  Message msg ;
+  int msg ;
 
   Int_t idx, index, numErrors ;
   Double_t value ;
@@ -242,17 +233,20 @@ void RooRealMPFE::serverLoop()
   
   clearEvalErrorLog() ;
 
-  while(doLoop) {
-    ssize_t n = read(_pipeToServer[0],&msg,sizeof(msg)) ;
-    if (n<0&&_verboseServer) perror("read") ;
+  while(*_pipe && !_pipe->eof()) {
+    *_pipe >> msg;
+    if (Terminate == msg) {
+      if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
+			       << ") IPC fromClient> Terminate" << endl; 
+      // send terminate acknowledged to client
+      *_pipe << msg << BidirMMapPipe::flush;
+      break;
+    }
 
     switch (msg) {
     case SendReal:
       {
-	UInt_t tmp1 = read(_pipeToServer[0],&idx,sizeof(Int_t)) ;
-	UInt_t tmp2 = read(_pipeToServer[0],&value,sizeof(Double_t)) ;      
-	UInt_t tmp3 = read(_pipeToServer[0],&isConst,sizeof(Bool_t)) ;      
-	if (tmp1+tmp2+tmp3<sizeof(Int_t)+sizeof(Double_t)+sizeof(Bool_t)) perror("read") ;
+	*_pipe >> idx >> value >> isConst;
 	if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 				 << ") IPC fromClient> SendReal [" << idx << "]=" << value << endl ;       
 	RooRealVar* rvar = (RooRealVar*)_vars.at(idx) ;
@@ -265,9 +259,7 @@ void RooRealMPFE::serverLoop()
 
     case SendCat:
       {
-	UInt_t tmp1 = read(_pipeToServer[0],&idx,sizeof(Int_t)) ;
-	UInt_t tmp2 = read(_pipeToServer[0],&index,sizeof(Int_t)) ;      
-	if (tmp1+tmp2<sizeof(Int_t)+sizeof(Int_t)) perror("read") ;
+	*_pipe >> idx >> index;
 	if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 				 << ") IPC fromClient> SendCat [" << idx << "]=" << index << endl ; 
 	((RooCategory*)_vars.at(idx))->setIndex(index) ;
@@ -293,45 +285,59 @@ void RooRealMPFE::serverLoop()
       {
 	if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 				 << ") IPC fromClient> Retrieve" << endl ; 
-	msg = ReturnValue ;
-	numErrors = numEvalErrors() ;
-	if (1) {
-	  char sendBuf[50] ;
-	  memcpy(sendBuf,&msg,sizeof(Message)) ;
-	  memcpy(sendBuf+sizeof(Message),&_value,sizeof(Double_t)) ;
-	  memcpy(sendBuf+sizeof(Message)+sizeof(Double_t),&numErrors,sizeof(Int_t)) ;
-	  UInt_t tmpx = write(_pipeToClient[1],sendBuf,sizeof(Message)+sizeof(Double_t)+sizeof(Int_t)) ;
-	  if (tmpx<sizeof(Message)+sizeof(Double_t)+sizeof(Int_t)) perror("write") ;	  
-	} else {
-	  UInt_t tmp1 = write(_pipeToClient[1],&msg,sizeof(Message)) ;
-	  UInt_t tmp2 = write(_pipeToClient[1],&_value,sizeof(Double_t)) ;
-	  UInt_t tmp3 = write(_pipeToClient[1],&numErrors,sizeof(Int_t)) ;
-	  if (tmp1+tmp2+tmp3<sizeof(Message)+sizeof(Double_t)+sizeof(Int_t)) perror("write") ;
-	}
+	msg = ReturnValue;
+	numErrors = numEvalErrors();
+	*_pipe << msg << _value << getCarry() << numErrors;
 
 	if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 				 << ") IPC toClient> ReturnValue " << _value << " NumError " << numErrors << endl ; 
+
+	if (numErrors) {
+	  // Loop over errors
+	  std::string objidstr;
+	  {
+	    ostringstream oss2;
+	    // Format string with object identity as this cannot be evaluated on the other side
+	    oss2 << "PID" << gSystem->GetPid() << "/";
+	    printStream(oss2,kName|kClassName|kArgs,kInline);
+	    objidstr = oss2.str();
+	  }
+	  std::map<const RooAbsArg*,pair<string,list<EvalError> > >::const_iterator iter = evalErrorIter();
+	  const RooAbsArg* ptr = 0;
+	  for (int i = 0; i < numEvalErrorItems(); ++i) {
+	    list<EvalError>::const_iterator iter2 = iter->second.second.begin();
+	    for (; iter->second.second.end() != iter2; ++iter2) {
+	      ptr = iter->first;
+	      *_pipe << ptr << iter2->_msg << iter2->_srvval << objidstr;
+	      if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
+		<< ") IPC toClient> sending error log Arg " << iter->first << " Msg " << iter2->_msg << endl ; 
+	    }
+	  } 
+	  // let other end know that we're done with the list of errors
+	  ptr = 0;
+	  *_pipe << ptr;
+	  // Clear error list on local side
+	  clearEvalErrorLog();
+	}
+	*_pipe << BidirMMapPipe::flush;
       }
-      break ;
+      break;
 
     case ConstOpt:
       {
-	ConstOpCode code ; 
 	Bool_t doTrack ;
-	UInt_t tmp1 = read(_pipeToServer[0],&code,sizeof(ConstOpCode)) ;
-	UInt_t tmp2 = read(_pipeToServer[0],&doTrack,sizeof(Bool_t)) ;
-	if ((tmp1+tmp2)<sizeof(ConstOpCode)) perror("read") ;
+	int code;
+	*_pipe >> code >> doTrack;
 	if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 				 << ") IPC fromClient> ConstOpt " << code << " doTrack = " << (doTrack?"T":"F") << endl ; 
-	((RooAbsReal&)_arg.arg()).constOptimizeTestStatistic(code,doTrack) ;      
+	((RooAbsReal&)_arg.arg()).constOptimizeTestStatistic(static_cast<RooAbsArg::ConstOpCode>(code),doTrack) ;
 	break ;
       }
 
     case Verbose:
       {
       Bool_t flag ;
-      UInt_t tmp1 = read(_pipeToServer[0],&flag,sizeof(Bool_t)) ;
-      if (tmp1<sizeof(Bool_t)) perror("read") ;
+      *_pipe >> flag;
       if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 			       << ") IPC fromClient> Verbose " << (flag?1:0) << endl ; 
       _verboseServer = flag ;
@@ -342,8 +348,7 @@ void RooRealMPFE::serverLoop()
     case ApplyNLLW2:
       {
       Bool_t flag ;
-      UInt_t tmp1 = read(_pipeToServer[0],&flag,sizeof(Bool_t)) ;
-      if (tmp1<sizeof(Bool_t)) perror("read") ;
+      *_pipe >> flag;
       if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 			       << ") IPC fromClient> ApplyNLLW2 " << (flag?1:0) << endl ; 
       
@@ -355,8 +360,7 @@ void RooRealMPFE::serverLoop()
     case EnableOffset:
       {
       Bool_t flag ;
-      UInt_t tmp1 = read(_pipeToServer[0],&flag,sizeof(Bool_t)) ;
-      if (tmp1<sizeof(Bool_t)) perror("read") ;
+      *_pipe >> flag;
       if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 			       << ") IPC fromClient> EnableOffset " << (flag?1:0) << endl ; 
       
@@ -365,17 +369,11 @@ void RooRealMPFE::serverLoop()
       }
       break ;
 
-    case Terminate: 
-      if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
-			       << ") IPC fromClient> Terminate" << endl ; 
-      doLoop = kFALSE ;
-      break ;
-
     case LogEvalError:
       {
-	RooAbsReal::ErrorLoggingMode flag2 ;
-	UInt_t tmp1 = read(_pipeToServer[0],&flag2,sizeof(RooAbsReal::ErrorLoggingMode)) ;
-	if (tmp1<sizeof(RooAbsReal::ErrorLoggingMode)) perror("read") ;
+	int iflag2;
+	*_pipe >> iflag2;
+	RooAbsReal::ErrorLoggingMode flag2 = static_cast<RooAbsReal::ErrorLoggingMode>(iflag2);
 	RooAbsReal::setEvalErrorLoggingMode(flag2) ;
 	if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 				 << ") IPC fromClient> LogEvalError flag = " << flag2 << endl ;       
@@ -383,72 +381,6 @@ void RooRealMPFE::serverLoop()
       break ;
 
 
-    case RetrieveErrors:
-
-      if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
-			       << ") IPC fromClient> RetrieveErrors" << endl ; 
-
-      // Loop over errors
-      {
-	std::map<const RooAbsArg*,pair<string,list<EvalError> > >::const_iterator iter = evalErrorIter() ;
-	for (int i=0 ; i<numEvalErrorItems() ; i++) {
-	  list<EvalError>::const_iterator iter2 = iter->second.second.begin() ;
-	  for (;iter2!=iter->second.second.end();++iter2) {
-	    
-	    // Reply with SendError message
-	    msg = SendError ;
-	    UInt_t tmp1 = write(_pipeToClient[1],&msg,sizeof(Message)) ;
-	    UInt_t tmp2 = write(_pipeToClient[1],&iter->first,sizeof(RooAbsReal*)) ;
-	   
-	    UInt_t ntext = strlen(iter2->_msg) ;
-	    UInt_t tmp3 = write(_pipeToClient[1],&ntext,sizeof(Int_t)) ;
-	    UInt_t tmp4 = write(_pipeToClient[1],iter2->_msg,ntext+1) ;
-	    
-	    UInt_t ntext2 = strlen(iter2->_srvval) ;
-	    UInt_t tmp5 = write(_pipeToClient[1],&ntext2,sizeof(Int_t)) ;
-	    UInt_t tmp6 = write(_pipeToClient[1],iter2->_srvval,ntext2+1) ;
-
-	    // Format string with object identity as this cannot be evaluated on the other side
-	    ostringstream oss2 ;
-	    oss2 << "PID" << gSystem->GetPid() << "/" ;
-	    printStream(oss2,kName|kClassName|kArgs,kInline)  ;
-	    UInt_t ntext3 = strlen(oss2.str().c_str()) ;
-	    UInt_t tmp7(0),tmp8(0) ;
-	    if (ntext3>1023) {
-	      ntext3=1023 ;
-	      tmp7 = write(_pipeToClient[1],&ntext3,sizeof(Int_t)) ;
-	      char tmpbuf[1024] ;
-	      strncpy(tmpbuf,oss2.str().c_str(),1023) ;
-	      tmpbuf[1020]='.' ;
-	      tmpbuf[1021]='.' ;
-	      tmpbuf[1022]='.' ;
-	      tmpbuf[1023]=0 ;
-	      tmp8 = write(_pipeToClient[1],tmpbuf,ntext3+1) ;
-	    } else {
-	      tmp7 = write(_pipeToClient[1],&ntext3,sizeof(Int_t)) ;
-	      tmp8 = write(_pipeToClient[1],oss2.str().c_str(),ntext3+1) ;
-	    }
-
-	    if (tmp1+tmp2+tmp3+tmp4+tmp5+tmp6+tmp7+tmp8<
-		sizeof(Message)+sizeof(RooAbsReal*)+sizeof(Int_t)+ntext+1+sizeof(Int_t)+ntext2+1+sizeof(Int_t)+ntext3+1) 
-	      perror("write") ;
-
-	    	    
-	    if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
-				     << ") IPC toClient> SendError Arg " << iter->first << " Msg " << iter2->_msg << endl ; 
-	  }
-	}  
-	
-	RooAbsReal* null(0) ;
-	UInt_t tmp1 = write(_pipeToClient[1],&msg,sizeof(Message)) ;
-	UInt_t tmp2 = write(_pipeToClient[1],&null,sizeof(RooAbsReal*)) ;
-	if (tmp1+tmp2<sizeof(Message)+sizeof(RooAbsReal*)) perror("write") ;
-      
-      }
-      // Clear error list on local side
-      clearEvalErrorLog() ;           
-      break ;
-
     default:
       if (_verboseServer) cout << "RooRealMPFE::serverLoop(" << GetName() 
 			       << ") IPC fromClient> Unknown message (code = " << msg << ")" << endl ; 
@@ -519,24 +451,17 @@ void RooRealMPFE::calculate() const
 	
 	// send message to server
 	if (dynamic_cast<RooAbsReal*>(var)) {
-	  Message msg = SendReal ;
+	  int msg = SendReal ;
 	  Double_t val = ((RooAbsReal*)var)->getVal() ;
 	  Bool_t isC = var->isConstant() ;
-	  UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-	  UInt_t tmp2 = write(_pipeToServer[1],&i,sizeof(Int_t)) ;
-	  UInt_t tmp3 = write(_pipeToServer[1],&val,sizeof(Double_t)) ;
-	  UInt_t tmp4 = write(_pipeToServer[1],&isC,sizeof(Bool_t)) ;
-	  if (tmp1+tmp2+tmp3+tmp4<sizeof(Message)+sizeof(Int_t)+sizeof(Double_t)+sizeof(Bool_t)) perror("write") ;
+	  *_pipe << msg << i << val << isC;
 
 	  if (_verboseServer) cout << "RooRealMPFE::calculate(" << GetName() 
 				   << ") IPC toServer> SendReal [" << i << "]=" << val << (isC?" (Constant)":"") <<  endl ;
 	} else if (dynamic_cast<RooAbsCategory*>(var)) {
-	  Message msg = SendCat ;
+	  int msg = SendCat ;
 	  UInt_t idx = ((RooAbsCategory*)var)->getIndex() ;
-	  UInt_t tmp5 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-	  UInt_t tmp6 = write(_pipeToServer[1],&i,sizeof(Int_t)) ;
-	  UInt_t tmp7 = write(_pipeToServer[1],&idx,sizeof(Int_t)) ;	
-	  if (tmp5+tmp6+tmp7<sizeof(Message)+sizeof(Int_t)+sizeof(Int_t)) perror("write") ;
+	  *_pipe << msg << i << idx;
 	  if (_verboseServer) cout << "RooRealMPFE::calculate(" << GetName() 
 				   << ") IPC toServer> SendCat [" << i << "]=" << idx << endl ;
 	}
@@ -544,9 +469,8 @@ void RooRealMPFE::calculate() const
       i++ ;
     }
 
-    Message msg = hideOffset() ? Calculate : CalculateNoOffset;
-    UInt_t tmp8 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-    if (tmp8<sizeof(Message)) perror("write") ;
+    int msg = hideOffset() ? Calculate : CalculateNoOffset;
+    *_pipe << msg;
     if (_verboseServer) cout << "RooRealMPFE::calculate(" << GetName() 
 			     << ") IPC toServer> Calculate " << endl ;
 
@@ -555,12 +479,10 @@ void RooRealMPFE::calculate() const
     _calcInProgress = kTRUE ;
     _forceCalc = kFALSE ;
 
-    // Immediately dispatch retrieve request
     msg = Retrieve ;
-    UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(Message)) ;    
+    *_pipe << msg << BidirMMapPipe::flush;
     if (_verboseServer) cout << "RooRealMPFE::evaluate(" << GetName() 
 			     << ") IPC toServer> Retrieve " << endl ;    
-    if (tmp1<sizeof(Message)) perror("write") ;
     _retrieveDispatched = kTRUE ;        
 
   } else if (_state!=Inline) {
@@ -617,39 +539,34 @@ Double_t RooRealMPFE::evaluate() const
     return_value = _arg ; 
   } else if (_state==Client) {
 #ifndef _WIN32
-    Message msg ;
-    Double_t value ;
+    bool needflush = false;
+    int msg;
+    Double_t value;
 
     // If current error loggin state is not the same as remote state
     // update the remote state
     if (evalErrorLoggingMode() != _remoteEvalErrorLoggingState) {
       msg = LogEvalError ;
-      UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(Message)) ;    
       RooAbsReal::ErrorLoggingMode flag = evalErrorLoggingMode() ;
-      UInt_t tmp2 = write(_pipeToServer[1],&flag,sizeof(RooAbsReal::ErrorLoggingMode)) ;      
+      *_pipe << msg << flag;
+      needflush = true;
       _remoteEvalErrorLoggingState = evalErrorLoggingMode() ;
-      if (tmp1+tmp2<sizeof(Message)+sizeof(RooAbsReal::ErrorLoggingMode)) perror("write") ;
     }
 
     if (!_retrieveDispatched) {
       msg = Retrieve ;
-      UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(Message)) ;    
+      *_pipe << msg;
+      needflush = true;
       if (_verboseServer) cout << "RooRealMPFE::evaluate(" << GetName() 
 			       << ") IPC toServer> Retrieve " << endl ;    
-      if (tmp1<sizeof(Message)) perror("write") ;
     }
+    if (needflush) *_pipe << BidirMMapPipe::flush;
     _retrieveDispatched = kFALSE ;
 
 
-    Int_t numError ;
+    Int_t numError;
 
-    char recvbuf[50] ;
-    const UInt_t recv_msg_size = sizeof(Message) + sizeof(Double_t) + sizeof(Int_t) ;
-    UInt_t tmpx = read(_pipeToClient[0],recvbuf,recv_msg_size) ;
-    if (tmpx<recv_msg_size) perror("read") ;
-    memcpy(&msg,recvbuf,sizeof(Message)) ;
-    memcpy(&value,recvbuf+sizeof(Message),sizeof(Double_t)) ;
-    memcpy(&numError,recvbuf+sizeof(Message)+sizeof(Double_t),sizeof(Int_t)) ;
+    *_pipe >> msg >> value >> _evalCarry >> numError;
     
     if (msg!=ReturnValue) {
       cout << "RooRealMPFE::evaluate(" << GetName() 
@@ -661,53 +578,22 @@ Double_t RooRealMPFE::evaluate() const
 
     if (_verboseServer) cout << "RooRealMPFE::evaluate(" << GetName() 
 			     << ") IPC fromServer> NumErrors " << numError << endl ;
-    
-    // Retrieve remote errors and feed into local error queue
-    if (numError>0) {
-      //cout  << "MPFE: there are errors..."<< endl ;
-      msg=RetrieveErrors ;
-      UInt_t tmp5 = write(_pipeToServer[1],&msg,sizeof(Message)) ;    
-      if (tmp5<sizeof(Message)) perror("write") ;
-
-      if (_verboseServer) cout << "RooRealMPFE::evaluate(" << GetName() 
-			     << ") IPC toServer> RetrieveErrors " << endl ;    
-
-
-      while(true) {
-	RooAbsReal* ptr(0) ;
-	Int_t ntext1,ntext2,ntext3 ;
-	char msgbuf1[1024] ;
-	char msgbuf2[1024] ;
-	char msgbuf3[1024] ;
-	UInt_t tmp12= read(_pipeToClient[0],&msg,sizeof(Message)) ;
-	UInt_t tmp13= read(_pipeToClient[0],&ptr,sizeof(RooAbsReal*)) ;
-	if (tmp12+tmp13<sizeof(Message)+sizeof(RooAbsReal*)) perror("read") ;
-	if (ptr==0) {
-	  break ;
-	}
-	
-	UInt_t tmp6 = read(_pipeToClient[0],&ntext1,sizeof(Int_t)) ;
-	if (ntext1>1023) ntext1=1023 ; if (ntext1<0) ntext1=0 ; 
-	UInt_t tmp7 = read(_pipeToClient[0],msgbuf1,ntext1+1) ;
-
-	UInt_t tmp8 = read(_pipeToClient[0],&ntext2,sizeof(Int_t)) ;
-	if (ntext2>1023) ntext2=1023 ; if (ntext2<0) ntext2=0 ; 
-	UInt_t tmp9 = read(_pipeToClient[0],msgbuf2,ntext2+1) ;
-
-	UInt_t tmp10= read(_pipeToClient[0],&ntext3,sizeof(Int_t)) ;
-	if (ntext3>1023) ntext3=1023 ; if (ntext3<0) ntext3=0 ; 
-	UInt_t tmp11= read(_pipeToClient[0],msgbuf3,ntext3+1) ;
-
-	if (tmp6+tmp7+tmp8+tmp9+tmp10+tmp11<sizeof(Int_t)+ntext1+1+sizeof(Int_t)+ntext2+1+sizeof(Int_t)+ntext3+1) perror("read") ;
-	
+    if (numError) {
+      // Retrieve remote errors and feed into local error queue
+      char *msgbuf1 = 0, *msgbuf2 = 0, *msgbuf3 = 0;
+      RooAbsArg *ptr = 0;
+      while (true) {
+	*_pipe >> ptr;
+	if (!ptr) break;
+	*_pipe >> msgbuf1 >> msgbuf2 >> msgbuf3;
 	if (_verboseServer) cout << "RooRealMPFE::evaluate(" << GetName() 
-				 << ") IPC fromServer> SendError Arg " << ptr << " Msg " << msgbuf1 << endl ;    
-	
-	// WVE: null char is read from pipe  
-	// coverity[STRING_NULL]
-	logEvalError(ptr,msgbuf3,msgbuf1,msgbuf2) ;
+	  << ") IPC fromServer> retrieving error log Arg " << ptr << " Msg " << msgbuf1 << endl ;    
+
+	logEvalError(reinterpret_cast<RooAbsReal*>(ptr),msgbuf3,msgbuf1,msgbuf2) ;
       }
-	
+      std::free(msgbuf1);
+      std::free(msgbuf2);
+      std::free(msgbuf3);
     }
 
     // Mark end of calculation in progress 
@@ -730,25 +616,25 @@ void RooRealMPFE::standby()
 
 #ifndef _WIN32
   if (_state==Client) {
-
     // Terminate server process ;
-    Message msg = Terminate ;
-    UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-    if (tmp1<sizeof(Message)) perror("write") ;
+    int msg = Terminate;
+    *_pipe << msg << BidirMMapPipe::flush;
+    // read handshake
+    msg = 0;
+    *_pipe >> msg;
+    if (Terminate != msg || 0 != _pipe->close()) {
+	std::cerr << "In " << __func__ << "(" << __FILE__ ", " << __LINE__ <<
+	    "): Server shutdown failed." << std::endl;
+    }
     if (_verboseServer) cout << "RooRealMPFE::standby(" << GetName() 
-			     << ") IPC toServer> Terminate " << endl ;  
+			     << ") IPC toServer> Terminate " << endl; 
 
     // Close pipes
-    close(_pipeToClient[0]) ;
-    close(_pipeToClient[1]) ;
-    close(_pipeToServer[0]) ;
-    close(_pipeToServer[1]) ;
-
-    // Release resource of child process
-    waitpid(_pid,0,0) ;
+    delete _pipe;
+    _pipe = 0;
     
     // Revert to initialize state 
-    _state = Initialize ;
+    _state = Initialize;
   }
 #endif // _WIN32
 }
@@ -764,11 +650,9 @@ void RooRealMPFE::constOptimizeTestStatistic(ConstOpCode opcode, Bool_t doAlsoTr
 #ifndef _WIN32
   if (_state==Client) {
 
-    Message msg = ConstOpt ;
-    UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-    UInt_t tmp2 = write(_pipeToServer[1],&opcode,sizeof(ConstOpCode)) ;
-    UInt_t tmp3 = write(_pipeToServer[1],&doAlsoTracking,sizeof(Bool_t)) ;
-    if (tmp1+tmp2+tmp3<sizeof(Message)+sizeof(ConstOpCode)+sizeof(Bool_t)) perror("write") ;
+    int msg = ConstOpt ;
+    int op = opcode;
+    *_pipe << msg << op << doAlsoTracking;
     if (_verboseServer) cout << "RooRealMPFE::constOptimize(" << GetName() 
 			     << ") IPC toServer> ConstOpt " << opcode << endl ;  
 
@@ -791,10 +675,8 @@ void RooRealMPFE::setVerbose(Bool_t clientFlag, Bool_t serverFlag)
 
 #ifndef _WIN32
   if (_state==Client) {
-    Message msg = Verbose ;
-    UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-    UInt_t tmp2 = write(_pipeToServer[1],&serverFlag,sizeof(Bool_t)) ;
-    if (tmp1+tmp2<sizeof(Message)+sizeof(Bool_t)) perror("write") ;
+    int msg = Verbose ;
+    *_pipe << msg << serverFlag;
     if (_verboseServer) cout << "RooRealMPFE::setVerbose(" << GetName() 
 			     << ") IPC toServer> Verbose " << (serverFlag?1:0) << endl ;      
   }
@@ -811,10 +693,8 @@ void RooRealMPFE::applyNLLWeightSquared(Bool_t flag)
 
 #ifndef _WIN32
   if (_state==Client) {
-    Message msg = ApplyNLLW2 ;
-    UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-    UInt_t tmp2 = write(_pipeToServer[1],&flag,sizeof(Bool_t)) ;
-    if (tmp1+tmp2<sizeof(Message)+sizeof(Bool_t)) perror("write") ;
+    int msg = ApplyNLLW2 ;
+    *_pipe << msg << flag;
     if (_verboseServer) cout << "RooRealMPFE::applyNLLWeightSquared(" << GetName() 
 			     << ") IPC toServer> ApplyNLLW2 " << (flag?1:0) << endl ;      
   } 
@@ -841,10 +721,8 @@ void RooRealMPFE::enableOffsetting(Bool_t flag)
 
 #ifndef _WIN32
   if (_state==Client) {
-    Message msg = EnableOffset ;
-    UInt_t tmp1 = write(_pipeToServer[1],&msg,sizeof(msg)) ;
-    UInt_t tmp2 = write(_pipeToServer[1],&flag,sizeof(Bool_t)) ;
-    if (tmp1+tmp2<sizeof(Message)+sizeof(Bool_t)) perror("write") ;
+    int msg = EnableOffset ;
+    *_pipe << msg << flag;
     if (_verboseServer) cout << "RooRealMPFE::enableOffsetting(" << GetName() 
 			     << ") IPC toServer> EnableOffset " << (flag?1:0) << endl ;      
   } 
diff --git a/roofit/roofitcore/src/RooSentinel.cxx b/roofit/roofitcore/src/RooSentinel.cxx
index 3ce1888..68e57dd 100644
--- a/roofit/roofitcore/src/RooSentinel.cxx
+++ b/roofit/roofitcore/src/RooSentinel.cxx
@@ -42,7 +42,6 @@
 #include "RooRealConstant.h"
 #include "RooResolutionModel.h"
 #include "RooExpensiveObjectCache.h"
-#include "RooMath.h"
 
 Bool_t RooSentinel::_active = kFALSE ;
 
@@ -59,7 +58,6 @@ static void CleanUpRooFitAtExit()
   RooArgSet::cleanup() ;
   RooRealConstant::cleanup() ;
   RooResolutionModel::cleanup() ;
-  RooMath::cleanup() ;
   RooExpensiveObjectCache::cleanup() ;
 }
 
diff --git a/roofit/roofitcore/src/RooTrace.cxx b/roofit/roofitcore/src/RooTrace.cxx
index ada3655..5ffa1e8 100644
--- a/roofit/roofitcore/src/RooTrace.cxx
+++ b/roofit/roofitcore/src/RooTrace.cxx
@@ -166,7 +166,7 @@ void RooTrace::callgrind_zero()
   // To trigger callgrind zero counter action, run callgrind with 
   // argument '--zero-before=RooTrace::callgrind_zero()' (include single quotes in cmdline)
   
-  oocoutP((TObject*)0,Tracing) << "RooTrace::callgrind_zero()" << endl ;
+  ooccoutD((TObject*)0,Tracing) << "RooTrace::callgrind_zero()" << endl ;
 }
 
 //_____________________________________________________________________________
@@ -178,5 +178,5 @@ void RooTrace::callgrind_dump()
   // To trigger callgrind dumping action, run callgrind with 
   // argument '--dump-before=RooTrace::callgrind_dump()' (include single quotes in cmdline)
 
-  oocoutP((TObject*)0,Tracing) << "RooTrace::callgrind_dump()" << endl ;
+  ooccoutD((TObject*)0,Tracing) << "RooTrace::callgrind_dump()" << endl ;
 }
diff --git a/roofit/roofitcore/src/RooXYChi2Var.cxx b/roofit/roofitcore/src/RooXYChi2Var.cxx
index 0949046..f0a2f18 100644
--- a/roofit/roofitcore/src/RooXYChi2Var.cxx
+++ b/roofit/roofitcore/src/RooXYChi2Var.cxx
@@ -442,6 +442,7 @@ Double_t RooXYChi2Var::evaluatePartition(Int_t firstEvent, Int_t lastEvent, Int_
     result = t;
   }
 
+  _evalCarry = carry;
   return result ;
 }
 
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 9d2507d..2150aea 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -10,3 +10,6 @@ endif()
 if(pgsql)
   add_subdirectory(pgsql)
 endif()
+if(sqlite)
+  add_subdirectory(sqlite)
+endif()
diff --git a/sql/pgsql/inc/TPgSQLStatement.h b/sql/pgsql/inc/TPgSQLStatement.h
index 6aea6ba..b4e1deb 100644
--- a/sql/pgsql/inc/TPgSQLStatement.h
+++ b/sql/pgsql/inc/TPgSQLStatement.h
@@ -67,6 +67,8 @@ private:
    void        FreeBuffers();
    void        SetBuffersNumber(Int_t n);
 
+   void        ConvertTimeToUTC(const TString &PQvalue, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec);
+
 public:
    TPgSQLStatement(PgSQL_Stmt_t* stmt, Bool_t errout = kTRUE);
    virtual ~TPgSQLStatement();
diff --git a/sql/pgsql/src/TPgSQLStatement.cxx b/sql/pgsql/src/TPgSQLStatement.cxx
index c56a40e..1d80f11 100644
--- a/sql/pgsql/src/TPgSQLStatement.cxx
+++ b/sql/pgsql/src/TPgSQLStatement.cxx
@@ -20,6 +20,7 @@
 #include "TPgSQLStatement.h"
 #include "TDataType.h"
 #include "TDatime.h"
+#include "TTimeStamp.h"
 
 #include <stdlib.h>
 
@@ -48,6 +49,11 @@ TPgSQLStatement::TPgSQLStatement(PgSQL_Stmt_t* stmt, Bool_t errout):
    // Normal constructor.
    // Checks if statement contains parameters tags.
 
+   // Given fRes not used, we retrieve the statement using the connection. 
+   if (fStmt->fRes != NULL) {
+      PQclear(fStmt->fRes);
+   }
+
    fStmt->fRes = PQdescribePrepared(fStmt->fConn,"preparedstmt");
    unsigned long paramcount = PQnparams(fStmt->fRes);
    fNumResultCols = PQnfields(fStmt->fRes);
@@ -150,6 +156,12 @@ Bool_t TPgSQLStatement::Process()
 
    CheckStmt("Process",kFALSE);
 
+   // We create the prepared statement below, MUST delete the old one
+   // from our constructor first! 
+   if (fStmt->fRes != NULL) {
+      PQclear(fStmt->fRes);
+   }
+
    if (IsSetParsMode()) {
       fStmt->fRes= PQexecPrepared(fStmt->fConn,"preparedstmt",fNumBuffers,
                                  (const char* const*)fBind,
@@ -283,7 +295,7 @@ void TPgSQLStatement::FreeBuffers()
 {
    // Release all buffers, used by statement.
 
-  //individual field names free()'ed by PQClear of fStmt->fRes
+  //individual field names free()'ed by PQclear of fStmt->fRes
    if (fFieldName)
       delete[] fFieldName;
 
@@ -529,33 +541,41 @@ Bool_t TPgSQLStatement::GetLargeObject(Int_t npar, void* &mem, Long_t& size)
 //______________________________________________________________________________
 Bool_t TPgSQLStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
 {
-   // Return field value as date.
+   // Return field value as date, in UTC.
 
    TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
    TDatime d = TDatime(val.Data());
    year = d.GetYear();
    month = d.GetMonth();
    day= d.GetDay();
+   Int_t hour = d.GetHour();
+   Int_t min = d.GetMinute();
+   Int_t sec = d.GetSecond();
+   ConvertTimeToUTC(val, year, month, day, hour, min, sec);
    return kTRUE;
 }
 
 //______________________________________________________________________________
 Bool_t TPgSQLStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
 {
-   // Return field as time.
+   // Return field as time, in UTC.
 
    TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
    TDatime d = TDatime(val.Data());
    hour = d.GetHour();
    min = d.GetMinute();
    sec= d.GetSecond();
+   Int_t year = d.GetYear();
+   Int_t month = d.GetMonth();
+   Int_t day = d.GetDay();
+   ConvertTimeToUTC(val, day, month, year, hour, min, sec);
    return kTRUE;
 }
 
 //______________________________________________________________________________
 Bool_t TPgSQLStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
 {
-   // Return field value as date & time.
+   // Return field value as date & time, in UTC.
 
    TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
    TDatime d = TDatime(val.Data());
@@ -565,25 +585,83 @@ Bool_t TPgSQLStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t&
    hour = d.GetHour();
    min = d.GetMinute();
    sec= d.GetSecond();
+   ConvertTimeToUTC(val, year, month, day, hour, min, sec);
    return kTRUE;
 }
 
 //______________________________________________________________________________
+void TPgSQLStatement::ConvertTimeToUTC(const TString &PQvalue, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
+{
+   // Convert timestamp value to UTC if a zone is included.
+
+   Ssiz_t p = PQvalue.Last('.');
+   // Check if timestamp has timezone
+   TSubString *s_zone;
+   Bool_t hasZone = kFALSE;
+   Ssiz_t tzP = PQvalue.Last('+');
+   if ((tzP != kNPOS) && (tzP > p) ) {
+      s_zone = new TSubString(PQvalue(tzP,PQvalue.Length()-tzP+1));
+      hasZone=kTRUE;
+   } else {
+      Ssiz_t tzM = PQvalue.Last('-');
+      if ((tzM != kNPOS) && (tzM > p) ) {
+         s_zone = new TSubString(PQvalue(tzM,PQvalue.Length()-tzM+1));
+         hasZone = kTRUE;
+      }
+   }
+   if (hasZone == kTRUE) {
+      // Parse timezone, might look like e.g. +00 or -00:00
+      Int_t hourOffset, minuteOffset = 0;
+      Int_t conversions=sscanf(s_zone->Data(), "%2d:%2d", &hourOffset, &minuteOffset);
+      Int_t secondOffset = hourOffset*3600;
+      if (conversions>1) {
+         // Use sign from hour also for minute
+         secondOffset += (TMath::Sign(minuteOffset, hourOffset))*60;
+      }
+      // Use TTimeStamp so we do not have to take care of over-/underflows
+      TTimeStamp ts(year, month, day, hour, min, sec, 0, kTRUE, -secondOffset);
+      UInt_t uyear, umonth, uday, uhour, umin, usec;
+      ts.GetDate(kTRUE, 0, &uyear, &umonth, &uday);
+      ts.GetTime(kTRUE, 0, &uhour, &umin, &usec);
+      year=uyear;
+      month=umonth;
+      day=uday;
+      hour=uhour;
+      min=umin;
+      sec=usec;
+      delete s_zone;
+   }
+}
+
+//______________________________________________________________________________
 Bool_t TPgSQLStatement::GetTimestamp(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec, Int_t& frac)
 {
-   // Return field as timestamp.
+   // Return field as timestamp, in UTC.
+   // Second fraction is to be interpreted as in the following example:
+   // 2013-01-12 12:10:23.093854+02
+   // Fraction is '93854', precision is fixed in this method to 6 decimal places.
+   // This means the returned frac-value is always in microseconds.
 
    TString val=PQgetvalue(fStmt->fRes,fIterationCount,npar);
-   Ssiz_t p = val.Last('.');
-   TSubString s_frac = val(p,val.Length()-p+1);
-   TDatime d = TDatime(val.Data());
+   TDatime d(val.Data());
    year = d.GetYear();
    month = d.GetMonth();
    day= d.GetDay();
    hour = d.GetHour();
    min = d.GetMinute();
    sec= d.GetSecond();
-   frac=atoi(s_frac.Data());
+
+   ConvertTimeToUTC(val, year, month, day, hour, min, sec);
+
+   Ssiz_t p = val.Last('.');
+   TSubString s_frac = val(p,val.Length()-p+1);
+
+   // atoi ignores timezone part.
+   // We MUST use atof here to correctly convert the fraction of
+   // "12:23:01.093854" and put a limitation on precision,
+   // as we can only return an Int_t.
+   frac=(Int_t) (atof(s_frac.Data())*1.E6);
+
    return kTRUE;
 }
 
@@ -778,12 +856,15 @@ Bool_t TPgSQLStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day
 }
 
 //______________________________________________________________________________
-Bool_t TPgSQLStatement::SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t)
+Bool_t TPgSQLStatement::SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t frac)
 {
    // Set parameter value as timestamp.
+   // Second fraction is assumed as value in microseconds,
+   // i.e. as a fraction with six decimal places.
+   // See GetTimestamp() for an example.
 
    TDatime d(year,month,day,hour,min,sec);
-   snprintf(fBind[npar],kBindStringSize,"%s",(char*)d.AsSQLString());
+   snprintf(fBind[npar],kBindStringSize,"%s.%06d",(char*)d.AsSQLString(),frac);
    return kTRUE;
 }
 
diff --git a/sql/sqlite/CMakeLists.txt b/sql/sqlite/CMakeLists.txt
new file mode 100644
index 0000000..63c01ba
--- /dev/null
+++ b/sql/sqlite/CMakeLists.txt
@@ -0,0 +1,13 @@
+############################################################################
+# CMakeLists.txt file for building ROOT sql/pgsql package
+############################################################################
+
+ROOT_USE_PACKAGE(io/io)
+ROOT_USE_PACKAGE(net/net)
+
+include_directories(${SQLITE_INCLUDE_DIR})
+
+ROOT_GENERATE_DICTIONARY(G__SQLite *.h LINKDEF LinkDef.h)
+ROOT_GENERATE_ROOTMAP(RSQLite LINKDEF LinkDef.h DEPENDENCIES Net RIO)
+ROOT_LINKER_LIBRARY(RSQLite *.cxx G__SQLite.cxx LIBRARIES Core ${SQLITE_LIBRARIES} DEPENDENCIES Net RIO)
+ROOT_INSTALL_HEADERS()
diff --git a/sql/sqlite/Module.mk b/sql/sqlite/Module.mk
new file mode 100644
index 0000000..a4159a3
--- /dev/null
+++ b/sql/sqlite/Module.mk
@@ -0,0 +1,72 @@
+# Module.mk for sqlite module
+# Copyright (c) 2013 Rene Brun and Fons Rademakers
+#
+# Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+MODNAME      := sqlite
+MODDIR       := $(ROOT_SRCDIR)/sql/$(MODNAME)
+MODDIRS      := $(MODDIR)/src
+MODDIRI      := $(MODDIR)/inc
+
+SQLITEDIR    := $(MODDIR)
+SQLITEDIRS   := $(SQLITEDIR)/src
+SQLITEDIRI   := $(SQLITEDIR)/inc
+
+##### libSQLite #####
+SQLITEL      := $(MODDIRI)/LinkDef.h
+SQLITEDS     := $(call stripsrc,$(MODDIRS)/G__SQLite.cxx)
+SQLITEDO     := $(SQLITEDS:.cxx=.o)
+SQLITEDH     := $(SQLITEDS:.cxx=.h)
+
+SQLITEH      := $(filter-out $(MODDIRI)/LinkDef%,$(wildcard $(MODDIRI)/*.h))
+SQLITES      := $(filter-out $(MODDIRS)/G__%,$(wildcard $(MODDIRS)/*.cxx))
+SQLITEO      := $(call stripsrc,$(SQLITES:.cxx=.o))
+
+SQLITEDEP     := $(SQLITEO:.o=.d) $(SQLITEDO:.o=.d)
+
+SQLITELIB     := $(LPATH)/libSQLite.$(SOEXT)
+SQLITEMAP     := $(SQLITELIB:.$(SOEXT)=.rootmap)
+
+# used in the main Makefile
+ALLHDRS     += $(patsubst $(MODDIRI)/%.h,include/%.h,$(SQLITEH))
+ALLLIBS     += $(SQLITELIB)
+ALLMAPS     += $(SQLITEMAP)
+
+# include all dependency files
+INCLUDEFILES += $(SQLITEDEP)
+
+##### local rules #####
+.PHONY:         all-$(MODNAME) clean-$(MODNAME) distclean-$(MODNAME)
+
+include/%.h:    $(SQLITEDIRI)/%.h
+		cp $< $@
+
+$(SQLITELIB):   $(SQLITEO) $(SQLITEDO) $(ORDER_) $(MAINLIBS) $(SQLITELIBDEP)
+		@$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \
+		   "$(SOFLAGS)" libSQLite.$(SOEXT) $@ "$(SQLITEO) $(SQLITEDO)" \
+		   "$(SQLITELIBEXTRA) $(SQLITELIBDIR) $(SQLITECLILIB)"
+
+$(SQLITEDS):    $(SQLITEH) $(SQLITEL) $(ROOTCINTTMPDEP)
+		$(MAKEDIR)
+		@echo "Generating dictionary $@..."
+		$(ROOTCINTTMP) -f $@ -c $(SQLITEINCDIR:%=-I%) $(SQLITEH) \
+		   $(SQLITEL)
+
+$(SQLITEMAP):   $(RLIBMAP) $(MAKEFILEDEP) $(SQLITEL)
+		$(RLIBMAP) -o $@ -l $(SQLITELIB) \
+		   -d $(SQLITELIBDEPM) -c $(SQLITEL)
+
+all-$(MODNAME): $(SQLITELIB) $(SQLITEMAP)
+
+clean-$(MODNAME):
+		@rm -f $(SQLITEO) $(SQLITEDO)
+
+clean::         clean-$(MODNAME)
+
+distclean-$(MODNAME): clean-$(MODNAME)
+		@rm -f $(SQLITEDEP) $(SQLITEDS) $(SQLITEDH) $(SQLITELIB) $(SQLITEMAP)
+
+distclean::     distclean-$(MODNAME)
+
+##### extra rules ######
+$(SQLITEO) $(SQLITEDO): CXXFLAGS += $(SQLITEINCDIR:%=-I%)
diff --git a/sql/sqlite/inc/LinkDef.h b/sql/sqlite/inc/LinkDef.h
new file mode 100644
index 0000000..d270ab6
--- /dev/null
+++ b/sql/sqlite/inc/LinkDef.h
@@ -0,0 +1,12 @@
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class TSQLiteServer+;
+#pragma link C++ class TSQLiteResult+;
+#pragma link C++ class TSQLiteRow+;
+#pragma link C++ class TSQLiteStatement+;
+
+#endif
diff --git a/sql/sqlite/inc/TSQLiteResult.h b/sql/sqlite/inc/TSQLiteResult.h
new file mode 100644
index 0000000..3530def
--- /dev/null
+++ b/sql/sqlite/inc/TSQLiteResult.h
@@ -0,0 +1,45 @@
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TSQLiteResult
+#define ROOT_TSQLiteResult
+
+#ifndef ROOT_TSQLResult
+#include "TSQLResult.h"
+#endif
+
+#if !defined(__CINT__)
+#include <sqlite3.h>
+#else
+struct sqlite3_stmt;
+#endif
+
+
+class TSQLiteResult : public TSQLResult {
+
+private:
+   sqlite3_stmt   *fResult;  // query result (rows)
+
+   Bool_t  IsValid(Int_t field);
+
+public:
+   TSQLiteResult(void *result);
+   ~TSQLiteResult();
+
+   void        Close(Option_t *opt="");
+   Int_t       GetFieldCount();
+   const char *GetFieldName(Int_t field);
+   TSQLRow    *Next();
+
+   ClassDef(TSQLiteResult, 0)  // SQLite query result
+};
+
+#endif
diff --git a/sql/sqlite/inc/TSQLiteRow.h b/sql/sqlite/inc/TSQLiteRow.h
new file mode 100644
index 0000000..11c3527
--- /dev/null
+++ b/sql/sqlite/inc/TSQLiteRow.h
@@ -0,0 +1,43 @@
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TPgSQLRow
+#define ROOT_TPgSQLRow
+
+#ifndef ROOT_TSQLRow
+#include "TSQLRow.h"
+#endif
+
+#if !defined(__CINT__)
+#include <sqlite3.h>
+#else
+struct sqlite3_stmt;
+#endif
+
+
+class TSQLiteRow : public TSQLRow {
+
+private:
+   sqlite3_stmt *fResult;       // current result set
+   Bool_t        IsValid(Int_t field);
+
+public:
+   TSQLiteRow(void *result, ULong_t rowHandle);
+   ~TSQLiteRow();
+
+   void        Close(Option_t *opt="");
+   ULong_t     GetFieldLength(Int_t field);
+   const char *GetField(Int_t field);
+
+   ClassDef(TSQLiteRow,0)  // One row of SQLite query result
+};
+
+#endif
diff --git a/sql/sqlite/inc/TSQLiteServer.h b/sql/sqlite/inc/TSQLiteServer.h
new file mode 100644
index 0000000..264d196
--- /dev/null
+++ b/sql/sqlite/inc/TSQLiteServer.h
@@ -0,0 +1,57 @@
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TSQLiteServer
+#define ROOT_TSQLiteServer
+
+#ifndef ROOT_TSQLServer
+#include "TSQLServer.h"
+#endif
+
+#if !defined(__CINT__)
+#include <sqlite3.h>
+#else
+struct sqlite3;
+#endif
+
+
+
+class TSQLiteServer : public TSQLServer {
+
+ private:
+   TString   fSrvInfo;   // Server info string
+   sqlite3  *fSQLite;    // connection to SQLite DB
+
+ public:
+   TSQLiteServer(const char *db, const char *uid=NULL, const char *pw=NULL);
+   ~TSQLiteServer();
+
+   void           Close(Option_t *opt="");
+   Bool_t         StartTransaction();
+   TSQLResult    *Query(const char *sql);
+   Bool_t         Exec(const char *sql);
+   TSQLStatement *Statement(const char *sql, Int_t = 100);
+   Bool_t         HasStatement() const;
+   Int_t          SelectDataBase(const char *dbname);
+   TSQLResult    *GetDataBases(const char *wild = 0);
+   TSQLResult    *GetTables(const char *dbname, const char *wild = 0);
+   TSQLResult    *GetColumns(const char *dbname, const char *table, const char *wild = 0);
+   TSQLTableInfo *GetTableInfo(const char* tablename);
+   Int_t          CreateDataBase(const char *dbname);
+   Int_t          DropDataBase(const char *dbname);
+   Int_t          Reload();
+   Int_t          Shutdown();
+   const char    *ServerInfo();
+
+   ClassDef(TSQLiteServer,0);  // Connection to SQLite DB
+};
+
+#endif
diff --git a/sql/pgsql/inc/TPgSQLStatement.h b/sql/sqlite/inc/TSQLiteStatement.h
similarity index 67%
copy from sql/pgsql/inc/TPgSQLStatement.h
copy to sql/sqlite/inc/TSQLiteStatement.h
index 6aea6ba..cd9c9ea 100644
--- a/sql/pgsql/inc/TPgSQLStatement.h
+++ b/sql/sqlite/inc/TSQLiteStatement.h
@@ -1,16 +1,16 @@
-// @(#)root/mysql:$Id$
-// Author: Dennis Box (dbox at fnal.gov)  3/12/2007
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
 
 /*************************************************************************
- * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
  * All rights reserved.                                                  *
  *                                                                       *
  * For the licensing terms see $ROOTSYS/LICENSE.                         *
  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
  *************************************************************************/
 
-#ifndef ROOT_TPgSQLStatement
-#define ROOT_TPgSQLStatement
+#ifndef ROOT_TSQLiteStatement
+#define ROOT_TSQLiteStatement
 
 #ifndef ROOT_TSQLStatement
 #include "TSQLStatement.h"
@@ -23,38 +23,29 @@
 #else
 #include <sys/time.h>
 #endif
-#include <libpq-fe.h>
-#include <pg_config.h> // to get PG_VERSION_NUM
 
-#define pgsql_success(x) (((x) == PGRES_EMPTY_QUERY) \
-                        || ((x) == PGRES_COMMAND_OK) \
-                        || ((x) == PGRES_TUPLES_OK))
+#include <sqlite3.h>
 
 #else
-struct PGconn;
-struct PGresult;
+struct sqlite3;
+struct sqlite3_stmt;
 #endif
 
 
-struct PgSQL_Stmt_t {
-   PGconn   *fConn;
-   PGresult *fRes;
+
+struct SQLite3_Stmt_t {
+   sqlite3      *fConn;
+   sqlite3_stmt *fRes;
 };
 
 
-class TPgSQLStatement : public TSQLStatement {
+class TSQLiteStatement : public TSQLStatement {
 
 private:
-   PgSQL_Stmt_t         *fStmt;          //! executed statement
-   Int_t                 fNumBuffers;    //! number of statement parameters
-   char                **fBind;          //! array of data for input
-   char                **fFieldName;     //! array of column names
-   Int_t                 fWorkingMode;   //! 1 - setting parameters, 2 - retrieving results
-   Int_t                 fIterationCount;//! number of iteration
-   int                  *fParamLengths;  //! length of column
-   int                  *fParamFormats;  //! data type (OID)
-   Int_t                 fNumResultRows;
-   Int_t                 fNumResultCols;
+   SQLite3_Stmt_t       *fStmt;           //! executed statement
+   Int_t                 fWorkingMode;    //! 1 - setting parameters, 2 - retrieving results
+   Int_t                 fNumPars;        //! Number of bindable parameters
+   Int_t                 fIterationCount; //! Iteration count
 
    Bool_t      IsSetParsMode() const { return fWorkingMode==1; }
    Bool_t      IsResultSetMode() const { return fWorkingMode==2; }
@@ -64,12 +55,11 @@ private:
    long double ConvertToNumeric(Int_t npar);
    const char *ConvertToString(Int_t npar);
 
-   void        FreeBuffers();
-   void        SetBuffersNumber(Int_t n);
+   Bool_t CheckBindError(const char *method, int res);
 
 public:
-   TPgSQLStatement(PgSQL_Stmt_t* stmt, Bool_t errout = kTRUE);
-   virtual ~TPgSQLStatement();
+   TSQLiteStatement(SQLite3_Stmt_t* stmt, Bool_t errout = kTRUE);
+   virtual ~TSQLiteStatement();
 
    virtual void        Close(Option_t * = "");
 
@@ -85,7 +75,6 @@ public:
    virtual Bool_t      SetDouble(Int_t npar, Double_t value);
    virtual Bool_t      SetString(Int_t npar, const char* value, Int_t maxsize = 256);
    virtual Bool_t      SetBinary(Int_t npar, void* mem, Long_t size, Long_t maxsize = 0x1000);
-   virtual Bool_t      SetLargeObject(Int_t npar, void* mem, Long_t size, Long_t maxsize = 0x1000);
    virtual Bool_t      SetDate(Int_t npar, Int_t year, Int_t month, Int_t day);
    virtual Bool_t      SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec);
    virtual Bool_t      SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec);
@@ -110,13 +99,12 @@ public:
    virtual Double_t    GetDouble(Int_t npar);
    virtual const char *GetString(Int_t npar);
    virtual Bool_t      GetBinary(Int_t npar, void* &mem, Long_t& size);
-   virtual Bool_t      GetLargeObject(Int_t npar, void* &mem, Long_t& size);
    virtual Bool_t      GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day);
    virtual Bool_t      GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec);
    virtual Bool_t      GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec);
    virtual Bool_t      GetTimestamp(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec, Int_t&);
 
-   ClassDef(TPgSQLStatement, 0);  // SQL statement class for PgSQL DB
+   ClassDef(TSQLiteStatement, 0);  // SQL statement class for SQLite DB
 };
 
 #endif
diff --git a/sql/sqlite/src/TSQLiteResult.cxx b/sql/sqlite/src/TSQLiteResult.cxx
new file mode 100644
index 0000000..087451f
--- /dev/null
+++ b/sql/sqlite/src/TSQLiteResult.cxx
@@ -0,0 +1,111 @@
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#include "TSQLiteResult.h"
+#include "TSQLiteRow.h"
+
+ClassImp(TSQLiteResult)
+
+//______________________________________________________________________________
+TSQLiteResult::TSQLiteResult(void *result)
+{
+   // SQLite query result.
+
+   fResult = (sqlite3_stmt *) result;
+
+   // RowCount is -1, as sqlite cannot determine RowCount beforehand:
+   fRowCount = -1;
+}
+
+//______________________________________________________________________________
+TSQLiteResult::~TSQLiteResult()
+{
+   // Cleanup SQLite query result.
+
+   if (fResult)
+      Close();
+}
+
+//______________________________________________________________________________
+void TSQLiteResult::Close(Option_t *)
+{
+   // Close query result.
+
+   if (!fResult)
+      return;
+
+   sqlite3_finalize(fResult);
+   fResult     = 0;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteResult::IsValid(Int_t field)
+{
+   // Check if result set is open and field index within range.
+
+   if (!fResult) {
+      Error("IsValid", "result set closed");
+      return kFALSE;
+   }
+   if (field < 0 || field >= GetFieldCount()) {
+      Error("IsValid", "field index out of bounds");
+      return kFALSE;
+   }
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteResult::GetFieldCount()
+{
+   // Get number of fields in result.
+
+   if (!fResult) {
+      Error("GetFieldCount", "result set closed");
+      return 0;
+   }
+   return sqlite3_column_count(fResult);
+}
+
+//______________________________________________________________________________
+const char *TSQLiteResult::GetFieldName(Int_t field)
+{
+   // Get name of specified field.
+
+   if (!fResult) {
+      Error("GetFieldName", "result set closed");
+      return 0;
+   }
+   return sqlite3_column_name(fResult, field);
+}
+
+//______________________________________________________________________________
+TSQLRow *TSQLiteResult::Next()
+{
+   // Get next query result row. The returned object must be
+   // deleted by the user.
+
+   if (!fResult) {
+      Error("Next", "result set closed");
+      return 0;
+   }
+
+   int ret = sqlite3_step(fResult);
+   if ((ret != SQLITE_DONE) && (ret != SQLITE_ROW)) {
+      Error("Statement", "SQL Error: %d %s", ret, sqlite3_errmsg(sqlite3_db_handle(fResult)));
+      return NULL;
+   }
+   if (ret == SQLITE_DONE) {
+      // Finished executing, no other row!
+      return NULL;
+   }
+   return new TSQLiteRow((void *) fResult, -1);
+}
+
diff --git a/sql/sqlite/src/TSQLiteRow.cxx b/sql/sqlite/src/TSQLiteRow.cxx
new file mode 100644
index 0000000..4598edb
--- /dev/null
+++ b/sql/sqlite/src/TSQLiteRow.cxx
@@ -0,0 +1,86 @@
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#include "TSQLiteRow.h"
+
+
+ClassImp(TSQLiteRow)
+
+//______________________________________________________________________________
+TSQLiteRow::TSQLiteRow(void *res, ULong_t /*rowHandle*/)
+{
+   // Single row of query result.
+
+   fResult = (sqlite3_stmt *) res;
+}
+
+//______________________________________________________________________________
+TSQLiteRow::~TSQLiteRow()
+{
+   // Destroy row object.
+
+   if (fResult)
+      Close();
+}
+
+//______________________________________________________________________________
+void TSQLiteRow::Close(Option_t *)
+{
+   // Close row.
+
+   fResult = 0;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteRow::IsValid(Int_t field)
+{
+   // Check if row is open and field index within range.
+
+   if (field < 0 || field >= (Int_t)sqlite3_column_count(fResult)) {
+      Error("IsValid", "field index out of bounds");
+      return kFALSE;
+   }
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+ULong_t TSQLiteRow::GetFieldLength(Int_t field)
+{
+   // Get length in bytes of specified field.
+
+   if (!IsValid(field))
+      return 0;
+
+   // Should call the access-method first, so sqlite3 can check whether a NULL-terminator
+   // needs to be added to the byte-count, e.g. for BLOB!
+   sqlite3_column_text(fResult, field);
+
+   ULong_t fieldLength = (ULong_t) sqlite3_column_bytes(fResult, field);
+
+   if (!fieldLength) {
+      Error("GetFieldLength", "cannot get field length");
+      return 0;
+   }
+
+   return fieldLength;
+}
+
+//______________________________________________________________________________
+const char *TSQLiteRow::GetField(Int_t field)
+{
+   // Get specified field from row (0 <= field < GetFieldCount()).
+
+   if (!IsValid(field))
+      return 0;
+
+   return reinterpret_cast<const char*>(sqlite3_column_text(fResult, field));
+}
+
diff --git a/sql/sqlite/src/TSQLiteServer.cxx b/sql/sqlite/src/TSQLiteServer.cxx
new file mode 100644
index 0000000..d6afa41
--- /dev/null
+++ b/sql/sqlite/src/TSQLiteServer.cxx
@@ -0,0 +1,369 @@
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#include "TSQLiteServer.h"
+#include "TSQLiteResult.h"
+#include "TSQLiteStatement.h"
+#include "TSQLColumnInfo.h"
+#include "TList.h"
+#include "TSQLTableInfo.h"
+#include "TSQLRow.h"
+
+ClassImp(TSQLiteServer)
+
+//______________________________________________________________________________
+TSQLiteServer::TSQLiteServer(const char *db, const char* /*uid*/, const char* /*pw*/)
+{
+   // Open a connection to an SQLite DB server. The db arguments should be
+   // of the form "sqlite://<database>", e.g.:
+   // "sqlite://test.sqlite" or "sqlite://:memory:" for a temporary database
+   // in memory.
+   // Note that for SQLite versions >= 3.7.7 the full string behind
+   // "sqlite://" is handed to sqlite3_open_v2() with SQLITE_OPEN_URI activated,
+   // so all URI accepted by it can be used.
+
+   fSQLite = NULL;
+   fSrvInfo = "SQLite ";
+   fSrvInfo += sqlite3_libversion();
+
+   if (strncmp(db, "sqlite://", 9)) {
+      TString givenProtocol(db, 9); // this TString-constructor allocs len+1 and does \0 termination already.
+      Error("TSQLiteServer", "protocol in db argument should be sqlite it is %s",
+            givenProtocol.Data());
+      MakeZombie();
+      return;
+   }
+
+   const char *dbase = db + 9;
+
+#ifndef SQLITE_OPEN_URI
+#define SQLITE_OPEN_URI 0x00000000
+#endif
+#if SQLITE_VERSION_NUMBER >= 3005000
+   Int_t error = sqlite3_open_v2(dbase, &fSQLite, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
+#else
+   Int_t error = sqlite3_open(dbase, &fSQLite);
+#endif
+
+   if (error == 0) {
+      // Set members of the abstract interface
+      fType = "SQLite";
+      fHost = "";
+      fDB = dbase;
+      // fPort != -1 means we are 'connected'
+      fPort = 0;
+   } else {
+      Error("TSQLiteServer", "opening of %s failed with error: %d %s", dbase, sqlite3_errcode(fSQLite), sqlite3_errmsg(fSQLite));
+      sqlite3_close(fSQLite);
+      MakeZombie();
+   }
+
+}
+
+//______________________________________________________________________________
+TSQLiteServer::~TSQLiteServer()
+{
+   // Close SQLite DB.
+
+   if (IsConnected()) {
+      sqlite3_close(fSQLite);
+   }
+}
+
+//______________________________________________________________________________
+void TSQLiteServer::Close(Option_t *)
+{
+   // Close connection to SQLite DB.
+
+   if (!fSQLite) {
+      return;
+   }
+
+   sqlite3_close(fSQLite);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteServer::StartTransaction()
+{
+   // submit "START TRANSACTION" query to database
+   // return kTRUE, if successful
+
+   return Exec("BEGIN TRANSACTION");
+}
+
+//______________________________________________________________________________
+TSQLResult *TSQLiteServer::Query(const char *sql)
+{
+   // Execute SQL command. Result object must be deleted by the user.
+   // Returns a pointer to a TSQLResult object if successful, 0 otherwise.
+   // The result object must be deleted by the user.
+
+   if (!IsConnected()) {
+      Error("Query", "not connected");
+      return 0;
+   }
+
+   sqlite3_stmt *preparedStmt = NULL;
+
+   // -1 as we read until we encounter a \0.
+   // NULL because we do not check which char was read last.
+#if SQLITE_VERSION_NUMBER >= 3005000
+   int retVal = sqlite3_prepare_v2(fSQLite, sql, -1, &preparedStmt, NULL);
+#else
+   int retVal = sqlite3_prepare(fSQLite, sql, -1, &preparedStmt, NULL);
+#endif
+   if (retVal != SQLITE_OK) {
+      Error("Query", "SQL Error: %d %s", retVal, sqlite3_errmsg(fSQLite));
+      return 0;
+   }
+
+   return new TSQLiteResult(preparedStmt);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteServer::Exec(const char *sql)
+{
+   // Execute SQL command which does not produce any result sets.
+   // Returns kTRUE if successful.
+
+   char *sqlite_err_msg;
+   int ret = sqlite3_exec(fSQLite, sql, NULL, NULL, &sqlite_err_msg);
+   if (ret != SQLITE_OK) {
+      Error("Exec", "SQL Error: %d %s", ret, sqlite_err_msg);
+      sqlite3_free(sqlite_err_msg);
+      return kFALSE;
+   }
+   return kTRUE;
+}
+
+
+//______________________________________________________________________________
+Int_t TSQLiteServer::SelectDataBase(const char* /*dbname*/)
+{
+   // Select a database. Always returns non-zero for SQLite,
+   // as only one DB exists per file.
+
+   Error("SelectDataBase", "SelectDataBase command makes no sense for SQLite!");
+   return -1;
+}
+
+//______________________________________________________________________________
+TSQLResult *TSQLiteServer::GetDataBases(const char* /*wild*/)
+{
+   // List all available databases. Always returns 0 for SQLite,
+   // as only one DB exists per file.
+
+   Error("GetDataBases", "GetDataBases command makes no sense for SQLite!");
+   return 0;
+}
+
+//______________________________________________________________________________
+TSQLResult *TSQLiteServer::GetTables(const char* /*dbname*/, const char *wild)
+{
+   // List all tables in the specified database. Wild is for wildcarding
+   // "t%" list all tables starting with "t".
+   // Returns a pointer to a TSQLResult object if successful, 0 otherwise.
+   // The result object must be deleted by the user.
+
+   if (!IsConnected()) {
+      Error("GetTables", "not connected");
+      return 0;
+   }
+
+   TString sql = "SELECT name FROM sqlite_master where type='table'";
+   if (wild)
+      sql += Form(" AND name LIKE '%s'", wild);
+
+   return Query(sql);
+}
+
+//______________________________________________________________________________
+TSQLResult *TSQLiteServer::GetColumns(const char* /*dbname*/, const char* table,
+      const char* wild)
+{
+   // List all columns in specified table (database argument is ignored).
+   // Wild is for wildcarding "t%" list all columns starting with "t".
+   // Returns a pointer to a TSQLResult object if successful, 0 otherwise.
+   // The result object must be deleted by the user.
+   // For SQLite, this fails with wildcard, as the column names are not queryable!
+   // If no wildcard is used, the result of PRAGMA table_info(table) is returned,
+   // which contains the names in field 1.
+
+   if (!IsConnected()) {
+      Error("GetColumns", "not connected");
+      return 0;
+   }
+
+   if (wild) {
+      Error("GetColumns", "Not implementable for SQLite as a query with wildcard, use GetFieldNames() after SELECT instead!");
+      return NULL;
+   } else {
+      TString sql = Form("PRAGMA table_info('%s')", table);
+      return Query(sql);
+   }
+}
+
+//______________________________________________________________________________
+TSQLTableInfo *TSQLiteServer::GetTableInfo(const char* tablename)
+{
+   // Produces SQL table info.
+   // Object must be deleted by user.
+
+   if (!IsConnected()) {
+      Error("GetTableInfo", "not connected");
+      return 0;
+   }
+
+   if ((tablename==0) || (*tablename==0)) return 0;
+
+   TSQLResult *columnRes = GetColumns("", tablename);
+
+   if (columnRes == NULL) {
+      Error("GetTableInfo", "could not query columns");
+      return NULL;
+   }
+
+   TList* lst = NULL;
+
+   TSQLRow *columnRow;
+
+   while ((columnRow = columnRes->Next()) != NULL) {
+      if (lst == NULL) {
+         lst = new TList();
+      }
+
+      // Field 3 is 'notnull', i.e. if it is 0, column is nullable
+      Bool_t isNullable = (strcmp(columnRow->GetField(3), "0") == 0);
+
+      lst->Add(new TSQLColumnInfo(columnRow->GetField(1), // column name
+                                  columnRow->GetField(2), // column type name
+                                  isNullable,  // isNullable defined above
+                                  -1,   // SQLite is totally free about types
+                                  -1,   // SQLite imposes no declarable size-limits
+                                  -1,   // Field length only available querying the field
+                                  -1,   // no data scale in SQLite
+                                  -1)); // SQLite does not enforce any sign(s)
+      delete columnRow;
+   }
+   delete columnRes;
+
+   // lst == NULL is ok as TSQLTableInfo accepts and handles this
+   TSQLTableInfo*  info = new TSQLTableInfo(tablename,
+                                            lst);
+
+   return info;
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteServer::CreateDataBase(const char* /*dbname*/)
+{
+   // Create a database. Always returns non-zero for SQLite,
+   // as it has only one DB per file.
+
+   Error("CreateDataBase", "CreateDataBase command makes no sense for SQLite!");
+   return -1;
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteServer::DropDataBase(const char* /*dbname*/)
+{
+   // Drop (i.e. delete) a database. Always returns non-zero for SQLite,
+   // as it has only one DB per file.
+
+   Error("DropDataBase", "DropDataBase command makes no sense for SQLite!");
+   return -1;
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteServer::Reload()
+{
+   // Reload permission tables. Returns 0 if successful, non-zero
+   // otherwise. User must have reload permissions.
+
+   if (!IsConnected()) {
+      Error("Reload", "not connected");
+      return -1;
+   }
+
+   Error("Reload", "not implemented");
+   return 0;
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteServer::Shutdown()
+{
+   // Shutdown the database server. Returns 0 if successful, non-zero
+   // otherwise. Makes no sense for SQLite, always returns -1.
+
+   if (!IsConnected()) {
+      Error("Shutdown", "not connected");
+      return -1;
+   }
+
+   Error("Shutdown", "not implemented");
+   return -1;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteServer::HasStatement() const
+{
+   // We assume prepared statements work for all SQLite-versions.
+   // As we actually use the recommended sqlite3_prepare(),
+   // or, if possible, sqlite3_prepare_v2(),
+   // this already introduces the "compile time check".
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+TSQLStatement* TSQLiteServer::Statement(const char *sql, Int_t)
+{
+   // Produce TSQLiteStatement.
+
+   if (!sql || !*sql) {
+      SetError(-1, "no query string specified", "Statement");
+      return 0;
+   }
+
+   sqlite3_stmt *preparedStmt = NULL;
+
+   // -1 as we read until we encounter a \0.
+   // NULL because we do not check which char was read last.
+#if SQLITE_VERSION_NUMBER >= 3005000
+   int retVal = sqlite3_prepare_v2(fSQLite, sql, -1, &preparedStmt, NULL);
+#else
+   int retVal = sqlite3_prepare(fSQLite, sql, -1, &preparedStmt, NULL);
+#endif
+   if (retVal != SQLITE_OK) {
+      Error("Statement", "SQL Error: %d %s", retVal, sqlite3_errmsg(fSQLite));
+      return 0;
+   }
+
+   SQLite3_Stmt_t *stmt = new SQLite3_Stmt_t;
+   stmt->fConn = fSQLite;
+   stmt->fRes  = preparedStmt;
+
+   return new TSQLiteStatement(stmt);
+}
+
+//______________________________________________________________________________
+const char *TSQLiteServer::ServerInfo()
+{
+   // Return server info, must be deleted by user.
+
+   if (!IsConnected()) {
+      Error("ServerInfo", "not connected");
+      return 0;
+   }
+
+   return fSrvInfo.Data();
+}
+
diff --git a/sql/sqlite/src/TSQLiteStatement.cxx b/sql/sqlite/src/TSQLiteStatement.cxx
new file mode 100644
index 0000000..02d38ac
--- /dev/null
+++ b/sql/sqlite/src/TSQLiteStatement.cxx
@@ -0,0 +1,590 @@
+// @(#)root/sqlite:$Id$
+// Author: o.freyermuth <o.f at cern.ch>, 01/06/2013
+
+/*************************************************************************
+ * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+//  SQL statement class for SQLite.                                     //
+//                                                                      //
+//  See TSQLStatement class documentation for more details.             //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include "TSQLiteStatement.h"
+#include "TDataType.h"
+#include "TDatime.h"
+#include "TTimeStamp.h"
+
+#include <stdlib.h>
+
+ClassImp(TSQLiteStatement)
+
+//______________________________________________________________________________
+TSQLiteStatement::TSQLiteStatement(SQLite3_Stmt_t* stmt, Bool_t errout):
+      TSQLStatement(errout),
+      fStmt(stmt),
+      fWorkingMode(0),
+      fNumPars(0),
+      fIterationCount(0)
+{
+   // Normal constructor.
+   // Checks if statement contains parameters tags.
+
+   unsigned long paramcount = sqlite3_bind_parameter_count(fStmt->fRes);
+   fNumPars = paramcount;
+
+   if (paramcount > 0) {
+      fWorkingMode = 1;
+   } else {
+      fWorkingMode = 2;
+   }
+}
+
+//______________________________________________________________________________
+TSQLiteStatement::~TSQLiteStatement()
+{
+   // Destructor.
+
+   Close();
+}
+
+//______________________________________________________________________________
+void TSQLiteStatement::Close(Option_t *)
+{
+   // Close statement.
+
+   if (fStmt->fRes) {
+      sqlite3_finalize(fStmt->fRes);
+   }
+
+   fStmt->fRes = 0;
+}
+
+
+// Reset error and check that statement exists
+#define CheckStmt(method, res)                          \
+   {                                                    \
+      ClearError();                                     \
+      if (fStmt==0) {                                   \
+         SetError(-1,"Statement handle is 0",method);   \
+         return res;                                    \
+      }                                                 \
+   }
+
+#define CheckErrNo(method, force, res)                  \
+   {                                                    \
+      int stmterrno = sqlite3_errcode(fStmt->fConn);    \
+      if ((stmterrno!=0) || force) {                    \
+         const char* stmterrmsg = sqlite3_errmsg(fStmt->fConn);  \
+         if (stmterrno==0) { stmterrno = -1; stmterrmsg = "SQLite statement error"; } \
+         SetError(stmterrno, stmterrmsg, method);       \
+         return res;                                    \
+      }                                                 \
+   }
+
+#define CheckGetField(method, res)                      \
+   {                                                    \
+      ClearError();                                     \
+      if (!IsResultSetMode()) {                         \
+         SetError(-1,"Cannot get statement parameters",method); \
+         return res;                                    \
+      }                                                 \
+      if ((npar<0) || (npar>=fNumPars)) {     \
+         SetError(-1,Form("Invalid parameter number %d", npar),method); \
+         return res;                                    \
+      }                                                 \
+   }
+
+
+Bool_t TSQLiteStatement::CheckBindError(const char *method, int res)
+{
+   if (res == SQLITE_RANGE) {
+      SetError(-1, Form("SQLite parameter out of bounds, error: %d %s", res, sqlite3_errmsg(fStmt->fConn)), method);
+      return kFALSE;
+   }
+   if (res != SQLITE_OK) {
+      SetError(-1, Form("SQLite error code during parameter binding, error: %d %s", res, sqlite3_errmsg(fStmt->fConn)), method);
+      return kFALSE;
+   }
+   return kTRUE;
+}
+
+//________________________________________________________________________
+Bool_t TSQLiteStatement::Process()
+{
+   // Process statement.
+
+   CheckStmt("Process", kFALSE);
+
+   int res = sqlite3_step(fStmt->fRes);
+   if ((res != SQLITE_DONE) && (res != SQLITE_ROW)) {
+      SetError(-1, Form("SQLite error code during statement-stepping: %d %s", res, sqlite3_errmsg(fStmt->fConn)), "Process");
+      return kFALSE;
+   }
+
+   // After a DONE-step, we have to reset, note this still KEEPS the parameters bound in SQLite,
+   // real reset happens in finalize, but user can still reuse the query!
+   if (res == SQLITE_DONE) {
+      sqlite3_reset(fStmt->fRes);
+
+      // If IsResultSetMode then this means we are done and should return kFALSE:
+      if (IsResultSetMode()) {
+         return kFALSE;
+      }
+
+      // If IsSetParsMode then this means we just stepped and should return kTRUE:
+      if (IsSetParsMode()) {
+         return kTRUE;
+      }
+   }
+
+   if (res == SQLITE_ROW) {
+      // Next row data retrieved, return kTRUE.
+      return kTRUE;
+   }
+
+   return kFALSE;
+}
+
+//________________________________________________________________________
+Int_t TSQLiteStatement::GetNumAffectedRows()
+{
+   // Return number of affected rows after statement is processed.
+   // Indirect changes e.g. by triggers are not counted, only direct changes
+   // from last completed statement are taken into account.
+
+   CheckStmt("GetNumAffectedRows", kFALSE);
+
+   return (Int_t) sqlite3_changes(fStmt->fConn);
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteStatement::GetNumParameters()
+{
+   // Return number of statement parameters.
+
+   CheckStmt("GetNumParameters", -1);
+
+   Int_t res = sqlite3_bind_parameter_count(fStmt->fRes);
+
+   CheckErrNo("GetNumParameters", kFALSE, -1);
+
+   return res;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::StoreResult()
+{
+   // Store result of statement processing to access them
+   // via GetInt(), GetDouble() and so on methods.
+   // For SQLite, this is a NO-OP.
+
+   fWorkingMode = 2;
+
+   CheckStmt("StoreResult", kFALSE);
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteStatement::GetNumFields()
+{
+   // Return number of fields in result set.
+
+   if (fWorkingMode == 1)
+      return sqlite3_bind_parameter_count(fStmt->fRes);
+   if (fWorkingMode == 2)
+      return sqlite3_column_count(fStmt->fRes);
+   return -1;
+}
+
+//______________________________________________________________________________
+const char* TSQLiteStatement::GetFieldName(Int_t nfield)
+{
+   // Returns field name in result set.
+
+   if (!IsResultSetMode() || (nfield < 0) || (nfield >= sqlite3_column_count(fStmt->fRes))) {
+      return 0;
+   }
+
+   return sqlite3_column_name(fStmt->fRes, nfield);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::NextResultRow()
+{
+   // Shift cursor to next row in result set.
+
+   ClearError();
+
+   if ((fStmt == 0) || !IsResultSetMode()) return kFALSE;
+
+   if (fIterationCount == 0) {
+      // The interface says user should call NextResultRow() before getting any data,
+      // this makes no sense at least for SQLite.
+      // We just return kTRUE here and only do something on second request.
+      fIterationCount++;
+      return kTRUE;
+   }
+
+   return Process();
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::NextIteration()
+{
+   // Increment iteration counter for statement, where parameter can be set.
+   // Statement with parameters of previous iteration
+   // automatically will be applied to database.
+   // Actually a NO-OP for SQLite, as parameters stay bound when step-ping.
+
+   ClearError();
+
+   if (!IsSetParsMode()) {
+      SetError(-1, "Cannot call for that statement", "NextIteration");
+      return kFALSE;
+   }
+
+   if (fIterationCount == 0) {
+      // The interface says user should call NextIteration() before binding any parameters,
+      // this makes no sense at least for SQLite.
+      // We just return kTRUE here and wait for data to really do something.
+      fIterationCount++;
+      return kTRUE;
+   }
+
+   fIterationCount++;
+
+   return Process();
+}
+
+//______________________________________________________________________________
+const char* TSQLiteStatement::ConvertToString(Int_t npar)
+{
+   // Convert field value to string.
+
+   return reinterpret_cast<const char *>(sqlite3_column_text(fStmt->fRes, npar));
+}
+
+//______________________________________________________________________________
+long double TSQLiteStatement::ConvertToNumeric(Int_t npar)
+{
+   // Convert field to numeric.
+
+   return (long double) sqlite3_column_double(fStmt->fRes, npar);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::IsNull(Int_t npar)
+{
+   // Checks if field value is null.
+
+   CheckGetField("IsNull", kFALSE);
+
+   return (sqlite3_column_type(fStmt->fRes, npar) == SQLITE_NULL);
+}
+
+//______________________________________________________________________________
+Int_t TSQLiteStatement::GetInt(Int_t npar)
+{
+   // Get integer.
+
+   return (Int_t) sqlite3_column_int(fStmt->fRes, npar);
+}
+
+//______________________________________________________________________________
+UInt_t TSQLiteStatement::GetUInt(Int_t npar)
+{
+   // Get unsigned integer.
+
+   return (UInt_t) sqlite3_column_int(fStmt->fRes, npar);
+}
+
+//______________________________________________________________________________
+Long_t TSQLiteStatement::GetLong(Int_t npar)
+{
+   // Get long.
+
+   return (Long_t) sqlite3_column_int64(fStmt->fRes, npar);
+}
+
+//______________________________________________________________________________
+Long64_t TSQLiteStatement::GetLong64(Int_t npar)
+{
+   // Get long64.
+
+   return (Long64_t) sqlite3_column_int64(fStmt->fRes, npar);
+}
+
+//______________________________________________________________________________
+ULong64_t TSQLiteStatement::GetULong64(Int_t npar)
+{
+   // Return field value as unsigned 64-bit integer
+
+   return (ULong64_t) sqlite3_column_int64(fStmt->fRes, npar);
+}
+
+//______________________________________________________________________________
+Double_t TSQLiteStatement::GetDouble(Int_t npar)
+{
+   // Return field value as double.
+
+   return (Double_t) sqlite3_column_double(fStmt->fRes, npar);
+}
+
+//______________________________________________________________________________
+const char *TSQLiteStatement::GetString(Int_t npar)
+{
+   // Return field value as string.
+
+   return reinterpret_cast<const char *>(sqlite3_column_text(fStmt->fRes, npar));
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::GetBinary(Int_t npar, void* &mem, Long_t& size)
+{
+   // Return field value as binary array.
+   // Memory at 'mem' will be reallocated and size updated
+   // to fit the data if not large enough.
+
+   // As we retrieve "as blob", we do NOT call sqlite3_column_text() before
+   // sqlite3_column_bytes(), which might leave us with a non-zero terminated
+   // data struture, but this should be okay for BLOB.
+   size_t sz = sqlite3_column_bytes(fStmt->fRes, npar);
+   if ((Long_t)sz > size) {
+      delete [](unsigned char*) mem;
+      mem = (void*) new unsigned char[sz];
+   }
+   size = sz;
+
+   memcpy(mem, sqlite3_column_blob(fStmt->fRes, npar), sz);
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::GetDate(Int_t npar, Int_t& year, Int_t& month, Int_t& day)
+{
+   // Return field value as date.
+
+   TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
+   TDatime d = TDatime(val.Data());
+   year = d.GetYear();
+   month = d.GetMonth();
+   day = d.GetDay();
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::GetTime(Int_t npar, Int_t& hour, Int_t& min, Int_t& sec)
+{
+   // Return field as time.
+
+   TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
+   TDatime d = TDatime(val.Data());
+   hour = d.GetHour();
+   min = d.GetMinute();
+   sec = d.GetSecond();
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::GetDatime(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec)
+{
+   // Return field value as date & time.
+
+   TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
+   TDatime d = TDatime(val.Data());
+   year = d.GetYear();
+   month = d.GetMonth();
+   day = d.GetDay();
+   hour = d.GetHour();
+   min = d.GetMinute();
+   sec = d.GetSecond();
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::GetTimestamp(Int_t npar, Int_t& year, Int_t& month, Int_t& day, Int_t& hour, Int_t& min, Int_t& sec, Int_t& frac)
+{
+   // Return field as timestamp.
+   // Second fraction is in milliseconds, which is also the precision all date and time functions of sqlite use.
+
+   TString val = reinterpret_cast<const char*>(sqlite3_column_text(fStmt->fRes, npar));
+
+   Ssiz_t p = val.Last('.');
+   TSubString ts_part = val(0, p);
+
+   TDatime d(ts_part.Data());
+   year = d.GetYear();
+   month = d.GetMonth();
+   day = d.GetDay();
+   hour = d.GetHour();
+   min = d.GetMinute();
+   sec = d.GetSecond();
+
+   TSubString s_frac = val(p, val.Length() - p+1);
+   frac=(Int_t) (atof(s_frac.Data())*1.E3);
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetNull(Int_t npar)
+{
+   // Set NULL as parameter value.
+
+   int res = sqlite3_bind_null(fStmt->fRes, npar + 1);
+
+   return CheckBindError("SetNull", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetInt(Int_t npar, Int_t value)
+{
+   // Set parameter value as integer.
+
+   int res = sqlite3_bind_int(fStmt->fRes, npar + 1, value);
+
+   return CheckBindError("SetInt", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetUInt(Int_t npar, UInt_t value)
+{
+   // Set parameter value as unsigned integer.
+   // Actually casted to signed integer, has to be re-casted upon read!
+
+   int res = sqlite3_bind_int(fStmt->fRes, npar + 1, (Int_t)value);
+
+   return CheckBindError("SetUInt", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetLong(Int_t npar, Long_t value)
+{
+   // Set parameter value as long.
+
+   int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, value);
+
+   return CheckBindError("SetLong", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetLong64(Int_t npar, Long64_t value)
+{
+   // Set parameter value as 64-bit integer.
+
+   int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, value);
+
+   return CheckBindError("SetLong64", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetULong64(Int_t npar, ULong64_t value)
+{
+   // Set parameter value as unsigned 64-bit integer.
+   // Actually casted to signed integer, has to be re-casted upon read!
+
+   int res = sqlite3_bind_int64(fStmt->fRes, npar + 1, (Long64_t)value);
+
+   return CheckBindError("SetULong64", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetDouble(Int_t npar, Double_t value)
+{
+   // Set parameter value as double value.
+
+   int res = sqlite3_bind_double(fStmt->fRes, npar + 1, value);
+
+   return CheckBindError("SetDouble", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetString(Int_t npar, const char* value, Int_t maxsize)
+{
+   // Set parameter value as string.
+
+   int res = sqlite3_bind_text(fStmt->fRes, npar + 1, value, maxsize, SQLITE_TRANSIENT);
+
+   return CheckBindError("SetString", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetBinary(Int_t npar, void* mem, Long_t size, Long_t /*maxsize*/)
+{
+   // Set parameter value as binary data.
+   // Maxsize is ignored for SQLite, we directly insert BLOB of size 'size'.
+   // Negative size would cause undefined behaviour, so we refuse that.
+
+   if (size < 0) {
+      SetError(-1, "Passing negative value to size for BLOB to SQLite would cause undefined behaviour, refusing it!", "SetBinary");
+      return kFALSE;
+   }
+
+   int res = sqlite3_bind_blob(fStmt->fRes, npar + 1, mem, (size_t)size, SQLITE_TRANSIENT);
+
+   return CheckBindError("SetBinary", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetDate(Int_t npar, Int_t year, Int_t month, Int_t day)
+{
+   // Set parameter value as date.
+
+   TDatime d = TDatime(year, month, day, 0, 0, 0);
+   int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
+
+   return CheckBindError("SetDate", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetTime(Int_t npar, Int_t hour, Int_t min, Int_t sec)
+{
+   // Set parameter value as time.
+
+   TDatime d = TDatime(2000, 1, 1, hour, min, sec);
+
+   int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
+
+   return CheckBindError("SetTime", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetDatime(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec)
+{
+   // Set parameter value as date & time.
+
+   TDatime d = TDatime(year, month, day, hour, min, sec);
+
+   int res = sqlite3_bind_text(fStmt->fRes, npar + 1, (char*)d.AsSQLString(), -1, SQLITE_TRANSIENT);
+
+   return CheckBindError("SetDatime", res);
+}
+
+//______________________________________________________________________________
+Bool_t TSQLiteStatement::SetTimestamp(Int_t npar, Int_t year, Int_t month, Int_t day, Int_t hour, Int_t min, Int_t sec, Int_t frac)
+{
+   // Set parameter value as timestamp.
+   // The second fraction has to be in milliseconds,
+   // as all SQLite functions for date and time assume 3 significant digits.
+
+   TDatime d(year,month,day,hour,min,sec);
+   TString value;
+   value.Form("%s.%03d", (char*)d.AsSQLString(), frac);
+
+   int res = sqlite3_bind_text(fStmt->fRes, npar + 1, value.Data(), -1, SQLITE_TRANSIENT);
+
+   return CheckBindError("SetTimestamp", res);
+}
diff --git a/test/Makefile b/test/Makefile
index ee7b1ba..1a3e168 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -274,28 +274,36 @@ STRESSHISTO   = stressHistogram.$(ObjSuf)
 STRESSHISTS   = stressHistogram.$(SrcSuf)
 STRESSHIST    = stressHistogram$(ExeSuf)
 
+ifeq ($(shell $(RC) --has-sqlite),yes)
+SQLITETESTO   = sqlitetest.$(ObjSuf)
+SQLITETESTS   = sqlitetest.$(SrcSuf)
+SQLITETEST    = sqlitetest$(ExeSuf)
+endif
+
 
-OBJS          = $(EVENTO) $(MAINEVENTO) $(EVENTMTO) $(HWORLDO) $(HSIMPLEO) $(MINEXAMO) \
+OBJS          = $(EVENTO) $(MAINEVENTO) $(EVENTMTO) $(HWORLDO) $(HSIMPLEO) \
+                $(MINEXAMO) \
                 $(TSTRINGO) $(TCOLLEXO) $(VVECTORO) $(VMATRIXO) $(VLAZYO) \
                 $(HELLOO) $(ACLOCKO) $(STRESSO) $(TBENCHO) $(BENCHO) \
                 $(STRESSSHAPESO) $(TCOLLBMO) $(STRESSGEOMETRYO) $(STRESSLO) \
-                $(STRESSGO) $(STRESSSPO) $(TESTBITSO)  \
+                $(STRESSGO) $(STRESSSPO) $(TESTBITSO) \
                 $(CTORTUREO) $(QPRANDOMO) $(THREADSO) $(STRESSVECO) \
-                $(STRESSMATHO) $(STRESSFITO) $(STRESSHISTOFITO) $(STRESSHEPIXO) \
-                $(STRESSENTRYLISTO) $(STRESSROOFITO) $(STRESSROOSTATSO) $(STRESSPROOFO) \
-                $(STRESSMATHMOREO) $(STRESSTMVAO) $(STRESSINTERPO) $(STRESSITERO) \
-                $(STRESSHISTO) $(STRESSGUIO)
-
-PROGRAMS      = $(EVENT) $(EVENTMTSO) $(HWORLD) $(HSIMPLE) $(MINEXAM) $(TSTRING) \
-                $(TCOLLEX) $(TCOLLBM) $(VVECTOR) $(VMATRIX) $(VLAZY) \
-                $(HELLOSO) $(ACLOCKSO) $(STRESS) $(TBENCHSO) $(BENCH) \
+                $(STRESSMATHO) $(STRESSFITO) $(STRESSHISTOFITO) \
+                $(STRESSHEPIXO) $(STRESSENTRYLISTO) $(STRESSROOFITO) \
+                $(STRESSROOSTATSO) $(STRESSPROOFO) $(STRESSMATHMOREO) \
+                $(STRESSTMVAO) $(STRESSINTERPO) $(STRESSITERO) \
+                $(STRESSHISTO) $(STRESSGUIO) $(SQLITETESTO)
+
+PROGRAMS      = $(EVENT) $(EVENTMTSO) $(HWORLD) $(HSIMPLE) $(MINEXAM) \
+                $(TSTRING) $(TCOLLEX) $(TCOLLBM) $(VVECTOR) $(VMATRIX) \
+                $(VLAZY) $(HELLOSO) $(ACLOCKSO) $(STRESS) $(TBENCHSO) $(BENCH) \
                 $(STRESSSHAPES) $(STRESSGEOMETRY) $(STRESSL) $(STRESSG) \
                 $(TESTBITS) $(CTORTURE) $(QPRANDOM) $(THREADS) $(STRESSSP) \
                 $(STRESSVEC) $(STRESSFIT) $(STRESSHISTOFIT) $(STRESSHEPIX) \
-                $(STRESSENTRYLIST) $(STRESSROOFIT) $(STRESSROOSTATS) $(STRESSPROOF) $(STRESSMATH) \
-                $(STRESSMATHMORE) $(STRESSTMVA) $(STRESSINTERP)  $(STRESSITER) \
-                $(STRESSHIST) $(STRESSGUI)
-
+                $(STRESSENTRYLIST) $(STRESSROOFIT) $(STRESSROOSTATS) \
+                $(STRESSPROOF) $(STRESSMATH) \
+                $(STRESSMATHMORE) $(STRESSTMVA) $(STRESSINTERP) $(STRESSITER) \
+                $(STRESSHIST) $(STRESSGUI) $(SQLITETEST)
 
 OBJS         += $(GUITESTO) $(GUIVIEWERO) $(TETRISO)
 PROGRAMS     += $(GUITEST) $(GUIVIEWER) $(TETRISSO)
@@ -702,12 +710,12 @@ else
 endif
 endif
 
-$(STRESSINTERP): $(STRESSINTERPO) 
+$(STRESSINTERP): $(STRESSINTERPO)
 		$(LD) $(LDFLAGS) $^ $(LIBS) $(OutPutOpt)$@
 		$(MT_EXE)
 		@echo "$@ done"
 
-$(STRESSITER):	$(STRESSITERO) 
+$(STRESSITER):	$(STRESSITERO)
 		$(LD) $(LDFLAGS) $^ $(LIBS) $(OutPutOpt)$@
 		$(MT_EXE)
 		@echo "$@ done"
@@ -717,6 +725,11 @@ $(STRESSHIST):  $(STRESSHISTO)
 		$(MT_EXE)
 		@echo "$@ done"
 
+$(SQLITETEST):  $(SQLITETESTO)
+		$(LD) $(LDFLAGS) $^ $(LIBS) $(OutPutOpt)$@
+		$(MT_EXE)
+		@echo "$@ done"
+
 clean:
 		@rm -f $(OBJS) $(TRACKMATHSRC) core *Dict.*
 
@@ -724,7 +737,7 @@ distclean:      clean
 		-@(mv -f stressRooStats_ref.root stressRooStats_ref.root- >/dev/null 2>&1;true)
 		@rm -f $(PROGRAMS) $(EVENTSO) $(EVENTLIB) *Dict.* *.def *.exp \
 		   *.root *.ps *.so *.lib *.dll *.d *.log .def so_locations \
-		   files/*
+		   files/* testdb.sqlite
 		@rm -rf cxx_repository
 		-@(mv -f stressRooStats_ref.root- stressRooStats_ref.root >/dev/null 2>&1;true)
 		- at cd RootShower && $(MAKE) distclean
diff --git a/test/sqlitetest.cxx b/test/sqlitetest.cxx
new file mode 100644
index 0000000..9574462
--- /dev/null
+++ b/test/sqlitetest.cxx
@@ -0,0 +1,215 @@
+#include <iostream>
+#include <iomanip>
+#include <unistd.h>
+
+#include "TSQLServer.h"
+#include "TSQLResult.h"
+#include "TSQLRow.h"
+#include "TSQLStatement.h"
+#include "TSQLTableInfo.h"
+#include "TTimeStamp.h"
+#include "TList.h"
+
+int main() {
+
+	// Create a new DB called testdb:
+	TSQLServer *serv=TSQLServer::Connect("sqlite://testdb.sqlite", "", "");
+	if (serv == NULL) {
+		std::cerr << "Connection failed!" << std::endl;
+		_exit(1);
+	}
+
+	// First, some debug-checks:
+	std::cout << "DB: " << serv->GetDB() << std::endl;
+	std::cout << "DBMS: " << serv->GetDBMS() << std::endl;
+	std::cout << "HOST: " << serv->GetHost() << std::endl;
+	std::cout << "PORT: " << serv->GetPort() << std::endl;
+	std::cout << "Info: " << serv->ServerInfo() << std::endl;
+
+	// Create table:
+	if ((serv!=0) && serv->IsConnected()) {
+		// create statement instance
+		TSQLStatement* stmt = serv->Statement("CREATE TABLE TESTTABLE (ID1 FOO, ID2 FOO, ID3 FOO, ID4 FOO, ID5 FOO, ID6 FOO, ID7 FOO, ID8 FOO, ID9 FOO, ID10 FOO)");
+		// process statement
+		stmt->Process();
+		// destroy object
+		delete stmt;
+	}
+
+	serv->StartTransaction();//Exec("BEGIN TRANSACTION;");
+
+	// Fill with data:
+	TSQLStatement* stmt = serv->Statement("INSERT INTO TESTTABLE (ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", 100);
+	std::cout << "statement pars: " << stmt->GetNumParameters() << std::endl;
+
+
+	for (int n=0;n<10;n++) {
+		if (stmt->NextIteration()) {
+			stmt->SetInt(0, n);
+			stmt->SetUInt(1, n);
+			stmt->SetLong(2, n);
+			stmt->SetULong64(3, n);
+			stmt->SetDate(4, 2013,1,n);
+			stmt->SetTime(5, 1,1,n);
+			stmt->SetDatime(6, 2013,1,n,1,1,n);
+			stmt->SetTimestamp(7, 2013,1,1,1,1,n,102+n);
+			TString foo;
+			foo.Form("testbinary %d", n);
+			void *binary=const_cast<char*>(foo.Data());
+			stmt->SetBinary(8, binary, foo.Length());
+			stmt->SetString(9, Form("%d", n), 200);
+		}
+	}
+
+	stmt->Process();
+	delete stmt;
+
+	serv->Commit();
+
+	delete serv;
+
+	std::cout << "Testing tool created DB with sample data. Now reopening and selecting all." << std::endl;
+
+	serv=TSQLServer::Connect("sqlite://testdb.sqlite", "", "");
+	if (serv == NULL) {
+		std::cerr << "Connection failed!" << std::endl;
+		_exit(1);
+	}
+
+	std::cout << "Select table names:" << std::endl;
+	TSQLResult *res=serv->GetTables(NULL, NULL);
+
+	int fields=res->GetFieldCount();
+	std::cout << "Table list has field count: " << fields << std::endl;
+
+	int rowcount=res->GetRowCount();
+	std::cout << "Table list has row count: " << rowcount << std::endl;
+
+	TSQLRow *row=NULL;
+	while ((row=res->Next()) != NULL) {
+		for (int i=0; i<fields; i++) {
+			std::cout << row->GetField(i);
+			TSQLResult *res2=serv->GetColumns(NULL, row->GetField(i), NULL);
+			if (res2 == NULL) continue;
+			std::cout << "|";
+			int fields2=res2->GetFieldCount();
+			std::cout << "Cols: " << fields2 << " ";
+			TSQLRow *row2=NULL;
+			while ((row2=res2->Next()) != NULL) {
+				std::cout << "(";
+				for (int ii=0; ii<fields2; ii++) {
+					if (row2->GetField(ii) == NULL) continue;
+					std::cout << row2->GetField(ii) << "|";
+				}
+				std::cout << ")";
+				delete row2;
+			}
+		}
+		std::cout << std::endl;
+		delete row;
+	}
+	delete res;
+	std::cout << std::endl;
+
+	std::cout << "Alternate way using GetTablesList:" << std::endl;
+	serv->GetTablesList()->Print();
+
+	std::cout << "Completed listing tables. Now selecting * from testtable, first using Query() and string output:" << std::endl;
+	row=NULL;
+	res=serv->Query("SELECT * from TESTTABLE;");
+	fields=res->GetFieldCount();
+	for (int i=0; i<fields; i++) {
+		std::cout << "|" << std::setw(19) << res->GetFieldName(i) << "|";
+	}
+	std::cout << std::endl;
+	while ((row=res->Next()) != NULL) {
+		for (int i=0; i<fields; i++) {
+			std::cout << "|" << std::setw(19) << row->GetField(i) << "|";
+		}
+		std::cout << std::endl;
+		delete row;
+	}
+	delete res;
+	std::cout << std::endl;
+
+	std::cout << "Now using TSQLStatement-methods with appropriate types:" << std::endl;
+
+	stmt = serv->Statement("SELECT * FROM TESTTABLE;", 100);
+	// process statement
+	if (stmt->Process()) {
+		std::cout << "iteration..." << std::endl;
+		// store result of statement in buffer
+		stmt->StoreResult();
+
+		// display info about selected field
+		std::cout << "NumFields = " << stmt->GetNumFields() << std::endl;
+		for (int n=0;n<stmt->GetNumFields();n++) {
+			std::cout << "|" << std::setw(19) << stmt->GetFieldName(n) << "|";
+		}
+		std::cout << std::endl;
+
+		// extract rows one after another
+		while (stmt->NextResultRow()) {
+			Int_t id1 = stmt->GetInt(0);
+			std::cout << "|" << std::setw(19) << id1 << "|";
+
+			UInt_t id2 = stmt->GetUInt(1);
+			std::cout << "|" << std::setw(19) << id2 << "|";
+
+			Long_t id3 = stmt->GetLong(2);
+			std::cout << "|" << std::setw(19) << id3 << "|";
+
+			ULong64_t id4 = stmt->GetULong64(3);
+			std::cout << "|" << std::setw(19) << id4 << "|";
+
+			Int_t year=0, month=0, day=0, hour=0, minute=0, second=0, frac=0;
+
+			stmt->GetDate(4, year, month, day);
+			TString id5;
+			id5.Form("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, 0, 0, 0);
+			std::cout << "|" << std::setw(19) << id5 << "|";
+
+			stmt->GetTime(5, hour, minute, second);
+			TString id6;
+			id6.Form("%04d-%02d-%02d %02d:%02d:%02d", 2000, 01, 01, hour, minute, second);
+			std::cout << "|" << std::setw(19) << id6 << "|";
+
+			stmt->GetDatime(6, year, month, day, hour, minute, second);
+			TString id7;
+			id7.Form("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
+			std::cout << "|" << std::setw(19) << id7 << "|";
+
+			stmt->GetTimestamp(7, year, month, day, hour, minute, second, frac);
+			TTimeStamp ts(year,month,day,hour,minute,second);
+			TString id8;
+			// Frac is in milliseconds for SQLite, thus use %3d here.
+			id8.Form("%04d-%02d-%02d %02d:%02d:%02d.%3d", year, month, day, hour, minute, second, frac);
+			std::cout << "|" << std::setw(23) << id8 << "|";
+
+			void* id9 = new unsigned char[1];
+			Long_t binSize=1;
+			stmt->GetBinary(8, id9, binSize);
+			char* id9str = new char[binSize+1];
+			memcpy(id9str, id9, binSize);
+			id9str[binSize]='\0';
+			std::cout << "|" << std::setw(19) << id9str << "|";
+			delete [] (unsigned char*) id9;
+			delete [] id9str;
+
+			TString id10 = stmt->GetString(9);
+			std::cout << "|" << std::setw(19) << id10 << "|";
+
+			std::cout << std::endl;
+		}
+	}
+	delete stmt;
+
+	// Test tableinfo:
+	std::cout << "Tableinfo:" << std::endl;
+	TSQLTableInfo *ti=serv->GetTableInfo("TESTTABLE");
+	ti->Print();
+
+	delete serv;
+
+	return 0;
+}
diff --git a/test/stressGraphics.ref b/test/stressGraphics.ref
index 43b06a0..c32be75 100644
--- a/test/stressGraphics.ref
+++ b/test/stressGraphics.ref
@@ -4,19 +4,19 @@ Test#   PS1Ref#   PS1Err#   PDFRef#   PDFErr#   GIFRef#   GIFErr#   JPGRef#   JP
     3       452        50     12632        50      4797       350     11232      4200      3796     10700       492        50
     4     23617      1500     19255       100     43077     12000    143320    123000     45665     11000     24908      1500
     5      1025        50     12802        50     19715      2900     33468      9900     30846      5000      1072        50
-    6       430        50     12616        50      4041       100      9322        50      4998       100       471        50
+    6       430        50     12616        50      4041       100      9558        50      5325       100       471        50
     7      4980        50     13821        50      8215       310     16143      1300     12230       500      5011        70
     8      5442        80     13415        50      9599       150     18430       400     12398       200      5469        80
     9      9253       100     14310        50      9664       400     19851      2400     12199       300      9449       100
-   10      8863        70     13539       100     13607       200     24236       150     23280       200      8894        70
+   10      8863        70     13539       100     14622       200     25627       150     25264       200      8894        70
    11     12971       100     14377        50     20508       700     34063       300     32033       300     12864       150
-   12      7674       100     13553        50     27519       700     82434       300     36703       300      7720       150
-   13      5600       100     13242       100      9465       250     16427       100     14426       200      5638       100
-   14  21117526    500000     12926       100     15663       800     23076      9500     24907       900  21117691    500000
+   12      7674       100     13553        50     27519       700     83557       300     38505       300      7720       150
+   13      5600       100     13242       100      9805       250     16881       100     15063       200      5638       100
+   14  21117526    500000     12926       100     15663       800     23076      9500     25987       900  21117691    500000
    15     15690      5000     17179       100     12037       800     23076      9500     15202       900     10437      5000
    16     27201       400     22976       200     25845       800     44462     11000     30062      1500     36287       400
-   17     19623       400     21387       100     12050       800     27511     11000     16794       500     19901       400
-   18     15205       100     19204       100     12364       550     27187     10300     15715       350     15236       100
+   17     19623       400     21387       100     12050       800     27511     11000     16280       500     19901       400
+   18     15205       100     19204       100     12943       550     27187     10300     16309       350     15236       100
    19     22521       300     42774       150     21207      6800     43868     17000     19232     11000     22729       300
    20      3664       600     14437       100      9623       900     19824      6300     10396       900      4220       600
    21     17464       600     13832       100     33543      5500     49440      6300     37586      9000      5938       600
@@ -30,16 +30,16 @@ Test#   PS1Ref#   PS1Err#   PDFRef#   PDFErr#   GIFRef#   GIFErr#   JPGRef#   JP
    29     30615      8200     27299       100     29010      5900     50520     18200     35724      5400     36690      8200
    30   3304592       100    697155       100    155478     32000     62688     19000    123056      7000         0         0
    31    315620      5500    433372      1000     34942      8300     65532     27800     37314     12000    325256      5500
-   32     35526       300     16815       200     23074      2200     47408     12700     33739      3700     35478       300
+   32     35526       300     16815       200     25333      2200     47408     12700     33739      3700     35478       300
    33     92810       750     59119       100     41853      6200     76094     38000     54717     11000     93584       800
-   34    239856      6500    116429       300     38898     10400     62719     34100     45592     14000    246031      6500
+   34    266472      6500    121119       300     38898     10400     62719     34100     45592     14000    274162      6500
    35    297200      5000    154995       750     43638      6300     65828     31800     53934      6500    301968      5000
    36   1479662     35000    757137       200     79412      3400     71417      9900    102567      3500   1507071     35000
    37    298263      2000    170884      4000     38621      8600     38425     13500     65177     18100    300165      2000
    38     23594       200     49391       100     47205      3900     36524     11800    103480      8000     23426       200
    39     15025      1500     29289       500     34091      1500     42525     11300     33336      3900     14787      1500
    40    254604      5000    376027      7000     34608      5000     55666     30400     46534      6500    259594      5000
-   41      4846        50     14075       100     24281       100     33004       150     25412       100      4877        50
+   41      4846        50     14075       100     24281       100     33239       150     25636       100      4877        50
    42   1435879    150000     12837       100     96029      4000     25972       100    359846     15000   1085792    250000
    43      5412       200     16343       200     25899      3500     40706     14000     20980      4000         0         0
    44      5723       700     15762       200     13799      2600     31626     11000     16916      3200      5670       800
diff --git a/test/stressProof.cxx b/test/stressProof.cxx
index b3d8bad..1c7994c 100644
--- a/test/stressProof.cxx
+++ b/test/stressProof.cxx
@@ -203,7 +203,7 @@ int stressProof(const char *url = 0,
                 const char *h1src = 0, const char *eventsrc = 0,
                 Bool_t dryrun = kFALSE, Bool_t showcpu = kFALSE,
                 Bool_t clearcache = kFALSE, Bool_t useprogress = kTRUE,
-                const char *tutdir = 0, Bool_t cleanlog = kFALSE);
+                const char *tutdir = 0, Bool_t cleanlog = kFALSE, Bool_t keeplog = kTRUE);
 
 //_____________________________batch only_____________________
 #ifndef __CINT__
@@ -241,10 +241,12 @@ int main(int argc,const char *argv[])
       printf("                 The log file path can be also passed via the env STRESSPROOF_LOGFILE.\n");
       printf("                 In case of failure, the log files of the nodes (master and workers) are saved into\n");
       printf("                 a file called <logfile>.nodes .\n");
-      printf("   -cleanlog     Delete the logfile specified via '-l' in case of a successful run; by default\n");
+      printf("   -c,-cleanlog  Delete the logfile specified via '-l' in case of a successful run; by default\n");
       printf("                 the file specified by '-l' is kept in all cases (default log files are deleted\n");
       printf("                 on success); adding this switch allows to keep a user-defined log file only\n");
       printf("                 in case of error.\n");
+      printf("   -k,-keeplog   Keep all logfiles, including the ones fro the PROOF nodes (in one single file).\n");
+      printf("                 The paths are printed on the screen.\n");
       printf("   -dyn          run the test in dynamicStartup mode\n");
       printf("   -ds           force the dataset test if skipped by default\n");
       printf("   -t tests      run only tests in the comma-separated list and those from which they\n");
@@ -286,6 +288,7 @@ int main(int argc,const char *argv[])
    Bool_t clearcache = kFALSE;
    Bool_t useprogress = kTRUE;
    Bool_t cleanlog = kFALSE;
+   Bool_t keeplog = kFALSE;
    const char *logfile = 0;
    const char *h1src = 0;
    const char *eventsrc = 0;
@@ -320,9 +323,12 @@ int main(int argc,const char *argv[])
             logfile = argv[i+1];
             i += 2;
          }
-      } else if (!strncmp(argv[i],"-cleanlog",11)) {
+      } else if (!strncmp(argv[i],"-c",2) || !strncmp(argv[i],"-cleanlog",11)) {
          cleanlog = kTRUE;
          i++;
+      } else if (!strncmp(argv[i],"-k",2) || !strncmp(argv[i],"-keeplog",10)) {
+         keeplog = kTRUE;
+         i++;
       } else if (!strncmp(argv[i],"-v",2)) {
          // For backward compatibility
          if (!strncmp(argv[i],"-vv",3)) verbose = "2";
@@ -398,7 +404,7 @@ int main(int argc,const char *argv[])
    }
 
    int rc = stressProof(url, tests, nWrks, verbose, logfile, gDynamicStartup, gSkipDataSetTest,
-                        h1src, eventsrc, dryrun, showcpu, clearcache, useprogress, tutdir, cleanlog);
+                        h1src, eventsrc, dryrun, showcpu, clearcache, useprogress, tutdir, cleanlog, keeplog);
 
    gSystem->Exit(rc);
 }
@@ -737,6 +743,7 @@ Int_t PT_Friends(void *, RunTimes &);
 Int_t PT_SimpleByObj(void *, RunTimes &);
 Int_t PT_H1ChainByObj(void *, RunTimes &);
 Int_t PT_AssertTutorialDir(const char *tutdir);
+Int_t PT_MultiTrees(void *, RunTimes &);
 Int_t PT_OutputHandlingViaFile(void *, RunTimes &);
 
 // Auxilliary functions
@@ -788,7 +795,7 @@ int stressProof(const char *url, const char *tests, Int_t nwrks,
                 const char *verbose, const char *logfile, Bool_t dyn, Bool_t skipds,
                 const char *h1src, const char *eventsrc,
                 Bool_t dryrun, Bool_t showcpu, Bool_t clearcache, Bool_t useprogress,
-                const char *tutdir, Bool_t cleanlog)
+                const char *tutdir, Bool_t cleanlog, Bool_t keeplog)
 {
    printf("******************************************************************\n");
    printf("*  Starting  P R O O F - S T R E S S  suite                      *\n");
@@ -970,6 +977,10 @@ int stressProof(const char *url, const char *tests, Int_t nwrks,
       printf("*  Clearing cache associated to files, if possible ...          **\n");
       printf("******************************************************************\n");
    }
+   if (keeplog && gverbose > 0) {
+      printf("*  Keeping logfiles (paths specified at the end)                **\n");
+      printf("******************************************************************\n");
+   }
    //
    // Reset dataset settings
    gEnv->SetValue("Proof.DataSetManager","");
@@ -1029,11 +1040,13 @@ int stressProof(const char *url, const char *tests, Int_t nwrks,
                                &PT_POFNtuple, (void *)&pfoptm, "1", "ProofNtuple", kTRUE));
    // Test TProofOutputFile technology for dataset creation (tests TProofDraw too)
    testList->Add(new ProofTest("File-resident output: create dataset", 22, &PT_POFDataset, 0, "1", "ProofNtuple", kTRUE));
+   // Test selecting different TTrees in same files
+   testList->Add(new ProofTest("File-resident output: multi trees", 23, &PT_MultiTrees, 0, "1,22", "ProofNtuple", kTRUE));
    // Test TPacketizerFile and TTree friends in separate files
-   testList->Add(new ProofTest("TTree friends (and TPacketizerFile)", 23, &PT_Friends, 0, "1", "ProofFriends,ProofAux", kTRUE));
+   testList->Add(new ProofTest("TTree friends (and TPacketizerFile)", 24, &PT_Friends, 0, "1", "ProofFriends,ProofAux", kTRUE));
    // Test TPacketizerFile and TTree friends in same file
    Bool_t sameFile = kTRUE;
-   testList->Add(new ProofTest("TTree friends, same file", 24,
+   testList->Add(new ProofTest("TTree friends, same file", 25,
                                &PT_Friends, (void *)&sameFile, "1", "ProofFriends,ProofAux", kTRUE));
 
    // Test handling output via file
@@ -1098,7 +1111,7 @@ int stressProof(const char *url, const char *tests, Int_t nwrks,
             printf("*  Non-positive test number: %d\n", test);
             continue;
          }
-         const int tmx = 26;
+         const int tmx = PT_NUMTEST;
          if (test > tmx) {
             printf("*                                                               **\r");
             printf("*  Unknown test number: %d\n", test);
@@ -1218,9 +1231,10 @@ int stressProof(const char *url, const char *tests, Int_t nwrks,
       }
 
    // Done
+   Bool_t kept = ((usedeflog || cleanlog) && !keeplog) ? kFALSE : kTRUE;
    if (failed) {
-      Bool_t kept = kTRUE;
-      if (usedeflog && !gROOT->IsBatch()) {
+      kept = kTRUE;
+      if (usedeflog && !gROOT->IsBatch() && !keeplog) {
          const char *answer = Getline(" Some tests failed: would you like to keep the log file (N,Y)? [Y] ");
          if (answer && (answer[0] == 'N' || answer[0] == 'n')) {
             // Remove log file
@@ -1228,29 +1242,34 @@ int stressProof(const char *url, const char *tests, Int_t nwrks,
             kept = kFALSE;
          }
       }
-      if (kept) {
-         TString logfiles(glogfile);
-         // Save also the logs from the workers
-         TProofMgr *mgr = gProof->GetManager();
-         if (mgr) {
-            TProofLog *pl = mgr->GetSessionLogs();
-            if (pl) {
-               logfiles += ".nodes";
-               pl->Retrieve("*",  TProofLog::kAll, logfiles);
-               SafeDelete(pl);
-            } else {
-               printf("+++ Warning: could not get the session logs\n");
-            }
-         } else {
-            printf("+++ Warning: could not attach to manager to get the session logs\n");
-         }         
-         printf("* Main log file kept at %s (Proof logs in %s)\n", glogfile.Data(), logfiles.Data());
-      }
    } else {
       printf("* All registered tests have been passed  :-)                     *\n");
+   }
+
+   if (kept) {
+      TString logfiles(glogfile);
+      // Save also the logs from the workers
+      TProofMgr *mgr = gProof ? gProof->GetManager() : 0;
+      if (mgr) {
+         gSystem->RedirectOutput(glogfile, "a", &gRH);
+         TProofLog *pl = mgr->GetSessionLogs();
+         if (pl) {
+            logfiles += ".nodes";
+            pl->Retrieve("*",  TProofLog::kAll, logfiles);
+            gSystem->RedirectOutput(0, 0, &gRH);
+            SafeDelete(pl);
+         } else {
+            gSystem->RedirectOutput(0, 0, &gRH);
+            printf("+++ Warning: could not get the session logs\n");
+         }
+      } else {
+         printf("+++ Warning: could not attach to manager to get the session logs\n");
+      }         
+      printf("******************************************************************\n");
+      printf(" Main log file kept at %s (Proof logs in %s)\n", glogfile.Data(), logfiles.Data());
+   } else {
       // Remove log file if not passed by the user
-      if (usedeflog || cleanlog)
-         gSystem->Unlink(glogfile);
+      gSystem->Unlink(glogfile);
    }
 
    printf("******************************************************************\n");
@@ -1270,14 +1289,14 @@ int stressProof(const char *url, const char *tests, Int_t nwrks,
          }
       if (navg > 0) avgmarks /= navg;
       
-      gProof->GetStatistics((verbose > 0));
+      gProof->GetStatistics((gverbose > 0));
       // Reference time measured on a HP DL580 24 core (4 x Intel(R) Xeon(R) CPU X7460
       // @ 2.132 GHz, 48GB RAM, 1 Gb/s NIC) with 4 workers.
       const double reftime = 70.169;
       double glbmarks = (gProof->GetRealTime() > 0) ? 1000 * reftime / gProof->GetRealTime() : -1;
-      printf(" ROOTMARKS = %.2f (overall: %.2f) ROOT version: %s\t%s@%d\n",
+      printf(" ROOTMARKS = %.2f (overall: %.2f) ROOT version: %s\t%s@%s\n",
              avgmarks, glbmarks, gROOT->GetVersion(),
-             gROOT->GetSvnBranch(), gROOT->GetSvnRevision());
+             gROOT->GetGitBranch(), gROOT->GetGitCommit());
       // Average from the single tests
       printf("******************************************************************\n");
    }
@@ -1740,9 +1759,6 @@ Int_t PT_CheckSimpleNtuple(TQueryResult *qr, Long64_t nevt, const char *dsname)
    // Clear dsname
    gProof->ClearData(TProof::kDataset |TProof::kForceClear, dsname);
    
-   // Clear dsname
-   gProof->ClearData(TProof::kDataset |TProof::kForceClear, dsname);
-   
    // Done
    PutPoint();
    return 0;
@@ -2008,8 +2024,8 @@ Int_t PT_CheckDataset(TQueryResult *qr, Long64_t nevt)
    Int_t rch1s = 0;
    TString emsg;
    // Check the histogram entries and mean values
-   Float_t hent[3] = { .607275, .367860, .067741};
-   Double_t hmea[3] = { 2.003304, 1.995983 , 3.044178};
+   Float_t hent[3] = { .607700, .364900, .065100};
+   Double_t hmea[3] = { 2.022, 2.046 , 3.043};
    Double_t prec = 10. / TMath::Sqrt(nevt);  // ~10 sigma ... conservative
    for (Int_t i = 0; i < 3; i++) {
       Double_t ent = h1s[i]->GetEntries();
@@ -2031,7 +2047,6 @@ Int_t PT_CheckDataset(TQueryResult *qr, Long64_t nevt)
 
    // Cleanup
    for (Int_t i = 0; i < 3; i++) delete h1s[i];   
-   gProof->RemoveDataSet(dsname);
 
    // Check the result
    if (rch1s != 0) {
@@ -2186,7 +2201,7 @@ Int_t PT_Open(void *args, RunTimes &tt)
    }
    
    // Check if it is in dynamic startup mode
-   Int_t dyn;
+   Int_t dyn = 0;
    p->GetRC("Proof.DynamicStartup", dyn);
    if (dyn != 0) gDynamicStartup = kTRUE;
 
@@ -3852,31 +3867,7 @@ Int_t PT_POFNtuple(void *opts, RunTimes &tt)
    }
 
    // Output file
-   TString fout = TString::Format("%s/ProofNtuple.root", gSystem->WorkingDirectory());
-   // Cleanup any existing instance of the output file
-   gSystem->Unlink(fout);
-
-   if (!gLocalCluster) {
-      // Setup a local basic xrootd to receive the file
-      Bool_t xrdok = kFALSE;
-      Int_t port = 9000;
-      while (port < 9010) {
-         if (checkXrootdAt(port) != 1) {
-            if (startXrootdAt(port, gSystem->WorkingDirectory(), kTRUE) == 0) {
-               xrdok = kTRUE;
-               break;
-            }
-         }
-         port++;
-      }
-      if (!xrdok) {
-         printf(" >>> PT_POFNtuple: could not start basic xrootd on ports 9000-9009 - skip this test");
-         return 1;
-      }
-      fout.Insert(0, TString::Format("root://%s:%d/", TUrl(gSystem->HostName()).GetHostFQDN(), port));
-      // Make a copy of the files on the master before merging
-      gProof->AddInput(new TNamed("PROOF_OUTPUTFILE_LOCATION", "LOCAL"));
-   }
+   TString fout("<datadir>/ProofNtuple.root");
    gProof->AddInput(new TNamed("PROOF_OUTPUTFILE", fout.Data()));
 
    // We use the 'NtpRndm' for a fixed values of randoms; we need to send over the file
@@ -3926,10 +3917,19 @@ Int_t PT_POFDataset(void *, RunTimes &tt)
       printf("\n >>> Test failure: no PROOF session found\n");
       return -1;
    }
+   
+   const char *dsname = "testNtuple";
+   // Clean-up any existing dataset with that name
+   if (gProof->ExistsDataSet(dsname)) gProof->RemoveDataSet(dsname);
 
    // Ask for registration of the dataset (the default is the the TFileCollection is return
    // without registration; the name of the TFileCollection is the name of the dataset
-   gProof->SetParameter("SimpleNtuple.root","testNtuple");
+   gProof->SetParameter("SimpleNtuple.root", dsname);
+
+   // We use the 'NtpRndm' for a fixed values of randoms; we need to send over the file
+   gProof->SetInputDataFile(gNtpRndm);
+   // Set the related parameter
+   gProof->SetParameter("PROOF_USE_NTP_RNDM","yes");
 
    // Define the number of events and histos
    Long64_t nevt = 1000000;
@@ -3951,6 +3951,8 @@ Int_t PT_POFDataset(void *, RunTimes &tt)
    // Remove any setting related to submergers
    gProof->DeleteParameters("PROOF_NTUPLE_DONT_PLOT");
    gProof->DeleteParameters("SimpleNtuple.root");
+   gProof->DeleteParameters("PROOF_USE_NTP_RNDM");
+   gProof->SetInputDataFile(0);
 
    // The runtimes
    PT_GetLastProofTimes(tt);
@@ -3961,6 +3963,128 @@ Int_t PT_POFDataset(void *, RunTimes &tt)
 }
 
 //_____________________________________________________________________________
+Int_t PT_MultiTrees(void *, RunTimes &tt)
+{
+   // Test processing of multiple trees in the same files
+
+   // Checking arguments
+   PutPoint();
+   if (!gProof) {
+      printf("\n >>> Test failure: no PROOF session found\n");
+      return -1;
+   }
+
+   const char *dsname = "testNtuple";
+   // There must be a dataset 'testNtuple' already registered and validated
+   if (!gProof->ExistsDataSet(dsname)) {
+      printf("\n >>> Test failure: dataset '%s' does not exist\n", dsname);
+      return -1;
+   }
+
+   // Get the associated TFileCollection
+   TFileCollection *fc = gProof->GetDataSet(dsname);
+   if (!fc) {
+      printf("\n >>> Test failure: unable to get TFileCollection for dataset '%s'\n", dsname);
+      return -1;
+   }
+
+   // Now create a TDSet out of the TFileCollection
+   TDSet *dset = new TDSet("testntps", "ntuple", "/", "TTree");
+   TChain *ch1 = new TChain("ntuple");
+   TChain *ch2 = new TChain("ntuple2");
+   TIter nxf(fc->GetList());
+   TFileInfo *fi = 0;
+   while ((fi = (TFileInfo *) nxf())) {
+      dset->Add(fi->GetCurrentUrl()->GetUrl());
+      ch1->Add(fi->GetCurrentUrl()->GetUrl());
+      ch2->Add(fi->GetCurrentUrl()->GetUrl());
+   }
+
+   // Check the ntuple content by filling some histos
+   TH1F *h1s[2] = {0};
+   h1s[0] = new TH1F("h1_1", "3*px+2 with px**2+py**2>1", 50, -15., 15.);
+   h1s[1] = new TH1F("h1_2", "vx**2+vy**2 with abs(vz)<.1", 50, 0., 10.);
+
+   Int_t rch1s = 0;
+   TString emsg;
+   const char *type[3] = { "dsname", "TDSet", "TChain" };
+   for (Int_t j = 0; j < 3; j++) {
+
+      PutPoint();
+
+      if (j == 0) {
+         // Fill the first histo from the first ntuple
+         gProof->SetDataSetTreeName(dsname, "ntuple");
+         {  SwitchProgressGuard spg;
+            gProof->DrawSelect(dsname, "3*px+2>>h1_1", "px*px+py*py>1");
+         }
+         // Fill the second histo from the second ntuple
+         gProof->SetDataSetTreeName(dsname, "ntuple2");
+         {  SwitchProgressGuard spg;
+            gProof->DrawSelect(dsname, "vx*vx+vy*vy>>h1_2", "vz>-0.1&&vz<0.1");
+         }
+      } else if (j == 1) {
+         // Fill the first histo from the first ntuple
+         {  SwitchProgressGuard spg;
+            gProof->DrawSelect(dset, "3*px+2>>h1_1", "px*px+py*py>1");
+         }
+         // Fill the second histo from the second ntuple
+         dset->SetObjName("ntuple2");
+         {  SwitchProgressGuard spg;
+            gProof->DrawSelect(dset, "vx*vx+vy*vy>>h1_2", "vz>-0.1&&vz<0.1");
+         }
+      } else {
+         // Fill the first histo from the first ntuple
+         {  SwitchProgressGuard spg;
+            ch1->Draw("3*px+2>>h1_1", "px*px+py*py>1");
+         }
+         // Fill the second histo from the second ntuple
+         {  SwitchProgressGuard spg;
+            ch2->Draw("vx*vx+vy*vy>>h1_2", "vz>-0.1&&vz<0.1");
+         }
+      }
+
+      rch1s = 0;
+      // Check the histogram entries and mean values
+      Int_t hent[2] = { 607700, 96100};
+      Double_t hmea[2] = { 2.022, 1.859};
+      for (Int_t i = 0; i < 2; i++) {
+         if ((Int_t)(h1s[i]->GetEntries()) != hent[i]) {
+            emsg.Form("%s: '%s' histo: wrong number of entries (%d: expected %d)",
+                      type[j], h1s[i]->GetName(), (Int_t)(h1s[i]->GetEntries()), hent[i]);
+            rch1s = -1;
+            break;
+         }
+         if (TMath::Abs((h1s[i]->GetMean() - hmea[i]) / hmea[i]) > 0.001) {
+            emsg.Form("%s: '%s' histo: wrong mean (%f: expected %f)",
+                      type[j], h1s[i]->GetName(), h1s[i]->GetMean(), hmea[i]);
+            rch1s = -1;
+            break;
+         }
+      }
+   }
+
+   // Cleanup
+   for (Int_t i = 0; i < 2; i++) delete h1s[i];
+
+   // Check the result
+   if (rch1s != 0) {
+      printf("\n >>> Test failure: %s\n", emsg.Data());
+      return -1;
+   }
+
+   // Clean-up
+   gProof->RemoveDataSet(dsname);
+
+   // The runtimes
+   PT_GetLastProofTimes(tt);
+
+   // Check the results
+   PutPoint();
+   return rch1s;
+}
+
+//_____________________________________________________________________________
 Int_t PT_Friends(void *sf, RunTimes &tt)
 {
    // Test processing of TTree friends in PROOF
diff --git a/test/stressRooFit.cxx b/test/stressRooFit.cxx
index 4935b63..d454b73 100644
--- a/test/stressRooFit.cxx
+++ b/test/stressRooFit.cxx
@@ -61,6 +61,7 @@ void StatusPrint(Int_t id,const TString &title,Int_t status)
 //______________________________________________________________________________
 Int_t stressRooFit(const char* refFile, Bool_t writeRef, Int_t doVerbose, Int_t oneTest, Bool_t dryRun, Bool_t doDump, Bool_t doTreeStore)
 {
+  Int_t retVal = 0;
   // Save memory directory location
   RooUnitTest::setMemDir(gDirectory) ;
 
@@ -73,7 +74,7 @@ Int_t stressRooFit(const char* refFile, Bool_t writeRef, Int_t doVerbose, Int_t
     if (TString(refFile).Contains("http:")) {
       if (writeRef) {
 	cout << "stressRooFit ERROR: reference file must be local file in writing mode" << endl ;
-	return kFALSE ;
+	return 1;
       }
       fref = new TWebFile(refFile) ;
     } else {
@@ -81,7 +82,7 @@ Int_t stressRooFit(const char* refFile, Bool_t writeRef, Int_t doVerbose, Int_t
     }
     if (fref->IsZombie()) {
       cout << "stressRooFit ERROR: cannot open reference file " << refFile << endl ;
-      return kFALSE ;
+      return 1;
     }
   }
 
@@ -177,7 +178,10 @@ Int_t stressRooFit(const char* refFile, Bool_t writeRef, Int_t doVerbose, Int_t
       if (doDump) {
 	(*iter)->setDebug(kTRUE) ;
       }
-      StatusPrint( i,(*iter)->GetName(),(*iter)->isTestAvailable()?(*iter)->runTest():-1);
+      Int_t status = (*iter)->isTestAvailable()?(*iter)->runTest():-1;
+      StatusPrint( i,(*iter)->GetName(), status);
+      // increment retVal for every failed test
+      if (!status) ++retVal;
     }
     delete (*iter) ;
     i++ ;
@@ -236,7 +240,7 @@ Int_t stressRooFit(const char* refFile, Bool_t writeRef, Int_t doVerbose, Int_t
   delete gBenchmark ;
   gBenchmark = 0 ;
 
-  return 0;
+  return retVal;
 }
 
 //_____________________________batch only_____________________
@@ -335,13 +339,9 @@ int main(int argc,const char *argv[])
     cout << "stressRooFit: WARNING running in write mode, but reference file is web file, writing local file instead: " << refFileName << endl ;
   }
 
-  // Disable caching of complex error function calculation, as we don't 
-  // want to write out the cache file as part of the validation procedure
-  RooMath::cacheCERF(kFALSE) ;
-
   gBenchmark = new TBenchmark();
-  stressRooFit(refFileName.c_str(),doWrite,doVerbose,oneTest,dryRun,doDump,doTreeStore);  
-  return 0;
+  Int_t retVal = stressRooFit(refFileName.c_str(),doWrite,doVerbose,oneTest,dryRun,doDump,doTreeStore);  
+  return retVal;
 }
 
 #endif
diff --git a/tree/tree/inc/TBranchElement.h b/tree/tree/inc/TBranchElement.h
index 082bebc..40b6a13 100644
--- a/tree/tree/inc/TBranchElement.h
+++ b/tree/tree/inc/TBranchElement.h
@@ -113,7 +113,6 @@ protected:
    virtual void             InitializeOffsets();
    virtual void             InitInfo();
    Bool_t                   IsMissingCollection() const;
-   TClass                  *GetCurrentClass(); // Class referenced by transient description
    TClass                  *GetParentClass(); // Class referenced by fParentName
    TStreamerInfo           *GetInfoImp() const;
    void                     ReleaseObject();
@@ -181,6 +180,7 @@ public:
    virtual TClass          *GetClass() const { return fBranchClass; }
    virtual const char      *GetClonesName() const { return fClonesName.Data(); }
    TVirtualCollectionProxy *GetCollectionProxy();
+   TClass                  *GetCurrentClass(); // Class referenced by transient description
    virtual Int_t            GetEntry(Long64_t entry = 0, Int_t getall = 0);
    virtual Int_t            GetExpectedType(TClass *&clptr,EDataType &type);
            const char      *GetIconName() const;
@@ -222,6 +222,20 @@ public:
    virtual void             SetType(Int_t btype) { fType = btype; }
    virtual void             UpdateFile();
 
+   enum EBranchElementType {
+      kLeafNode = 0,
+      kBaseClassNode = 1,  // -- We are a base class element.
+                           // Note: This does not include an STL container class which is
+                           //        being used as a base class because the streamer element
+                           //        in that case is not the base streamer element it is the
+                           //        STL streamer element.
+      kObjectNode = 2,
+      kClonesNode = 3,
+      kSTLNode = 4,
+      kClonesMemberNode = 31,
+      kSTLMemberNode = 41
+   };
+
    ClassDef(TBranchElement,9)  // Branch in case of an object
 };
 
diff --git a/tree/tree/src/TBranchBrowsable.cxx b/tree/tree/src/TBranchBrowsable.cxx
index c5d87ad..21a6cd1 100644
--- a/tree/tree/src/TBranchBrowsable.cxx
+++ b/tree/tree/src/TBranchBrowsable.cxx
@@ -666,13 +666,19 @@ Int_t TNonSplitBrowsable::GetBrowsables(TList& li, const TBranch* branch,
          if (!clElements) continue;
 
          // now loop over the class's streamer elements
-         streamerInfo= clElements->GetStreamerInfo();
-         TIter iElem(streamerInfo->GetElements());
-         TStreamerElement* elem=0;
-         while ((elem=(TStreamerElement*)iElem())) {
-            TNonSplitBrowsable* nsb=new TNonSplitBrowsable(elem, branch, parent);
-            li.Add(nsb);
-            numAdded++;
+         streamerInfo = clElements->GetStreamerInfo();
+         if (streamerInfo) {
+            TIter iElem(streamerInfo->GetElements());
+            TStreamerElement* elem=0;
+            while ((elem=(TStreamerElement*)iElem())) {
+               TNonSplitBrowsable* nsb=new TNonSplitBrowsable(elem, branch, parent);
+               li.Add(nsb);
+               numAdded++;
+            }
+         } else {
+            ::Error("TNonSplitBrowsable::GetBrowsables",
+                    "Missing the StreamerInfo for the class \"%s\" for the branch \"%s\" in the TTree \"%s\".",
+                    clElements->GetName(), branch->GetName(), branch->GetTree()->GetName());
          }
       } else {
          // we have a basic streamer element
diff --git a/tree/tree/src/TBranchElement.cxx b/tree/tree/src/TBranchElement.cxx
index b51c06f..2615eca 100644
--- a/tree/tree/src/TBranchElement.cxx
+++ b/tree/tree/src/TBranchElement.cxx
@@ -1972,7 +1972,6 @@ void TBranchElement::InitInfo()
                for (size_t i = 0; i < ndata; ++i) {
                   if (((TStreamerElement*) elems[i]) == elt) {
                      if (elt->TestBit (TStreamerElement::kCache)
-                         && elt->TestBit(TStreamerElement::kRepeat)
                          && (i+1) < ndata
                          && s == ((TStreamerElement*) elems[i])->GetName())
                      {
@@ -1982,7 +1981,11 @@ void TBranchElement::InitInfo()
                         // ReadLeaves).
                         // fID = i+1;
                         fID = i;
-                        fIDs.push_back(fID+1);
+                        if (elt->TestBit(TStreamerElement::kRepeat)) {
+                           fIDs.push_back(fID+1);
+                        } else if (((TStreamerElement*) elems[i+1])->TestBit(TStreamerElement::kWrite)) {
+                           fIDs.push_back(fID+1);
+                        }
                      } else {
                         fID = i;
                      }
@@ -2095,7 +2098,39 @@ TVirtualCollectionProxy* TBranchElement::GetCollectionProxy()
          className = se->GetTypeName();
       }
       TClass* cl = TClass::GetClass(className);
+      if (!cl) {
+         // The TClass was not created but we do know (since it
+         // is used as a collection) that it 'className' was a
+         // class, so let's create it by hand!.
+
+         if (fID < 0) {
+            cl = new TClass(fBranchClass.GetClassName(), fClassVersion, 0, 0, -1, -1);
+            cl->SetBit(TClass::kIsEmulation);
+            className = cl->GetName();
+         } else {
+            cl = new TClass(className, fClassVersion, 0, 0, -1, -1);
+            cl->SetBit(TClass::kIsEmulation);
+         }
+      }
       TVirtualCollectionProxy* proxy = cl->GetCollectionProxy();
+      if (!proxy) {
+         // humm, we must have an older file with a custom collection
+         // let's try to work-around it.
+         TString equiv;
+         equiv.Form("vector<%s>",fClonesName.Data());
+         TClass *clequiv = TClass::GetClass(equiv);
+         proxy = clequiv->GetCollectionProxy();
+         if (!proxy) { 
+            Fatal("GetCollectionProxy",
+                  "Can not create a Collection Proxy of any kind for the class \"%s\" needed by the branch \"%s\" of the TTree \"%s\"!",
+                  className, GetName(), GetTree()->GetName());
+         }
+         if (gDebug > 0) Info("GetCollectionProxy",
+                              "Fixing the collection proxy of the class \"%s\" \n"
+                              "\tneeded by the branch \"%s\" of the TTree \"%s\" to be similar to \"%s\".",
+                              className, GetName(), GetTree()->GetName(),equiv.Data());
+         cl->CopyCollectionProxy( *proxy );
+      }
       fCollProxy = proxy->Generate();
       fSTLtype = className ? TClassEdit::IsSTLCont(className) : 0;
       if (fSTLtype < 0) {
@@ -2640,6 +2675,12 @@ void TBranchElement::InitializeOffsets()
             Warning("InitializeOffsets", "Cannot get streamer element for branch: %s!", GetName());
             fInitOffsets = kTRUE;
             return;
+         } else if (branchElem->TestBit(TStreamerElement::kRepeat)) {
+            // If we have a repeating streamerElement, use the next
+            // one as it actually hold the 'real' data member('s offset)
+            if (elems[fID+1]) {
+               branchElem = (TStreamerElement*) elems[fID+1];
+            }
          }
          localOffset = branchElem->GetOffset();
          branchClass = branchElem->GetClassPointer();
@@ -2675,6 +2716,8 @@ void TBranchElement::InitializeOffsets()
 
       // Loop over our sub-branches and compute their offsets.
       for (Int_t subBranchIdx = 0; subBranchIdx < nbranches; ++subBranchIdx) {
+         bool alternateElement = false;
+
          fBranchOffset[subBranchIdx] = 0;
          TBranchElement* subBranch = dynamic_cast<TBranchElement*> (fBranches[subBranchIdx]);
          if (subBranch == 0) {
@@ -2707,6 +2750,31 @@ void TBranchElement::InitializeOffsets()
             Warning("InitializeOffsets", "No streamer element for branch: %s subbranch: %s", GetName(), subBranch->GetName());
             fInitOffsets = kTRUE;
             return;
+         } else if (subBranchElement->TestBit(TStreamerElement::kRepeat)) {
+            // If we have a repeating streamerElement, use the next
+            // one as it actually hold the 'real' data member('s offset)
+            if (subBranchElems[subBranch->fID+1]) {
+               subBranchElement = (TStreamerElement*) subBranchElems[subBranch->fID+1];
+            }
+         } else if (subBranchElement->TestBit(TStreamerElement::kCache)) {
+            // We have a cached item which is not a repeated but we might still
+            // have some Actions triggered by a rule that affect real 
+            // data member(s).
+            if (subBranch->fReadActionSequence && subBranch->fReadActionSequence->fActions.size() > 1) {
+               typedef TStreamerInfoActions::ActionContainer_t::iterator iterator;
+               iterator end = subBranch->fReadActionSequence->fActions.end();
+               for(iterator iter = subBranch->fReadActionSequence->fActions.begin();
+                   iter != end; ++iter) {
+                  TStreamerInfoActions::TConfiguration *config = iter->fConfiguration;
+                  UInt_t id = config->fElemId;
+                  TStreamerElement *e = (TStreamerElement*)config->fInfo->GetElements()->At(id);
+                  if (e && !e->TestBit(TStreamerElement::kCache)) {
+                     subBranchElement = e;
+                     alternateElement = true;
+                     break;
+                  }
+               }
+            }
          }
 
          localOffset = subBranchElement->GetOffset();
@@ -2941,7 +3009,8 @@ void TBranchElement::InitializeOffsets()
             // First check whether this sub-branch is part of the 'cache' (because the data member it
             // represents is no longer in the current class layout.
             TStreamerInfo *subInfo = subBranch->GetInfoImp();
-            if (subInfo && subBranch->TestBit(kCache)) { // subInfo->GetElements()->At(subBranch->GetID())->TestBit(TStreamerElement::kCache)) {
+            //if (subInfo && subBranch->TestBit(kCache)) { // subInfo->GetElements()->At(subBranch->GetID())->TestBit(TStreamerElement::kCache)) {
+            if (subBranchElement->TestBit(TStreamerElement::kCache)) {
                pClass = ((TStreamerElement*)subInfo->GetElements()->At(0))->GetClassPointer();
             }
             // FIXME: Do we need the other base class tests here?
@@ -3016,6 +3085,13 @@ void TBranchElement::InitializeOffsets()
             // Find our offset in our parent class using
             // a lookup by name in the dictionary meta info
             // for our parent class.
+           
+            if (alternateElement) {
+               Ssiz_t dotpos = dataName.Last('.');
+               Ssiz_t endpos = dataName.Length();
+               if (dotpos != kNPOS) ++dotpos; else dotpos = 0;
+               dataName.Replace(dotpos,endpos-dotpos,subBranchElement->GetFullName());
+            }
             TRealData* rd = pClass->GetRealData(dataName);
             if (rd && !rd->TestBit(TRealData::kTransient)) {
                // -- Data member exists in the dictionary meta info, get the offset.
@@ -4897,7 +4973,7 @@ void TBranchElement::SetReadActionSequence()
             } else {
                original = GetCollectionProxy()->GetReadMemberWiseActions(fClassVersion);
             }
-         } else {
+         } else if (GetCollectionProxy()) {
             // Base class and embedded objects.
 
             transient = TStreamerInfoActions::TActionSequence::CreateReadMemberWiseActions(info,*GetCollectionProxy());
@@ -4984,7 +5060,7 @@ void TBranchElement::SetFillActionSequence()
             //} else {
             original = GetCollectionProxy()->GetWriteMemberWiseActions();
             //}
-         } else {
+         } else if (GetCollectionProxy()) {
             // Base class and embedded objects.
 
             transient = TStreamerInfoActions::TActionSequence::CreateWriteMemberWiseActions(info,*GetCollectionProxy());
@@ -5367,6 +5443,9 @@ Int_t TBranchElement::Unroll(const char* name, TClass* clParent, TClass* cl, cha
       if (elem->TestBit(TStreamerElement::kRepeat)) {
          continue;
       }
+      if (elem->TestBit(TStreamerElement::kCache) && !elem->TestBit(TStreamerElement::kWrite)) {
+         continue;
+      }
       Int_t offset = elem->GetOffset();
       // FIXME: An STL container as a base class gets TStreamerSTL as its class, so this test is not enough.
       // See InitializeOffsets() for the proper test.
diff --git a/tree/tree/src/TLeafB.cxx b/tree/tree/src/TLeafB.cxx
index 8a93b6b..d15ffb5 100644
--- a/tree/tree/src/TLeafB.cxx
+++ b/tree/tree/src/TLeafB.cxx
@@ -166,9 +166,22 @@ void TLeafB::ReadBasketExport(TBuffer& b, TClonesArray* list, Int_t n)
 //______________________________________________________________________________
 void TLeafB::ReadValue(istream &s, Char_t /*delim = ' '*/)
 {
-   // -- Read a string from istream s and store it into the branch buffer.
-   char* value = (char*) GetValuePointer();
-   s >> value;
+   // -- Read a 8 bit integer from istream s and store it into the branch buffer.
+   if (fIsUnsigned) {
+      UChar_t *uvalue = (UChar_t*)GetValuePointer();
+      for (Int_t i=0;i<fLen;i++) {
+         UShort_t tmp;
+         s >> tmp;
+         uvalue[i] = tmp;
+      }
+   } else {
+      Char_t *value = (Char_t*)GetValuePointer();
+      for (Int_t i=0;i<fLen;i++) {
+         Short_t tmp;
+         s >> tmp;
+         value[i] = tmp;
+      }
+   }
 }
 
 //______________________________________________________________________________
diff --git a/tree/tree/src/TTree.cxx b/tree/tree/src/TTree.cxx
index e048a34..9783cda 100644
--- a/tree/tree/src/TTree.cxx
+++ b/tree/tree/src/TTree.cxx
@@ -2270,6 +2270,9 @@ TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr,
          if (element->TestBit(TStreamerElement::kRepeat)) {
             continue;
          }
+         if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
+            continue;
+         }
          char* pointer = (char*) (objptr + element->GetOffset());
          // FIXME: This is not good enough, an STL container can be
          //        a base, and the test will fail.
@@ -6047,7 +6050,13 @@ void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *opti
          TBranch *branch = leaf->GetBranch();
          Double_t totBytes = (Double_t)branch->GetTotBytes();
          Double_t idealFactor = totBytes/aveSize;
-         UInt_t sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries()); 
+         UInt_t sizeOfOneEntry;
+         if (branch->GetEntries() == 0) {
+            // There is no data, so let's make a guess ...
+            sizeOfOneEntry = aveSize;
+         } else {
+            sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries()); 
+         }
          Int_t oldBsize = branch->GetBasketSize();
          oldMemsize += oldBsize;
          oldBaskets += 1+Int_t(totBytes/oldBsize);
diff --git a/tree/treeplayer/src/TTreeFormula.cxx b/tree/treeplayer/src/TTreeFormula.cxx
index 725e0cf..a9dca06 100644
--- a/tree/treeplayer/src/TTreeFormula.cxx
+++ b/tree/treeplayer/src/TTreeFormula.cxx
@@ -1,4 +1,4 @@
-// @(#)root/treeplayer:$Id$
+// @(#)root/treeplayer:$Id: 725e0cf2ee411db3c264a8c94d1432c21569b191 $
 // Author: Rene Brun   19/01/96
 
 /*************************************************************************
@@ -3688,7 +3688,7 @@ const char* TTreeFormula::EvalStringInstance(Int_t instance)
    const Int_t real_instance = GetRealInstance(instance,0);                                     \
                                                                                                 \
    if (instance==0) fNeedLoading = kTRUE;                                                       \
-   if (real_instance>fNdata[0]) return 0;                                                       \
+   if (real_instance>=fNdata[0]) return 0;                                                      \
                                                                                                 \
    /* Since the only operation in this formula is reading this branch,                          \
       we are guaranteed that this function is first called with instance==0 and                 \
@@ -5316,6 +5316,13 @@ Bool_t TTreeFormula::LoadCurrentDim() {
             // member to be signed integral type.
 
             TBranchElement* branch = (TBranchElement*) leaf->GetBranch();
+            if (branch->GetAddress() == 0) {
+               // Humm there is no space reserve to write the data,
+               // the data member is likely 'removed' from the class
+               // layout, so rather than crashing by accessing 
+               // random memory, make it clear we can't read it.
+               size = 0;
+            }
 
             // NOTE: could be sped up
             if (fHasMultipleVarDim[i]) {// info && info->GetVarDim()>=0) {
diff --git a/tutorials/hist/th2polyEurope.C b/tutorials/hist/th2polyEurope.C
index e5531e6..53b7081 100644
--- a/tutorials/hist/th2polyEurope.C
+++ b/tutorials/hist/th2polyEurope.C
@@ -39,19 +39,19 @@ void th2polyEurope(Int_t npoints=500000)
    const Int_t nx = 36;
    // see http://en.wikipedia.org/wiki/Area_and_population_of_European_countries
    char *countries[nx] = { "france",     "spain",  "sweden",  "germany",       "finland",
-                           "norway",     "poland", "italy",   "yugoslavia",    "united_kingdom", 
-			   "romania",    "belarus","greece",  "czechoslovakia","bulgaria", 
-			   "iceland",    "hungary","portugal","austria",       "ireland", 
+                           "norway",     "poland", "italy",   "yugoslavia",    "united_kingdom",
+			   "romania",    "belarus","greece",  "czechoslovakia","bulgaria",
+			   "iceland",    "hungary","portugal","austria",       "ireland",
 			   "lithuania",  "latvia", "estonia", "denmark",       "netherlands",
-                           "switzerland","moldova","belgium", "albania",       "cyprus", 
-			   "luxembourg", "andorra","malta",   "liechtenstein", "san_marino", 
+                           "switzerland","moldova","belgium", "albania",       "cyprus",
+			   "luxembourg", "andorra","malta",   "liechtenstein", "san_marino",
 			   "monaco" };
-   Float_t surfaces[nx] = { 547030,        505580,   449964,      357021,        338145, 
-                            324220,        312685,   301230,      255438,        244820, 
-			    237500,        207600,   131940,      127711,        110910, 
-			    103000,         93030,    89242,       83870,         70280, 
-			     65200,         64589,    45226,       43094,         41526, 
-			     41290,         33843,    30528,       28748,          9250, 
+   Float_t surfaces[nx] = { 547030,        505580,   449964,      357021,        338145,
+                            324220,        312685,   301230,      255438,        244820,
+			    237500,        207600,   131940,      127711,        110910,
+			    103000,         93030,    89242,       83870,         70280,
+			     65200,         64589,    45226,       43094,         41526,
+			     41290,         33843,    30528,       28748,          9250,
 			      2586,           468,      316,         160,            61,
                                  2};
 
@@ -63,6 +63,11 @@ void th2polyEurope(Int_t npoints=500000)
    TFile *f;
    f = TFile::Open("http://root.cern.ch/files/europe.root","cacheread");
 
+   if (!f) {
+      printf("Cannot access europe.root. Is internet working ?\n");
+      return;
+   }
+
    TH2Poly *p = new TH2Poly(
              "Europe",
              "Europe (bin contents are normalized to the surfaces in km^{2})",
@@ -87,7 +92,7 @@ void th2polyEurope(Int_t npoints=500000)
    TRandom r;
    Double_t longitude, latitude;
    Double_t x, y, pi4 = TMath::Pi()/4, alpha = TMath::Pi()/360;
-   
+
    gBenchmark->Start("Partitioning");
    p->ChangePartition(100, 100);
    gBenchmark->Show("Partitioning");
@@ -157,7 +162,7 @@ void th2polyEurope(Int_t npoints=500000)
    leg->AddEntry(h2,"Countries surfaces from TH2Poly (with errors)","lp");
    leg->Draw();
    leg->Draw();
-   
+
    Double_t wikiSum = h->Integral();
    Double_t polySum = h2->Integral();
    Double_t error = TMath::Abs(wikiSum-polySum)/wikiSum;
diff --git a/tutorials/hist/th2polyUSA.C b/tutorials/hist/th2polyUSA.C
index 4fec80b..170af5e 100644
--- a/tutorials/hist/th2polyUSA.C
+++ b/tutorials/hist/th2polyUSA.C
@@ -47,6 +47,11 @@ void th2polyUSA()
    TFile *f;
    f = TFile::Open("http://root.cern.ch/files/usa.root");
 
+   if (!f) {
+      printf("Cannot access usa.root. Is internet working ?\n");
+      return;
+   }
+
    // Define the TH2Poly bins.
    TMultiGraph *mg;
    TKey *key;
diff --git a/tutorials/proof/ProofNtuple.C b/tutorials/proof/ProofNtuple.C
index 5f56cda..f8bb815 100644
--- a/tutorials/proof/ProofNtuple.C
+++ b/tutorials/proof/ProofNtuple.C
@@ -29,6 +29,7 @@ ProofNtuple::~ProofNtuple()
    // Destructor
 
    SafeDelete(fNtp);
+   SafeDelete(fNtp2);
    SafeDelete(fFile);
    SafeDelete(fRandom);
 }
@@ -138,6 +139,12 @@ void ProofNtuple::SlaveBegin(TTree * /*tree*/)
    fNtp->SetDirectory(fFile);
    fNtp->AutoSave();
 
+   // Now we create the second ntuple
+   fNtp2 = new TNtuple("ntuple2","Demo ntuple2","vx:vy:vz");
+   // File resident
+   fNtp2->SetDirectory(fFile);
+   fNtp2->AutoSave();
+
    // Should we generate the random numbers or take them from the ntuple ?
    TNamed *unr = (TNamed *) fInput->FindObject("PROOF_USE_NTP_RNDM");
    if (unr) {
@@ -200,6 +207,12 @@ Bool_t ProofNtuple::Process(Long64_t entry)
    Int_t i = (Int_t) entry;
    fNtp->Fill(px,py,pz,random,i);
 
+   if (!fNtp2) return kTRUE;
+   
+   // The second ntuple
+   Float_t vz = random * 2. - 1.;
+   fNtp2->Fill(px,py,vz);
+
    return kTRUE;
 }
 
@@ -220,13 +233,15 @@ void ProofNtuple::SlaveTerminate()
       TDirectory *savedir = gDirectory;
       if (fNtp->GetEntries() > 0) {
          fFile->cd();
-         fNtp->Write();
+         fNtp->Write(0, TObject::kOverwrite);
+         if (fNtp2 && fNtp2->GetEntries() > 0) fNtp2->Write(0, TObject::kOverwrite);
          fProofFile->Print();
          fOutput->Add(fProofFile);
       } else {
          cleanup = kTRUE;
       }
       fNtp->SetDirectory(0);
+      if (fNtp2) fNtp2->SetDirectory(0);
       gDirectory = savedir;
       fFile->Close();
       // Cleanup, if needed
diff --git a/tutorials/proof/ProofNtuple.h b/tutorials/proof/ProofNtuple.h
index a1663bf..698d9f0 100644
--- a/tutorials/proof/ProofNtuple.h
+++ b/tutorials/proof/ProofNtuple.h
@@ -24,11 +24,12 @@ public :
    TFile            *fFile;
    TProofOutputFile *fProofFile; // For optimized merging of the ntuple
    TNtuple          *fNtp;
+   TNtuple          *fNtp2;      // To test double TTree in the same file
    TRandom3         *fRandom;
    Bool_t            fPlotNtuple;
    TNtuple          *fNtpRndm;   // Ntuple with random numbers
 
-   ProofNtuple() : fFile(0), fProofFile(0), fNtp(0), fRandom(0), fPlotNtuple(kTRUE), fNtpRndm(0)  { }
+   ProofNtuple() : fFile(0), fProofFile(0), fNtp(0), fNtp2(0), fRandom(0), fPlotNtuple(kTRUE), fNtpRndm(0)  { }
    virtual ~ProofNtuple();
    virtual Int_t   Version() const { return 2; }
    virtual void    Begin(TTree *tree);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/root-system.git



More information about the debian-science-commits mailing list