[Libreoffice-commits] core.git: Branch 'feature/unitver' - 1961 commits - accessibility/inc accessibility/source android/Bootstrap android/CustomTarget_lo_android.mk android/.gitignore android/Makefile android/README android/source animations/source autogen.sh avmedia/inc avmedia/source basctl/source basctl/uiconfig basebmp/inc basebmp/Library_basebmp.mk basebmp/README basebmp/source basebmp/StaticLibrary_basebmp.mk basebmp/test basegfx/source basegfx/test basic/inc basic/source bean/com binaryurp/source bin/check-icon-sizes.py bin/find-duplicated-files.py bin/findunusedcode bin/gbuild-to-ide bin/gen-iwyu-dummy-lib bin/get-bugzilla-attachments-by-mimetype bin/lo-all-static-libs bridges/inc bridges/Module_bridges.mk bridges/source canvas/source canvas/workben chart2/inc chart2/Library_chartcontroller.mk chart2/qa chart2/source chart2/uiconfig cli_ure/source codemaker/source comphelper/CppunitTest_comphelper_variadictemplates_test.mk comphelper/Module_comphelper.mk comphelper/qa comphelper/source c ompilerplugins/clang config_host/config_features.h.in config_host/config_global.h.in config_host/config_liblangtag.h.in config_host.mk.in configmgr/CppunitTest_configmgr_unit.mk configmgr/qa configmgr/source configure.ac connectivity/com connectivity/Library_tdeab1.mk connectivity/Library_tdeabdrv1.mk connectivity/qa connectivity/source cppcanvas/qa cppcanvas/source cppuhelper/qa cppuhelper/source cppu/qa cppu/source cpputools/source cui/source cui/uiconfig dbaccess/qa dbaccess/source desktop/CppunitTest_desktop_lib.mk desktop/inc desktop/Library_sofficeapp.mk desktop/Pagein_common.mk desktop/qa desktop/README.vars desktop/source desktop/unx dictionaries distro-configs/LibreOfficeAndroidAarch64.conf distro-configs/LibreOfficeAndroid.conf distro-configs/LibreOfficeAndroidX86.conf distro-configs/LibreOfficeCoverity.conf distro-configs/LibreOfficeEmscripten.conf distro-configs/LibreOfficeLinux.conf distro-configs/LibreOfficeOpenBSD.conf distro-configs/OxygenOfficeLinux.conf distro-conf igs/OxygenOfficeWin32.conf download.lst drawinglayer/README drawinglayer/source dtrans/source editeng/inc editeng/Library_editeng.mk editeng/qa editeng/source embeddedobj/source embeddedobj/test embedserv/source eventattacher/source extensions/qa extensions/source extensions/test extensions/workben external/apache-commons external/expat external/firebird external/graphite external/hunspell external/icu external/libmwaw external/liborcus external/libwps external/Module_external.mk external/udunits2 extras/source filter/Configuration_filter.mk filter/Library_t602filter.mk filter/qa filter/README filter/source forms/qa forms/source formula/source fpicker/source fpicker/test fpicker/uiconfig framework/inc framework/qa framework/source .gitignore helpcompiler/source helpcontent2 hwpfilter/qa hwpfilter/source i18nlangtag/CppunitTest_i18nlangtag_test_languagetag.mk i18nlangtag/Library_i18nlangtag.mk i18nlangtag/qa i18nlangtag/source i18npool/inc i18npool/qa i18npool/source i18nutil/source icon-themes/breeze icon-themes/classic icon-themes/crystal icon-themes/elementary icon-themes/galaxy icon-themes/human icon-themes/industrial icon-themes/oxygen icon-themes/README icon-themes/sifr icon-themes/tango icon-themes/tango_testing idlc/inc idlc/source idl/inc idl/source include/avmedia include/basebmp include/basegfx include/basic include/canvas include/codemaker include/comphelper include/connectivity include/cppcanvas include/cppuhelper include/dbaccess include/drawinglayer include/editeng include/filter include/formula include/framework include/i18nlangtag include/i18nutil include/jvmaccess include/LibreOfficeKit include/linguistic include/o3tl include/oox include/osl include/registry include/rtl include/sal include/sax include/sfx2 include/sot include/store include/svl include/svtools include/svx include/test include/toolkit include/tools include/ucbhelper include/unoidl include/unotest include/unotools include/vbahelper include/vcl include/xmloff include/xmlreader inc lude/xmlscript instsetoo_native/CustomTarget_install.mk instsetoo_native/CustomTarget_setup.mk instsetoo_native/inc_openoffice instsetoo_native/util io/qa ios/CustomTarget_TiledLibreOffice_app.mk ios/experimental io/source io/test javaunohelper/com javaunohelper/source jurt/com jurt/test jvmfwk/plugins jvmfwk/source l10ntools/inc l10ntools/source libreofficekit/Executable_gtktiledviewer.mk libreofficekit/Executable_tilebench.mk libreofficekit/Library_libreofficekitgtk.mk libreofficekit/Module_libreofficekit.mk libreofficekit/qa libreofficekit/source lingucomponent/source linguistic/inc linguistic/source lotuswordpro/qa lotuswordpro/source m4/ax_boost_base.m4 Makefile.fetch Makefile.in mysqlc/source nlpsolver/src nlpsolver/ThirdParty odk/examples odk/settings odk/source offapi/com offapi/type_reference offapi/UnoApi_offapi.mk officecfg/Configuration_officecfg.mk officecfg/registry onlineupdate/source oox/CppunitTest_oox_vba_encryption.mk oox/inc oox/Module_oox.mk oox/qa oox/source op encl/inc opencl/source package/inc package/qa package/source postprocess/CustomTarget_registry.mk postprocess/Rdb_services.mk pyuno/inc pyuno/source qadevOOo/Jar_OOoRunner.mk qadevOOo/objdsc qadevOOo/runner qadevOOo/tests readlicense_oo/license README.Solaris registry/inc registry/source registry/tools remotebridges/source reportbuilder/java reportdesign/inc reportdesign/source RepositoryExternal.mk Repository.mk ridljar/com ridljar/Jar_ridl.mk rsc/inc rsc/source sal/android sal/cpprt sal/cppunittester salhelper/qa salhelper/source sal/osl sal/qa sal/rtl sal/textenc sal/workben sax/qa sax/source scaddins/source sc/AllLangResTarget_sc.mk sccomp/qa sccomp/source sc/CppunitTest_sc_ucalc.mk sc/CppunitTest_sc_units.mk sc/inc sc/Library_scfilt.mk sc/Library_sc.mk sc/Module_sc.mk scp2/AutoInstall.mk scp2/InstallModule_gnome.mk scp2/InstallModule_ooo.mk scp2/InstallScript_setup_osl.mk scp2/Module_scp2.mk scp2/source sc/qa scripting/java scripting/source sc/sdi sc/source sc/uiconfig sc/UICon fig_scalc.mk sc/util sc/workben sd/CppunitTest_sd_import_tests.mk sdext/inc sdext/source sd/inc sd/qa sd/sdi sd/source sd/uiconfig sd/workben setup_native/scripts setup_native/source sfx2/inc sfx2/Library_sfx.mk sfx2/qa sfx2/source sfx2/uiconfig shell/inc shell/Library_gconfbe.mk shell/Module_shell.mk shell/Package_scripts.mk shell/Package_scripts_tde.mk shell/README shell/source slideshow/inc slideshow/source slideshow/test smoketest/org smoketest/smoketest.cxx solenv/bin solenv/doc solenv/gbuild soltools/cpp sot/qa sot/source starmath/inc starmath/Library_sm.mk starmath/qa starmath/sdi starmath/source stoc/source store/source svgio/inc svgio/qa svgio/source svl/qa svl/source svtools/inc svtools/Library_svt.mk svtools/qa svtools/source svtools/uiconfig svx/Executable_gengal.mk svx/inc svx/Library_svxcore.mk svx/sdi svx/source svx/uiconfig svx/workben sw/CppunitTest_sw_uiwriter.mk sw/CppunitTest_sw_ww8export.mk swext/Extension_wiki-publisher.mk swext/Jar_mediawiki.mk swext/mediawiki sw/inc sw/Library_sw.mk sw/qa sw/sdi sw/source sw/uiconfig sysui/CustomTarget_deb.mk sysui/desktop test/source testtools/com testtools/source toolkit/inc toolkit/qa toolkit/source tools/qa tools/source translations tubes/source ucbhelper/source ucb/qa ucb/source udkapi/com UnoControls/inc UnoControls/source unoidl/source unotest/source unotools/Library_utl.mk unotools/qa unotools/source unotools/util unoxml/qa unoxml/source uui/source vbahelper/source vcl/android vcl/Executable_icontest.mk vcl/Executable_mtfdemo.mk vcl/Executable_ui-previewer.mk vcl/Executable_vcldemo.mk vcl/generic vcl/headless vcl/inc vcl/ios vcl/Library_desktop_detector.mk vcl/Library_vcl.mk vcl/Module_vcl.mk vcl/opengl vcl/osx vcl/qa vcl/quartz vcl/README.GDIMetaFile vcl/source vcl/test vcl/uiconfig vcl/UIConfig_vcl.mk vcl/unx vcl/win vcl/workben winaccessibility/inc winaccessibility/source wizards/com wizards/source writerfilter/inc writerfilter/qa writerfilter/source writerperfect/inc writerperfect/qa writerp erfect/source xmerge/source xmlhelp/Library_ucpchelp1.mk xmlhelp/source xmloff/inc xmloff/Library_xo.mk xmloff/qa xmloff/source xmlscript/source xmlsecurity/inc xmlsecurity/Library_xsec_xmlsec.mk xmlsecurity/Module_xmlsecurity.mk xmlsecurity/source

Andrzej Hunt andrzej at ahunt.org
Wed Oct 21 06:01:59 PDT 2015


Rebased ref, commits from common ancestor:
commit 0d7d7f22337c56623da15ad3003bceae2c1a063c
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Wed Oct 21 14:24:44 2015 +0200

    unit-verification: more convert Link<> to typed
    
    Change-Id: I8f330dbfb3b5a0a7409475a5a8802c3640e6bb31

diff --git a/sc/source/ui/inc/unitsconversiondlg.hxx b/sc/source/ui/inc/unitsconversiondlg.hxx
index cda8f83..d5a1f3c 100644
--- a/sc/source/ui/inc/unitsconversiondlg.hxx
+++ b/sc/source/ui/inc/unitsconversiondlg.hxx
@@ -85,11 +85,11 @@ private:
     void PerformConversion();
 
     DECL_LINK_TYPED( OkClicked,             Button*, void );
-    DECL_LINK( GetFocusHandler,             Control* );
-    DECL_LINK( LoseFocusHandler,            void* );
-    DECL_LINK( OutputUnitsModified,         void* );
-    DECL_LINK( OutputUnitsGetFocusHandler,  void* );
-    DECL_LINK( OutputUnitsLoseFocusHandler, void* );
+    DECL_LINK_TYPED( GetFocusHandler,       Control&, void );
+    DECL_LINK_TYPED( LoseFocusHandler,      Control&, void );
+    DECL_LINK_TYPED( OutputUnitsModified,   Edit&, void );
+    DECL_LINK_TYPED( OutputUnitsGetFocusHandler,  Control&, void );
+    DECL_LINK_TYPED( OutputUnitsLoseFocusHandler, Control&, void );
 };
 
 #endif // INCLUDED_SC_SOURCE_UI_INC_UNITSCONVERSIONDLG_HXX
diff --git a/sc/source/ui/miscdlgs/unitsconversiondlg.cxx b/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
index cea5405..0e6e922 100644
--- a/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
+++ b/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
@@ -75,7 +75,7 @@ void ScUnitsConversionDialog::dispose()
 
 void ScUnitsConversionDialog::Init()
 {
-    Link<> aLink = LINK( this, ScUnitsConversionDialog, GetFocusHandler );
+    Link<Control&, void> aLink = LINK( this, ScUnitsConversionDialog, GetFocusHandler );
     mpInputRangeEdit->SetGetFocusHdl( aLink );
     mpInputRangeButton->SetGetFocusHdl( aLink );
 
@@ -206,38 +206,34 @@ IMPL_LINK_TYPED( ScUnitsConversionDialog, OkClicked, Button*, /*pButton*/, void
     Close();
 }
 
-IMPL_LINK( ScUnitsConversionDialog, GetFocusHandler, Control*, pCtrl )
+IMPL_LINK_TYPED( ScUnitsConversionDialog, GetFocusHandler, Control&, rCtrl, void )
 {
     Edit* pEdit = NULL;
 
-    if( (pCtrl == mpInputRangeEdit.get()) || (pCtrl == mpInputRangeButton.get()) ) {
+    if ( ( &rCtrl == static_cast<Control*>( mpInputRangeEdit ) ) ||
+         ( &rCtrl == static_cast<Control*>( mpInputRangeButton ) ) ) {
         pEdit = mpInputRangeEdit;
     }
 
-    if( pEdit ) {
+    if ( pEdit ) {
         pEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
     }
-
-    return 0;
 }
 
-IMPL_LINK_NOARG( ScUnitsConversionDialog, LoseFocusHandler )
+IMPL_LINK_NOARG_TYPED( ScUnitsConversionDialog, LoseFocusHandler, Control&, void )
 {
     mbDialogLostFocus = !IsActive();
-    return 0;
 }
 
-IMPL_LINK_NOARG( ScUnitsConversionDialog, OutputUnitsGetFocusHandler )
+IMPL_LINK_NOARG_TYPED( ScUnitsConversionDialog, OutputUnitsGetFocusHandler, Control&, void )
 {
     // The warning box may have been enabled because of an incompatible unit,
     // however we should disable it during editing (it will then be reenabled
     // if needed once the user completes editing their desired output unit).
     mpIncompatibleOutputBox->Show( false );
-
-    return 0;
 }
 
-IMPL_LINK_NOARG( ScUnitsConversionDialog, OutputUnitsModified )
+IMPL_LINK_NOARG_TYPED( ScUnitsConversionDialog, OutputUnitsModified, Edit&, void )
 {
     OUString sOutputUnit = mpOutputUnitsEdit->GetText();
 
@@ -251,15 +247,11 @@ IMPL_LINK_NOARG( ScUnitsConversionDialog, OutputUnitsModified )
         mpOutputUnitsEdit->SetControlForeground( Color( COL_BLACK ) );
         mpOutputUnitsEdit->set_font_attribute( "underline", "false" );
     }
-
-    return 0;
 }
 
-IMPL_LINK_NOARG( ScUnitsConversionDialog, OutputUnitsLoseFocusHandler )
+IMPL_LINK_NOARG_TYPED( ScUnitsConversionDialog, OutputUnitsLoseFocusHandler, Control&, void )
 {
     mpIncompatibleOutputBox->Show( !CheckUnitsAreConvertible() );
-
-    return 0;
 }
 
 void ScUnitsConversionDialog::PerformConversion()
commit f54a180271349de75b6c3e5dc80a58e91b5b289b
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Tue Oct 20 22:04:46 2015 +0200

    ScreenSaverInhibitor: Don't depend on glib type definitions
    
    We also include this header from the kde and tde backends,
    it seems to be saner just to use the base definitions of these
    types rather than depending on glib there.
    
    Change-Id: Ib270fd33290f9c213dea72a8e20618007470d882

diff --git a/vcl/inc/unx/screensaverinhibitor.hxx b/vcl/inc/unx/screensaverinhibitor.hxx
index 286c18d..7b5af6d 100644
--- a/vcl/inc/unx/screensaverinhibitor.hxx
+++ b/vcl/inc/unx/screensaverinhibitor.hxx
@@ -21,19 +21,20 @@
 
 #include <boost/optional.hpp>
 
-#include <glib.h>
-
 class VCL_PLUGIN_PUBLIC ScreenSaverInhibitor
 {
 public:
     void inhibit( bool bInhibit, const rtl::OUString& sReason,
-                  bool bIsX11, const boost::optional<guint> xid, boost::optional<Display*> pDisplay );
+                  bool bIsX11, const boost::optional<unsigned int> xid, boost::optional<Display*> pDisplay );
 
 private:
-    boost::optional<guint> mnFDOCookie; // FDO ScreenSaver Inhibit
-    boost::optional<guint> mnFDOPMCookie; // FDO PowerManagement Inhibit
-    boost::optional<guint> mnGSMCookie;
-    boost::optional<guint> mnMSMCookie;
+    // These are all used as guint, however this header may be included
+    // in kde/tde/etc backends, where we would ideally avoid having
+    // any glib dependencies, hence the direct use of unsigned int.
+    boost::optional<unsigned int> mnFDOCookie; // FDO ScreenSaver Inhibit
+    boost::optional<unsigned int> mnFDOPMCookie; // FDO PowerManagement Inhibit
+    boost::optional<unsigned int> mnGSMCookie;
+    boost::optional<unsigned int> mnMSMCookie;
 
     boost::optional<int> mnXScreenSaverTimeout;
 
@@ -58,10 +59,10 @@ private:
     //       (This is replaced by the GSM interface from Mate 1.12 onwards)
     //
     // Note: the Uninhibit call has different spelling in FDO (UnInhibit) vs GSM (Uninhibit)
-    void inhibitFDO( bool bInhibit, const gchar* appname, const gchar* reason );
-    void inhibitFDOPM( bool bInhibit, const gchar* appname, const gchar* reason );
-    void inhibitGSM( bool bInhibit, const gchar* appname, const gchar* reason, const guint xid );
-    void inhibitMSM( bool bInhibit, const gchar* appname, const gchar* reason, const guint xid );
+    void inhibitFDO( bool bInhibit, const char* appname, const char* reason );
+    void inhibitFDOPM( bool bInhibit, const char* appname, const char* reason );
+    void inhibitGSM( bool bInhibit, const char* appname, const char* reason, const unsigned int xid );
+    void inhibitMSM( bool bInhibit, const char* appname, const char* reason, const unsigned int xid );
 
     void inhibitXScreenSaver( bool bInhibit, Display* pDisplay );
     static void inhibitXAutoLock( bool bInhibit, Display* pDisplay );
commit 7bf56d5495b583d7d1629b89d4de8a77f212f976
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Tue Oct 20 21:23:42 2015 +0200

    Ignore the default constructor for loplugin:badvectorinit too
    
    The default constructor doesn't necessarily have 0 parameters,
    hence we need to explicitly test for this too.
    
    Change-Id: I685c44ab373ec8234a86824a77cc523a355c8b05

diff --git a/compilerplugins/clang/badvectorinit.cxx b/compilerplugins/clang/badvectorinit.cxx
index 005726e..709a65d 100644
--- a/compilerplugins/clang/badvectorinit.cxx
+++ b/compilerplugins/clang/badvectorinit.cxx
@@ -172,7 +172,10 @@ bool BadVectorInit::VisitCXXConstructExpr(const CXXConstructExpr* expr)
     const CXXConstructorDecl *consDecl = expr->getConstructor();
     consDecl = consDecl->getCanonicalDecl();
 
-    if (consDecl->param_size() == 0)
+    // The default constructor can potentially have a parameter, e.g.
+    // in glibcxx-debug the default constructor is:
+    // explicit vector(const _Allocator& __a = _Allocator())
+    if (consDecl->param_size() == 0 || consDecl->isDefaultConstructor())
         return true;
 
     std::string aParentName = consDecl->getParent()->getQualifiedNameAsString();
commit 6e51d7a50f43f0702649851f141b1e6e5c7cddf9
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Thu Sep 24 18:24:57 2015 +0200

    Make incompatible-output-box visible to ensure layout space
    
    If the incompatible-output warning is not visible when the dialog is
    loaded, it receives no space in the layout - this then looks ugly
    when this warning is enabled (as it overlaps the OK/Cancel buttons).
    We already set the boxes visibility again on startup, hence we then
    hide the box as needed at that time.
    
    Change-Id: I61c9ce463ad80aaec08ae680aa3ad1535c33d9c5

diff --git a/sc/uiconfig/scalc/ui/unitsconversiondialog.ui b/sc/uiconfig/scalc/ui/unitsconversiondialog.ui
index f7ed3fe..97d70af 100644
--- a/sc/uiconfig/scalc/ui/unitsconversiondialog.ui
+++ b/sc/uiconfig/scalc/ui/unitsconversiondialog.ui
@@ -256,6 +256,7 @@
                         </child>
                         <child>
                           <object class="GtkBox" id="incompatible-output-box">
+                            <property name="visible">True</property>
                             <property name="can_focus">False</property>
                             <child>
                               <object class="GtkImage" id="incompatible-output-icon">
commit 1a01024da99f93b0044720e16bc8f2d605cad685
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Tue Sep 22 19:10:38 2015 +0200

    Set default focus on output unit entry box
    
    This allows the user to immediately enter their desired unit -
    the input area selection is likely to be used only rarely.
    
    Change-Id: I08de7718ed183db21513d1f46f346da27c3ebbf7

diff --git a/sc/uiconfig/scalc/ui/unitsconversiondialog.ui b/sc/uiconfig/scalc/ui/unitsconversiondialog.ui
index 3549282..f7ed3fe 100644
--- a/sc/uiconfig/scalc/ui/unitsconversiondialog.ui
+++ b/sc/uiconfig/scalc/ui/unitsconversiondialog.ui
@@ -243,7 +243,8 @@
                             <property name="has_entry">True</property>
                             <child internal-child="entry">
                               <object class="GtkEntry" id="foo">
-                                <property name="can_focus">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="has_focus">True</property>
                               </object>
                             </child>
                           </object>
commit 569a1b967af589358f72aef30f63c937d462a01d
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Tue Sep 22 14:02:33 2015 +0200

    unit-verification: convert Link<> to typed
    
    (fix build after rebasing on master)
    
    Change-Id: Iecbdbf5a854de0b552f6c9074e72da3fa47d91a4

diff --git a/sc/source/ui/inc/unitsconversiondlg.hxx b/sc/source/ui/inc/unitsconversiondlg.hxx
index 01116d2..cda8f83 100644
--- a/sc/source/ui/inc/unitsconversiondlg.hxx
+++ b/sc/source/ui/inc/unitsconversiondlg.hxx
@@ -84,7 +84,7 @@ private:
     bool CheckUnitsAreConvertible();
     void PerformConversion();
 
-    DECL_LINK( OkClicked,                   PushButton* );
+    DECL_LINK_TYPED( OkClicked,             Button*, void );
     DECL_LINK( GetFocusHandler,             Control* );
     DECL_LINK( LoseFocusHandler,            void* );
     DECL_LINK( OutputUnitsModified,         void* );
diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index 259bcf0..2682cf5 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -371,14 +371,14 @@ private:
     void            NotifyUnitErrorInFormula( const ScAddress& rAddress,
                                               ScDocument* pDoc,
                                               const sc::units::FormulaStatus& rStatus);
-    DECL_LINK( EditUnitErrorFormulaHandler, PushButton* );
+    DECL_LINK_TYPED( EditUnitErrorFormulaHandler, Button*, void);
 
     void            NotifyUnitConversionRecommended( const ScAddress& rCellAddress,
                                                      ScDocument* pDoc,
                                                      const OUString& sHeaderUnit,
                                                      const ScAddress& rHeaderAddress,
                                                      const OUString& sCellUnit );
-    DECL_LINK( UnitConversionRecommendedHandler, UnitConversionPushButton* );
+    DECL_LINK_TYPED( UnitConversionRecommendedHandler, Button*, void);
 };
 
 #endif
diff --git a/sc/source/ui/miscdlgs/unitsconversiondlg.cxx b/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
index a3a6744..cea5405 100644
--- a/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
+++ b/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
@@ -192,26 +192,25 @@ bool ScUnitsConversionDialog::CheckUnitsAreConvertible()
     return bCompatibleInputFound;
 }
 
-IMPL_LINK( ScUnitsConversionDialog, OkClicked, PushButton*, /*pButton*/ )
+IMPL_LINK_TYPED( ScUnitsConversionDialog, OkClicked, Button*, /*pButton*/, void )
 {
     if (!CheckUnitsAreConvertible())
     {
         // As we have now clicked on this button, the output units entry
         // box has lost focus, so the "no conversion possible" warning
         // will already be shown by the OutputUnitsComplete handler.
-        return 0;
+        return;
     }
 
     PerformConversion();
     Close();
-    return 0;
 }
 
 IMPL_LINK( ScUnitsConversionDialog, GetFocusHandler, Control*, pCtrl )
 {
     Edit* pEdit = NULL;
 
-    if( (pCtrl == (Control*) mpInputRangeEdit) || (pCtrl == (Control*) mpInputRangeButton) ) {
+    if( (pCtrl == mpInputRangeEdit.get()) || (pCtrl == mpInputRangeButton.get()) ) {
         pEdit = mpInputRangeEdit;
     }
 
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index f382f76..a22ddbc 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -2897,9 +2897,8 @@ void ScViewFunc::NotifyUnitErrorInFormula( const ScAddress& rAddress, ScDocument
     pInfoBar->addButton( pButtonGotoCell);
 }
 
-IMPL_LINK( ScViewFunc, EditUnitErrorFormulaHandler, PushButton*, pButton )
+IMPL_LINK_TYPED( ScViewFunc, EditUnitErrorFormulaHandler, Button*, pButton, void )
 {
-
     OUString sAddress;
     {
         // keep pInfoBar within this scope only as we'll be deleting it just below (using RemoveInfoBar)
@@ -2920,8 +2919,6 @@ IMPL_LINK( ScViewFunc, EditUnitErrorFormulaHandler, PushButton*, pButton )
     // UI making it a bit easier to see where the data is coming from).
     ScModule* pScMod = SC_MOD();
     pScMod->SetInputMode( SC_INPUT_TABLE );
-
-    return 0;
 }
 
 /*
@@ -2995,14 +2992,20 @@ void ScViewFunc::NotifyUnitConversionRecommended( const ScAddress& rCellAddress,
     pInfoBar->addButton( pButtonConvertCell );
 }
 
-IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButton*, pButton )
+IMPL_LINK_TYPED( ScViewFunc, UnitConversionRecommendedHandler, Button*, pButton, void )
 {
     // Do conversion first, and only then remove the infobar as we need data from the infobar
     // (specifically from the pushbutton) to do the conversion.
 #ifdef ENABLE_CALC_UNITVERIFICATION
+
+    // We can't pass in a UnitConversionPushButton* as this would require template-parameter downcasting
+    // (which is illegal) when setting pButtonConvertCell->SetClickHdl (which expects a
+    // Link<Button*, void>). Instead we can just cast back to the expected type here.
+    UnitConversionPushButton* pPushButton = dynamic_cast<UnitConversionPushButton*>( pButton );
+
     boost::shared_ptr< Units > pUnits = Units::GetUnits();
 
-    ScDocument* pDoc = pButton->mpDoc;
+    ScDocument* pDoc = pPushButton->mpDoc;
     ScDocShell* pDocShell = static_cast<ScDocShell*>(pDoc->GetDocumentShell());
 
     ScDocShellModificator aModificator( *pDocShell );
@@ -3018,12 +3021,12 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
     {
         pUndoManager = pDocShell->GetUndoManager();
 
-        aOldVal.assign( *pDoc, pButton->aCellAddress );
+        aOldVal.assign( *pDoc, pPushButton->aCellAddress );
 
-        aMark.SetMarkArea( pButton->aCellAddress );
+        aMark.SetMarkArea( pPushButton->aCellAddress );
         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
-        pUndoDoc->InitUndo( pDoc, pButton->aCellAddress.Tab(), pButton->aCellAddress.Tab() );
-        pDoc->CopyToDocument( ScRange( pButton->aCellAddress ), IDF_ATTRIB, false, pUndoDoc, &aMark );
+        pUndoDoc->InitUndo( pDoc, pPushButton->aCellAddress.Tab(), pPushButton->aCellAddress.Tab() );
+        pDoc->CopyToDocument( ScRange( pPushButton->aCellAddress ), IDF_ATTRIB, false, pUndoDoc, &aMark );
 
         // This commences logging of changes to the drawing layer
         // (i.e. notes) for storing in an undo. (See more below.)
@@ -3031,14 +3034,14 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
         pDrawLayer->BeginCalcUndo(false);
     }
 
-    OUString sOriginalValue = pDoc->GetString( pButton->aCellAddress );
+    OUString sOriginalValue = pDoc->GetString( pPushButton->aCellAddress );
 
-    pUnits->convertCellToHeaderUnit( pButton->aCellAddress,
+    pUnits->convertCellToHeaderUnit( pPushButton->aCellAddress,
                                      pDoc,
-                                     pButton->sHeaderUnit,
-                                     pButton->sCellUnit );
+                                     pPushButton->sHeaderUnit,
+                                     pPushButton->sCellUnit );
 
-    const OUString sCurrentNoteText = pDoc->GetOrCreateNote( pButton->aCellAddress )->GetText();
+    const OUString sCurrentNoteText = pDoc->GetOrCreateNote( pPushButton->aCellAddress )->GetText();
     const OUString sConversionNote("Original input: " + sOriginalValue);
     OUString sNewNoteText;
 
@@ -3052,11 +3055,11 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
     }
 
     // ensure existing caption object before draw undo tracking starts
-    ScPostIt* pOldNote = pDoc->ReleaseNote( pButton->aCellAddress );
+    ScPostIt* pOldNote = pDoc->ReleaseNote( pPushButton->aCellAddress );
     ScNoteData aOldNoteData = pOldNote->GetNoteData();
     delete pOldNote;
 
-    ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( *pDoc, pButton->aCellAddress, sNewNoteText, false, true );
+    ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( *pDoc, pPushButton->aCellAddress, sNewNoteText, false, true );
     assert( pNewNote );
 
     if ( bUndo )
@@ -3065,14 +3068,14 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
         pUndoManager->EnterListAction( aUndo, aUndo );
 
         ScCellValue aNewVal;
-        aNewVal.assign( *pDoc, pButton->aCellAddress );
-        const ScPatternAttr* pNewPat = pDoc->GetPattern( pButton->aCellAddress );
+        aNewVal.assign( *pDoc, pPushButton->aCellAddress );
+        const ScPatternAttr* pNewPat = pDoc->GetPattern( pPushButton->aCellAddress );
 
-        pUndoManager->AddUndoAction( new ScUndoSetCell( pDocShell, pButton->aCellAddress, aOldVal, aNewVal ) );
+        pUndoManager->AddUndoAction( new ScUndoSetCell( pDocShell, pPushButton->aCellAddress, aOldVal, aNewVal ) );
         pUndoManager->AddUndoAction( new ScUndoSelectionAttr( pDocShell,
                                                               aMark,
-                                                              pButton->aCellAddress.Col(), pButton->aCellAddress.Row(), pButton->aCellAddress.Tab(),
-                                                              pButton->aCellAddress.Col(), pButton->aCellAddress.Row(), pButton->aCellAddress.Tab(),
+                                                              pPushButton->aCellAddress.Col(), pPushButton->aCellAddress.Row(), pPushButton->aCellAddress.Tab(),
+                                                              pPushButton->aCellAddress.Col(), pPushButton->aCellAddress.Row(), pPushButton->aCellAddress.Tab(),
                                                               pUndoDoc,
                                                               false,
                                                               pNewPat) );
@@ -3083,7 +3086,7 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
         // different constructors for each case.
         if ( sCurrentNoteText.isEmpty() )
         {
-            pUndoManager->AddUndoAction( new ScUndoReplaceNote( *pDocShell, pButton->aCellAddress,
+            pUndoManager->AddUndoAction( new ScUndoReplaceNote( *pDocShell, pPushButton->aCellAddress,
                                                                 aNewNoteData, true, nullptr ) );
         }
         else
@@ -3091,14 +3094,14 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
             // Actual note content changes are stored in the DrawLayer CalcUndo,
             // as opposed to being the NoteData (which just seems to store note
             // metadata) - hence we need to make sure that we save that too.
-            pUndoManager->AddUndoAction( new ScUndoReplaceNote( *pDocShell, pButton->aCellAddress,
+            pUndoManager->AddUndoAction( new ScUndoReplaceNote( *pDocShell, pPushButton->aCellAddress,
                                                                 aOldNoteData, aNewNoteData,
                                                                 pDrawLayer->GetCalcUndo() ) );
         }
         pUndoManager->LeaveListAction();
     }
 
-    pDocShell->PostPaint(ScRange( pButton->aCellAddress), PAINT_GRID);
+    pDocShell->PostPaint(ScRange( pPushButton->aCellAddress), PAINT_GRID);
 
     aModificator.SetDocumentModified();
     SfxGetpApp()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
@@ -3122,8 +3125,6 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
     GetViewData().GetDispatcher().Execute( SID_CURRENTCELL,
                                            SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
                                            &aPosition, &aUnmark, 0L );
-
-    return 0;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 215a189e5d35a0423bf26937405993499a8ed987
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Tue Sep 22 14:01:28 2015 +0200

    loplugin:vclwidgets
    
    Change-Id: I8edbf71d961067ee565954cbb91ee9e503e3077d

diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index f046551..f382f76 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -2892,7 +2892,7 @@ void ScViewFunc::NotifyUnitErrorInFormula( const ScAddress& rAddress, ScDocument
     SfxInfoBarWindow* pInfoBar = pViewFrame->AppendInfoBar( sCellAddress, sTitle );
 
     assert( pInfoBar );
-    PushButton* pButtonGotoCell = new PushButton( &pViewFrame->GetWindow(), ScResId(BT_UNITS_EDIT_CELL) );
+    VclPtr<PushButton> pButtonGotoCell = VclPtr<PushButton>::Create( &pViewFrame->GetWindow(), ScResId(BT_UNITS_EDIT_CELL) );
     pButtonGotoCell->SetClickHdl( LINK( this, ScViewFunc, EditUnitErrorFormulaHandler ) );
     pInfoBar->addButton( pButtonGotoCell);
 }
@@ -2979,12 +2979,13 @@ void ScViewFunc::NotifyUnitConversionRecommended( const ScAddress& rCellAddress,
 
     assert( pInfoBar );
 
-    UnitConversionPushButton* pButtonConvertCell = new UnitConversionPushButton( &pViewFrame->GetWindow(),
-                                                                                 ScResId(BT_UNITS_CONVERT_THIS_CELL),
-                                                                                 rCellAddress,
-                                                                                 pDoc,
-                                                                                 rsHeaderUnit,
-                                                                                 rsCellUnit );
+    VclPtr<UnitConversionPushButton> pButtonConvertCell =
+        VclPtr<UnitConversionPushButton>::Create( &pViewFrame->GetWindow(),
+                                                  ScResId(BT_UNITS_CONVERT_THIS_CELL),
+                                                  rCellAddress,
+                                                  pDoc,
+                                                  rsHeaderUnit,
+                                                  rsCellUnit );
     pButtonConvertCell->SetClickHdl( LINK( this, ScViewFunc, UnitConversionRecommendedHandler ) );
 
     OUString sConvertText = pButtonConvertCell->GetText();
commit 2daa56a63baea4cb3f946e3bc2f662dbfa0a45cd
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Fri Aug 7 08:25:48 2015 +0100

    Implement undoing conversion of individual locally annotated cells
    
    Change-Id: I16b62f1105f7839b047a96fdab0e3e6089d400ee

diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc
index ede086a..318c5bb 100644
--- a/sc/inc/sc.hrc
+++ b/sc/inc/sc.hrc
@@ -1008,7 +1008,10 @@
 #define STR_UNITS_CONVERSION_RECOMMENDED (STR_START + 455)
 #define BT_UNITS_CONVERT_THIS_CELL  (STR_START + 456)
 #define BT_UNITS_CONV_ALL       (STR_START + 457)
-#define STR_END                 (BT_UNITS_CONV_ALL)
+
+#define STR_UNDO_UNITSCONVERSION (STR_START + 458)
+
+#define STR_END                 (STR_UNDO_UNITSCONVERSION)
 
 #define BMP_START               (STR_END)
 
diff --git a/sc/source/ui/src/units.src b/sc/source/ui/src/units.src
index d666923..bc9a315 100644
--- a/sc/source/ui/src/units.src
+++ b/sc/source/ui/src/units.src
@@ -55,4 +55,9 @@ PushButton BT_UNITS_CONV_ALL
     Text [ en-US ] = "Convert (automatically for all cells needing $2)" ;
 };
 
+String STR_UNDO_UNITSCONVERSION
+{
+    Text [ en-US ] = "Units conversion";
+};
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index cd3a0ba..f046551 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -2984,8 +2984,7 @@ void ScViewFunc::NotifyUnitConversionRecommended( const ScAddress& rCellAddress,
                                                                                  rCellAddress,
                                                                                  pDoc,
                                                                                  rsHeaderUnit,
-                                                                                 rsCellUnit,
-                                                                                 pDocSh );
+                                                                                 rsCellUnit );
     pButtonConvertCell->SetClickHdl( LINK( this, ScViewFunc, UnitConversionRecommendedHandler ) );
 
     OUString sConvertText = pButtonConvertCell->GetText();
@@ -3002,32 +3001,108 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
 #ifdef ENABLE_CALC_UNITVERIFICATION
     boost::shared_ptr< Units > pUnits = Units::GetUnits();
 
-    ScDocShell* pDocShell = static_cast<ScDocShell*>(pButton->mpDoc->GetDocumentShell());
+    ScDocument* pDoc = pButton->mpDoc;
+    ScDocShell* pDocShell = static_cast<ScDocShell*>(pDoc->GetDocumentShell());
 
     ScDocShellModificator aModificator( *pDocShell );
+    bool bUndo = pDoc->IsUndoEnabled();
+    ScCellValue aOldVal;
+    ScDocument* pUndoDoc;
+    ScMarkData aMark;
 
-    OUString sOriginalValue = pButton->mpDoc->GetString( pButton->aCellAddress );
+    svl::IUndoManager* pUndoManager;
+    ScDrawLayer* pDrawLayer;
+
+    if ( bUndo )
+    {
+        pUndoManager = pDocShell->GetUndoManager();
+
+        aOldVal.assign( *pDoc, pButton->aCellAddress );
+
+        aMark.SetMarkArea( pButton->aCellAddress );
+        pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
+        pUndoDoc->InitUndo( pDoc, pButton->aCellAddress.Tab(), pButton->aCellAddress.Tab() );
+        pDoc->CopyToDocument( ScRange( pButton->aCellAddress ), IDF_ATTRIB, false, pUndoDoc, &aMark );
+
+        // This commences logging of changes to the drawing layer
+        // (i.e. notes) for storing in an undo. (See more below.)
+        pDrawLayer = pDoc->GetDrawLayer();
+        pDrawLayer->BeginCalcUndo(false);
+    }
+
+    OUString sOriginalValue = pDoc->GetString( pButton->aCellAddress );
 
     pUnits->convertCellToHeaderUnit( pButton->aCellAddress,
-                                     pButton->mpDoc,
+                                     pDoc,
                                      pButton->sHeaderUnit,
                                      pButton->sCellUnit );
 
-    ScPostIt* pNote = pButton->mpDoc->GetOrCreateNote( pButton->aCellAddress );
-    OUString sCurrentNote = pNote->GetText();
-
-    OUString sConversionNote("Original input: " + sOriginalValue);
+    const OUString sCurrentNoteText = pDoc->GetOrCreateNote( pButton->aCellAddress )->GetText();
+    const OUString sConversionNote("Original input: " + sOriginalValue);
+    OUString sNewNoteText;
 
-    if (sCurrentNote.isEmpty())
+    if (sCurrentNoteText.isEmpty())
     {
-        pNote->SetText( pButton->aCellAddress, sConversionNote );
+        sNewNoteText = sConversionNote;
     }
     else
     {
-        pNote->SetText( pButton->aCellAddress, sCurrentNote + "\n\n" + sConversionNote );
+        sNewNoteText = sCurrentNoteText + "\n\n" + sConversionNote;
     }
 
+    // ensure existing caption object before draw undo tracking starts
+    ScPostIt* pOldNote = pDoc->ReleaseNote( pButton->aCellAddress );
+    ScNoteData aOldNoteData = pOldNote->GetNoteData();
+    delete pOldNote;
+
+    ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( *pDoc, pButton->aCellAddress, sNewNoteText, false, true );
+    assert( pNewNote );
+
+    if ( bUndo )
+    {
+        const OUString aUndo( ScResId( STR_UNDO_UNITSCONVERSION ) );
+        pUndoManager->EnterListAction( aUndo, aUndo );
+
+        ScCellValue aNewVal;
+        aNewVal.assign( *pDoc, pButton->aCellAddress );
+        const ScPatternAttr* pNewPat = pDoc->GetPattern( pButton->aCellAddress );
+
+        pUndoManager->AddUndoAction( new ScUndoSetCell( pDocShell, pButton->aCellAddress, aOldVal, aNewVal ) );
+        pUndoManager->AddUndoAction( new ScUndoSelectionAttr( pDocShell,
+                                                              aMark,
+                                                              pButton->aCellAddress.Col(), pButton->aCellAddress.Row(), pButton->aCellAddress.Tab(),
+                                                              pButton->aCellAddress.Col(), pButton->aCellAddress.Row(), pButton->aCellAddress.Tab(),
+                                                              pUndoDoc,
+                                                              false,
+                                                              pNewPat) );
+        ScNoteData aNewNoteData = pNewNote->GetNoteData();
+
+        // We specifically need to differentiate between a completely new
+        // note, or editing an existing note. ScUndoReplaceNote has two
+        // different constructors for each case.
+        if ( sCurrentNoteText.isEmpty() )
+        {
+            pUndoManager->AddUndoAction( new ScUndoReplaceNote( *pDocShell, pButton->aCellAddress,
+                                                                aNewNoteData, true, nullptr ) );
+        }
+        else
+        {
+            // Actual note content changes are stored in the DrawLayer CalcUndo,
+            // as opposed to being the NoteData (which just seems to store note
+            // metadata) - hence we need to make sure that we save that too.
+            pUndoManager->AddUndoAction( new ScUndoReplaceNote( *pDocShell, pButton->aCellAddress,
+                                                                aOldNoteData, aNewNoteData,
+                                                                pDrawLayer->GetCalcUndo() ) );
+        }
+        pUndoManager->LeaveListAction();
+    }
+
+    pDocShell->PostPaint(ScRange( pButton->aCellAddress), PAINT_GRID);
+
     aModificator.SetDocumentModified();
+    SfxGetpApp()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
+
+
 #endif
 
     OUString sAddress;
commit 03ab4a1945ccf5f4e194bcaf64e88c1680018b9a
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Thu Aug 6 09:20:40 2015 +0100

    Remove redundant parameters.
    
    Change-Id: I0230fdd69d4f60058ca4f0258c5098f77099a3e4

diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index c6311d1..259bcf0 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/sc/source/ui/inc/viewfunc.hxx
@@ -377,8 +377,7 @@ private:
                                                      ScDocument* pDoc,
                                                      const OUString& sHeaderUnit,
                                                      const ScAddress& rHeaderAddress,
-                                                     const OUString& sCellUnit,
-                                                     ScDocShell* pDocSh );
+                                                     const OUString& sCellUnit );
     DECL_LINK( UnitConversionRecommendedHandler, UnitConversionPushButton* );
 };
 
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 125fe9d..cd3a0ba 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -596,7 +596,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
                 ScAddress aHeaderAddress;
 
                 if ( pUnits->isCellConversionRecommended( aAddress, pDoc, sHeaderUnit, aHeaderAddress, sCellUnit ) )
-                    NotifyUnitConversionRecommended( aAddress, pDoc, sHeaderUnit, aHeaderAddress, sCellUnit, pDocSh );
+                    NotifyUnitConversionRecommended( aAddress, pDoc, sHeaderUnit, aHeaderAddress, sCellUnit );
                 else
                 {
                     SfxViewFrame* pViewFrame = GetViewData().GetViewShell()->GetFrame();
@@ -2940,21 +2940,18 @@ struct UnitConversionPushButton: public PushButton
     ScDocument* mpDoc;
     const OUString sHeaderUnit;
     const OUString sCellUnit;
-    ScDocShell* mpDocSh;
 
     UnitConversionPushButton( vcl::Window* pParent,
                               const ResId& rResId,
                               const ScAddress& rCellAddress,
                               ScDocument* pDoc,
                               const OUString& rsHeaderUnit,
-                              const OUString& rsCellUnit,
-                              ScDocShell* pDocSh ):
+                              const OUString& rsCellUnit ):
         PushButton( pParent, rResId ),
         aCellAddress( rCellAddress ),
         mpDoc( pDoc ),
         sHeaderUnit( rsHeaderUnit ),
-        sCellUnit( rsCellUnit ),
-        mpDocSh( pDocSh )
+        sCellUnit( rsCellUnit )
         {}
 };
 
@@ -2962,8 +2959,8 @@ void ScViewFunc::NotifyUnitConversionRecommended( const ScAddress& rCellAddress,
                                                   ScDocument* pDoc,
                                                   const OUString& rsHeaderUnit,
                                                   const ScAddress& rHeaderAddress,
-                                                  const OUString& rsCellUnit,
-                                                  ScDocShell* pDocSh ) {
+                                                  const OUString& rsCellUnit )
+{
     SfxViewFrame* pViewFrame = GetViewData().GetViewShell()->GetFrame();
 
     // As with NotifyUnitErrorInFormula we use the cell address as the infobar id.
@@ -3005,7 +3002,9 @@ IMPL_LINK( ScViewFunc, UnitConversionRecommendedHandler, UnitConversionPushButto
 #ifdef ENABLE_CALC_UNITVERIFICATION
     boost::shared_ptr< Units > pUnits = Units::GetUnits();
 
-    ScDocShellModificator aModificator( *pButton->mpDocSh );
+    ScDocShell* pDocShell = static_cast<ScDocShell*>(pButton->mpDoc->GetDocumentShell());
+
+    ScDocShellModificator aModificator( *pDocShell );
 
     OUString sOriginalValue = pButton->mpDoc->GetString( pButton->aCellAddress );
 
commit da06bb25def1af25253efa9737683223607a78f3
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Wed Aug 5 19:50:55 2015 +0100

    Test for tdf#92455 (persist purely local annotations after conversion)
    
    Change-Id: I3f0ed297ef4eb9ac7876a9e24e3c2f0c1ec0b521

diff --git a/sc/qa/unit/units.cxx b/sc/qa/unit/units.cxx
index 28cffa2..86efc22 100644
--- a/sc/qa/unit/units.cxx
+++ b/sc/qa/unit/units.cxx
@@ -948,6 +948,18 @@ void UnitsTest::testRangeConversion() {
         // TODO: we need to test:
         // 1. actual sensible ranges
     }
+
+    // test purely local annotations (tdf#92455)
+    ScAddress headerAddressCol4(3, 0, nTab);
+
+    mpDoc->SetValue(headerAddressCol4, 3);
+    setNumberFormatUnit(headerAddressCol4, "m");
+
+    aRange = ScRange(headerAddressCol4);
+    CPPUNIT_ASSERT(mpUnitsImpl->convertCellUnits(aRange, mpDoc, "cm"));
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(mpDoc->GetValue(headerAddressCol4), 300, 1e-7);
+
+    CPPUNIT_ASSERT(UnitsImpl::extractUnitStringForCell(headerAddressCol4, mpDoc) == "cm");
 }
 
 void UnitsTest::testConvertCellUnits()
commit 31ac44715883c3c41c71fadae248f7a0ce8851d8
Author: Benjamin Ni <benjaminniri at hotmail.com>
Date:   Fri Jul 3 04:40:29 2015 +0100

    Added checkbox and config option to toggle unit verification
    
    Change-Id: Ie218821d05466b77ed42a26365b04a6798dec067

diff --git a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
index 8e1200e..db39071 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
@@ -1424,6 +1424,13 @@
           </info>
           <value>false</value>
         </prop>
+        <prop oor:name="UnitValidat" oor:type="xs:boolean" oor:nillable="false">
+          <!-- UIHints: Tools - Options  Spreadsheet  Formula -->
+          <info>
+            <desc>Whether to check for unit consistency upon entering formulae.</desc>
+          </info>
+          <value>false</value>
+        </prop>
         <prop oor:name="SeparatorArg" oor:type="xs:string" oor:nillable="false">
           <!-- UIHints: Tools - Options  Spreadsheet  Formula -->
           <info>
diff --git a/sc/inc/formulaopt.hxx b/sc/inc/formulaopt.hxx
index 8a903d2..f6d9e69 100644
--- a/sc/inc/formulaopt.hxx
+++ b/sc/inc/formulaopt.hxx
@@ -23,6 +23,7 @@ class SC_DLLPUBLIC ScFormulaOptions
 {
 private:
     bool bUseEnglishFuncName;     // use English function name even if the locale is not English.
+    bool bUnitValidat;
     formula::FormulaGrammar::Grammar eFormulaGrammar;  // formula grammar used to switch different formula syntax
     ScCalcConfig aCalcConfig;
     bool mbWriteCalcConfig;
@@ -53,6 +54,8 @@ public:
 
     void SetWriteCalcConfig( bool bVal ) { mbWriteCalcConfig = bVal; }
     bool GetWriteCalcConfig() const { return mbWriteCalcConfig; }
+    void SetUnitValidat( bool bVal ) { bUnitValidat = bVal; }
+    bool GetUnitValidat() const { return bUnitValidat; }
 
     void SetFormulaSepArg(const OUString& rSep) { aFormulaSepArg = rSep; }
     OUString GetFormulaSepArg() const { return aFormulaSepArg; }
diff --git a/sc/source/core/tool/formulaopt.cxx b/sc/source/core/tool/formulaopt.cxx
index db1bc0b..0855544 100644
--- a/sc/source/core/tool/formulaopt.cxx
+++ b/sc/source/core/tool/formulaopt.cxx
@@ -34,8 +34,9 @@ ScFormulaOptions::ScFormulaOptions()
 
 ScFormulaOptions::ScFormulaOptions( const ScFormulaOptions& rCpy ) :
     bUseEnglishFuncName ( rCpy.bUseEnglishFuncName ),
+    bUnitValidat        ( rCpy.bUnitValidat ),
     eFormulaGrammar     ( rCpy.eFormulaGrammar ),
-    aCalcConfig(rCpy.aCalcConfig),
+    aCalcConfig         ( rCpy.aCalcConfig ),
     mbWriteCalcConfig   (rCpy.mbWriteCalcConfig),
     aFormulaSepArg      ( rCpy.aFormulaSepArg ),
     aFormulaSepArrayRow ( rCpy.aFormulaSepArrayRow ),
@@ -52,6 +53,7 @@ ScFormulaOptions::~ScFormulaOptions()
 void ScFormulaOptions::SetDefaults()
 {
     bUseEnglishFuncName = false;
+    bUnitValidat = false;
     eFormulaGrammar     = ::formula::FormulaGrammar::GRAM_NATIVE;
     mbWriteCalcConfig = true;
     meOOXMLRecalc = RECALC_ASK;
@@ -129,9 +131,10 @@ const LocaleDataWrapper& ScFormulaOptions::GetLocaleDataWrapper()
 ScFormulaOptions& ScFormulaOptions::operator=( const ScFormulaOptions& rCpy )
 {
     bUseEnglishFuncName = rCpy.bUseEnglishFuncName;
+    bUnitValidat        = rCpy.bUnitValidat;
     eFormulaGrammar     = rCpy.eFormulaGrammar;
-    aCalcConfig = rCpy.aCalcConfig;
-    mbWriteCalcConfig = rCpy.mbWriteCalcConfig;
+    aCalcConfig         = rCpy.aCalcConfig;
+    mbWriteCalcConfig   = rCpy.mbWriteCalcConfig;
     aFormulaSepArg      = rCpy.aFormulaSepArg;
     aFormulaSepArrayRow = rCpy.aFormulaSepArrayRow;
     aFormulaSepArrayCol = rCpy.aFormulaSepArrayCol;
@@ -143,8 +146,9 @@ ScFormulaOptions& ScFormulaOptions::operator=( const ScFormulaOptions& rCpy )
 bool ScFormulaOptions::operator==( const ScFormulaOptions& rOpt ) const
 {
     return bUseEnglishFuncName == rOpt.bUseEnglishFuncName
+        && bUnitValidat        == rOpt.bUnitValidat
         && eFormulaGrammar     == rOpt.eFormulaGrammar
-        && aCalcConfig == rOpt.aCalcConfig
+        && aCalcConfig         == rOpt.aCalcConfig
         && mbWriteCalcConfig   == rOpt.mbWriteCalcConfig
         && aFormulaSepArg      == rOpt.aFormulaSepArg
         && aFormulaSepArrayRow == rOpt.aFormulaSepArrayRow
@@ -189,22 +193,23 @@ SfxPoolItem* ScTpFormulaItem::Clone( SfxItemPool * ) const
 
 #define CFGPATH_FORMULA           "Office.Calc/Formula"
 
-#define SCFORMULAOPT_GRAMMAR              0
-#define SCFORMULAOPT_ENGLISH_FUNCNAME     1
-#define SCFORMULAOPT_SEP_ARG              2
-#define SCFORMULAOPT_SEP_ARRAY_ROW        3
-#define SCFORMULAOPT_SEP_ARRAY_COL        4
-#define SCFORMULAOPT_STRING_REF_SYNTAX    5
-#define SCFORMULAOPT_STRING_CONVERSION    6
-#define SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO 7
-#define SCFORMULAOPT_OOXML_RECALC         8
-#define SCFORMULAOPT_ODF_RECALC           9
-#define SCFORMULAOPT_OPENCL_AUTOSELECT   10
-#define SCFORMULAOPT_OPENCL_DEVICE       11
-#define SCFORMULAOPT_OPENCL_SUBSET_ONLY  12
-#define SCFORMULAOPT_OPENCL_MIN_SIZE     13
-#define SCFORMULAOPT_OPENCL_SUBSET_OPS   14
-#define SCFORMULAOPT_COUNT               15
+#define SCFORMULAOPT_GRAMMAR                0
+#define SCFORMULAOPT_ENGLISH_FUNCNAME       1
+#define SCFORMULAOPT_UNIT_VALIDAT           2
+#define SCFORMULAOPT_SEP_ARG                3
+#define SCFORMULAOPT_SEP_ARRAY_ROW          4
+#define SCFORMULAOPT_SEP_ARRAY_COL          5
+#define SCFORMULAOPT_STRING_REF_SYNTAX      6
+#define SCFORMULAOPT_STRING_CONVERSION      7
+#define SCFORMULAOPT_EMPTY_OUSTRING_AS_ZERO 8
+#define SCFORMULAOPT_OOXML_RECALC           9
+#define SCFORMULAOPT_ODF_RECALC            10
+#define SCFORMULAOPT_OPENCL_AUTOSELECT     11
+#define SCFORMULAOPT_OPENCL_DEVICE         12
+#define SCFORMULAOPT_OPENCL_SUBSET_ONLY    13
+#define SCFORMULAOPT_OPENCL_MIN_SIZE       14
+#define SCFORMULAOPT_OPENCL_SUBSET_OPS     15
+#define SCFORMULAOPT_COUNT                 16
 
 Sequence<OUString> ScFormulaCfg::GetPropertyNames()
 {
@@ -212,6 +217,7 @@ Sequence<OUString> ScFormulaCfg::GetPropertyNames()
     {
         "Syntax/Grammar",                // SCFORMULAOPT_GRAMMAR
         "Syntax/EnglishFunctionName",    // SCFORMULAOPT_ENGLISH_FUNCNAME
+        "Syntax/UnitValidat",            // SCFORMULAOPT_UNIT_VALIDAT
         "Syntax/SeparatorArg",           // SCFORMULAOPT_SEP_ARG
         "Syntax/SeparatorArrayRow",      // SCFORMULAOPT_SEP_ARRAY_ROW
         "Syntax/SeparatorArrayCol",      // SCFORMULAOPT_SEP_ARRAY_COL
@@ -240,6 +246,7 @@ ScFormulaCfg::PropsToIds ScFormulaCfg::GetPropNamesToId()
     static sal_uInt16 aVals[] = {
         SCFORMULAOPT_GRAMMAR,
         SCFORMULAOPT_ENGLISH_FUNCNAME,
+        SCFORMULAOPT_UNIT_VALIDAT,
         SCFORMULAOPT_SEP_ARG,
         SCFORMULAOPT_SEP_ARRAY_ROW,
         SCFORMULAOPT_SEP_ARRAY_COL,
@@ -323,6 +330,13 @@ void ScFormulaCfg::UpdateFromProperties( const Sequence<OUString>& aNames )
                         SetUseEnglishFuncName(bEnglish);
                 }
                 break;
+                case SCFORMULAOPT_UNIT_VALIDAT:
+                {
+                    bool bValidat = false;
+                    if (pValues[nProp] >>= bValidat)
+                        SetUnitValidat(bValidat);
+                }
+                break;
                 case SCFORMULAOPT_SEP_ARG:
                 {
                     OUString aSep;
@@ -542,6 +556,12 @@ void ScFormulaCfg::ImplCommit()
                 pValues[nProp] <<= b;
             }
             break;
+            case SCFORMULAOPT_UNIT_VALIDAT:
+            {
+                bool b = GetUnitValidat();
+                pValues[nProp] <<= b;
+            }
+            break;
             case SCFORMULAOPT_SEP_ARG:
                 pValues[nProp] <<= GetFormulaSepArg();
             break;
diff --git a/sc/source/ui/inc/tpformula.hxx b/sc/source/ui/inc/tpformula.hxx
index 3c7ed8c..e9a4c41 100644
--- a/sc/source/ui/inc/tpformula.hxx
+++ b/sc/source/ui/inc/tpformula.hxx
@@ -60,6 +60,7 @@ private:
 private:
     VclPtr<ListBox>     mpLbFormulaSyntax;
     VclPtr<CheckBox>    mpCbEnglishFuncName;
+    VclPtr<CheckBox>    mpCbUnitValidat;
 
     VclPtr<RadioButton> mpBtnCustomCalcDefault;
     VclPtr<RadioButton> mpBtnCustomCalcCustom;
diff --git a/sc/source/ui/optdlg/tpformula.cxx b/sc/source/ui/optdlg/tpformula.cxx
index 789555d..d9eb16d 100644
--- a/sc/source/ui/optdlg/tpformula.cxx
+++ b/sc/source/ui/optdlg/tpformula.cxx
@@ -44,6 +44,7 @@ ScTpFormulaOptions::ScTpFormulaOptions(vcl::Window* pParent, const SfxItemSet& r
 {
     get(mpLbFormulaSyntax, "formulasyntax");
     get(mpCbEnglishFuncName, "englishfuncname");
+    get(mpCbUnitValidat, "unitvalidat");
     get(mpBtnCustomCalcDefault, "calcdefault");
     get(mpBtnCustomCalcCustom, "calccustom");
     get(mpBtnCustomCalcDetails, "details");
@@ -92,6 +93,7 @@ void ScTpFormulaOptions::dispose()
 {
     mpLbFormulaSyntax.clear();
     mpCbEnglishFuncName.clear();
+    mpCbUnitValidat.clear();
     mpBtnCustomCalcDefault.clear();
     mpBtnCustomCalcCustom.clear();
     mpBtnCustomCalcDetails.clear();
@@ -246,6 +248,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet)
     bool bRet = false;
     ScFormulaOptions aOpt;
     bool bEnglishFuncName = mpCbEnglishFuncName->IsChecked();
+    bool bUnitValidat     = mpCbUnitValidat->IsChecked();
     sal_Int16 aSyntaxPos      = mpLbFormulaSyntax->GetSelectEntryPos();
     OUString aSep             = mpEdSepFuncArg->GetText();
     OUString aSepArrayCol     = mpEdSepArrayCol->GetText();
@@ -261,6 +264,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet)
 
     if ( mpLbFormulaSyntax->GetSavedValue() != aSyntaxPos
          || mpCbEnglishFuncName->GetSavedValue() != (bEnglishFuncName ? 1 : 0)
+         || mpCbUnitValidat->GetSavedValue() != (bUnitValidat ? 1 : 0)
          || static_cast<OUString>(mpEdSepFuncArg->GetSavedValue()) != aSep
          || static_cast<OUString>(mpEdSepArrayCol->GetSavedValue()) != aSepArrayCol
          || static_cast<OUString>(mpEdSepArrayRow->GetSavedValue()) != aSepArrayRow
@@ -289,6 +293,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet)
 
         aOpt.SetFormulaSyntax(eGram);
         aOpt.SetUseEnglishFuncName(bEnglishFuncName);
+        aOpt.SetUnitValidat(bUnitValidat);
         aOpt.SetFormulaSepArg(aSep);
         aOpt.SetFormulaSepArrayCol(aSepArrayCol);
         aOpt.SetFormulaSepArrayRow(aSepArrayRow);
@@ -345,6 +350,10 @@ void ScTpFormulaOptions::Reset(const SfxItemSet* rCoreSet)
     mpCbEnglishFuncName->Check( aOpt.GetUseEnglishFuncName() );
     mpCbEnglishFuncName->SaveValue();
 
+    // unit validation
+    mpCbUnitValidat->Check( aOpt.GetUnitValidat() );
+    mpCbUnitValidat->SaveValue();
+
     // Separators
     OUString aSep = aOpt.GetFormulaSepArg();
     OUString aSepArrayRow = aOpt.GetFormulaSepArrayRow();
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 402c574..125fe9d 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -471,25 +471,28 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
             }
 
 #ifdef ENABLE_CALC_UNITVERIFICATION
-            boost::shared_ptr< Units > pUnits = Units::GetUnits();
-            FormulaStatus aStatus = pUnits->verifyFormula( pArr, aPos, pDoc );
-            if ( aStatus == FormulaStatus::VALID || aStatus == FormulaStatus::UNKNOWN )
+            if ( SC_MOD()->GetFormulaOptions().GetUnitValidat() )
             {
-                SAL_INFO( "sc.units", "verification successful" );
-
-                // If we have fixed a previously erronous cell we need to make sure we remove
-                // the associate warning infobar. It's simplest to simply call RemoveInfoBar
-                // with the hypothetical ID, and RemoveInfoBar deals with the remaning details.
-                // (The cell address is used as it's infobar id, see NotifyUnitErrorInFormula
-                // for further details.)
-                SfxViewFrame* pViewFrame = GetViewData().GetViewShell()->GetFrame();
-                OUString sAddress = aPos.Format( SCA_BITS, pDoc );
-                pViewFrame->RemoveInfoBar( sAddress );
-            }
-            else
-            {
-                SAL_INFO( "sc.units", "verification failed" );
-                NotifyUnitErrorInFormula( aPos, pDoc, aStatus );
+                boost::shared_ptr< Units > pUnits = Units::GetUnits();
+                FormulaStatus aStatus = pUnits->verifyFormula( pArr, aPos, pDoc );
+                if ( aStatus == FormulaStatus::VALID || aStatus == FormulaStatus::UNKNOWN )
+                {
+                    SAL_INFO( "sc.units", "verification successful" );
+
+                    // If we have fixed a previously erronous cell we need to make sure we remove
+                    // the associate warning infobar. It's simplest to simply call RemoveInfoBar
+                    // with the hypothetical ID, and RemoveInfoBar deals with the remaning details.
+                    // (The cell address is used as it's infobar id, see NotifyUnitErrorInFormula
+                    // for further details.)
+                    SfxViewFrame* pViewFrame = GetViewData().GetViewShell()->GetFrame();
+                    OUString sAddress = aPos.Format( SCA_BITS, pDoc );
+                    pViewFrame->RemoveInfoBar( sAddress );
+                }
+                else
+                {
+                    SAL_INFO( "sc.units", "verification failed" );
+                    NotifyUnitErrorInFormula( aPos, pDoc, aStatus );
+                }
             }
 #endif
         } while ( bAgain );
@@ -585,17 +588,21 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab,
             }
 
 #ifdef ENABLE_CALC_UNITVERIFICATION
-            boost::shared_ptr< Units > pUnits = Units::GetUnits();
+            if ( SC_MOD()->GetFormulaOptions().GetUnitValidat() )
+            {
+                boost::shared_ptr< Units > pUnits = Units::GetUnits();
 
-            OUString sHeaderUnit, sCellUnit;
-            ScAddress aHeaderAddress;
+                OUString sHeaderUnit, sCellUnit;
+                ScAddress aHeaderAddress;
 
-            if ( pUnits->isCellConversionRecommended( aAddress, pDoc, sHeaderUnit, aHeaderAddress, sCellUnit ) ) {
-                NotifyUnitConversionRecommended( aAddress, pDoc, sHeaderUnit, aHeaderAddress, sCellUnit, pDocSh );
-            } else {
-                SfxViewFrame* pViewFrame = GetViewData().GetViewShell()->GetFrame();
-                OUString sAddress = aAddress.Format( SCA_BITS, pDoc );
-                pViewFrame->RemoveInfoBar( sAddress );
+                if ( pUnits->isCellConversionRecommended( aAddress, pDoc, sHeaderUnit, aHeaderAddress, sCellUnit ) )
+                    NotifyUnitConversionRecommended( aAddress, pDoc, sHeaderUnit, aHeaderAddress, sCellUnit, pDocSh );
+                else
+                {
+                    SfxViewFrame* pViewFrame = GetViewData().GetViewShell()->GetFrame();
+                    OUString sAddress = aAddress.Format( SCA_BITS, pDoc );
+                    pViewFrame->RemoveInfoBar( sAddress );
+                }
             }
 #endif
         }
diff --git a/sc/uiconfig/scalc/ui/optformula.ui b/sc/uiconfig/scalc/ui/optformula.ui
index 4e66f81..2b63101 100644
--- a/sc/uiconfig/scalc/ui/optformula.ui
+++ b/sc/uiconfig/scalc/ui/optformula.ui
@@ -32,6 +32,23 @@
                 <property name="can_focus">False</property>
                 <property name="row_spacing">6</property>
                 <child>
+                  <object class="GtkCheckButton" id="unitvalidat">
+                    <property name="label" translatable="yes">Enable unit validation check</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_underline">False</property>
+                    <property name="xalign">0</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkCheckButton" id="englishfuncname">
                     <property name="label" translatable="yes">Use English function names</property>
                     <property name="visible">True</property>
commit ff257403fed69615080515a68c41e7c8f697f456
Author: Benjamin Ni <benjaminniri at hotmail.com>
Date:   Fri Jul 3 16:45:52 2015 +0100

    tdf#92455 - inconsistent unit handling
    
    Change-Id: Ifbb85a32ef9d84199d17cedd28fa0f9e66eabf66

diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index c2e39f9..0c89201 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -789,8 +789,9 @@ bool UnitsImpl::convertCellUnitsForColumnRange(const ScRange& rRange,
                 }
             }
 
-            bool bLocalAnnotationRequired = (aHeader.address && !rRange.In(*aHeader.address)) &&
-                (rOutputUnit != aHeader.unit);
+            bool bLocalAnnotationRequired = !aHeader.address || (
+                                            !rRange.In(*aHeader.address) &&
+                                            (rOutputUnit != aHeader.unit) );
             double nValue = pDoc->GetValue(aCurrent);
 
             if (!aLocalUnit.areConvertibleTo(rOutputUnit))
commit 67c4c1c5b2a0183b0fb05222096193c7abd146b3
Author: Benjamin Ni <benjaminniri at hotmail.com>
Date:   Fri Jul 3 15:20:19 2015 +0100

    Coding style cleanup
    
    Change-Id: I6171ba59e4df40dfc4734204832857f0fe7637e9
    Reviewed-on: https://gerrit.libreoffice.org/16738
    Reviewed-by: Markus Mohrhard <markus.mohrhard at googlemail.com>
    Tested-by: Markus Mohrhard <markus.mohrhard at googlemail.com>

diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index 4f0057c..c2e39f9 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -751,19 +751,24 @@ bool UnitsImpl::convertCellUnitsForColumnRange(const ScRange& rRange,
         // It's possible that the header refers to an incompatible unit, hence
         // shouldn't be modified when we're converting.
         if (aCurrent == aHeader.address &&
-            aHeader.unit.areConvertibleTo(rOutputUnit)) {
+            aHeader.unit.areConvertibleTo(rOutputUnit) )
+        {
             OUString sHeader = pDoc->GetString(aCurrent);
             sHeader = sHeader.replaceAt(aHeader.unitStringPosition, aHeader.unitString.getLength(), *rOutputUnit.getInputString());
             pDoc->SetString(aCurrent, sHeader);
 
             aHeader.valid = false;
-        } else if (pDoc->GetCellType(aCurrent) != CELLTYPE_STRING) {
-            if (!aHeader.valid) {
+        }
+        else if (pDoc->GetCellType(aCurrent) != CELLTYPE_STRING)
+        {
+            if (!aHeader.valid)
+            {
                 aHeader = findHeaderUnitForCell(aCurrent, pDoc);
 
                 // If there is no header we get an invalid unit returned from findHeaderUnitForCell,
                 // and therfore assume the dimensionless unit 1.
-                if (!aHeader.valid) {
+                if (!aHeader.valid)
+                {
                     UtUnit::createUnit("", aHeader.unit, mpUnitSystem);
                     aHeader.valid = true;
                 }
@@ -771,10 +776,14 @@ bool UnitsImpl::convertCellUnitsForColumnRange(const ScRange& rRange,
 
             OUString sLocalUnit(extractUnitStringForCell(aCurrent, pDoc));
             UtUnit aLocalUnit;
-            if (sLocalUnit.isEmpty()) {
+            if (sLocalUnit.isEmpty())
+            {
                 aLocalUnit = aHeader.unit;
-            } else { // override header unit with annotation unit
-                if (!UtUnit::createUnit(sLocalUnit, aLocalUnit, mpUnitSystem)) {
+            }
+            else
+            { // override header unit with annotation unit
+                if (!UtUnit::createUnit(sLocalUnit, aLocalUnit, mpUnitSystem))
+                {
                     // but assume dimensionless if invalid
                     UtUnit::createUnit("", aLocalUnit, mpUnitSystem);
                 }
@@ -784,13 +793,17 @@ bool UnitsImpl::convertCellUnitsForColumnRange(const ScRange& rRange,
                 (rOutputUnit != aHeader.unit);
             double nValue = pDoc->GetValue(aCurrent);
 
-            if (!aLocalUnit.areConvertibleTo(rOutputUnit)) {
+            if (!aLocalUnit.areConvertibleTo(rOutputUnit))
+            {
                 bAllConverted = false;
-            } else {
+            }
+            else
+            {
                 double nNewValue = aLocalUnit.convertValueTo(nValue, rOutputUnit);
                 pDoc->SetValue(aCurrent, nNewValue);
 
-                if (bLocalAnnotationRequired) {
+                if (bLocalAnnotationRequired)
+                {
                     // All a local dirty hack too - needs to be refactored and improved.
                     // And ideally we should reuse the existing format.
                     OUString sNewFormat = "General\"" + *rOutputUnit.getInputString() + "\"";
@@ -801,7 +814,9 @@ bool UnitsImpl::convertCellUnitsForColumnRange(const ScRange& rRange,
                     SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
                     pFormatter->PutEntry(sNewFormat, nErrorPosition, nType, nFormatKey);
                     pDoc->SetNumberFormat(aCurrent, nFormatKey);
-                } else {
+                }
+                else
+                {
                     // The number formats will by definition be wrong once we've converted, so just reset completely.
                     pDoc->SetNumberFormat(aCurrent, 0);
                 }
commit 732e791f49ffebb5b7a97c161693eb032fe29934
Author: Benjamin Ni <benjaminniri at hotmail.com>
Date:   Tue Jun 30 06:40:38 2015 +0100

    Added more range conversion tests
    
    Change-Id: If4898e6c70cb9731af35d51457de28410f808b96

diff --git a/sc/qa/unit/units.cxx b/sc/qa/unit/units.cxx
index ee6af8a..28cffa2 100644
--- a/sc/qa/unit/units.cxx
+++ b/sc/qa/unit/units.cxx
@@ -321,6 +321,13 @@ void UnitsTest::testUnitVerification() {
     pTokens = pCell->GetCode();
     CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
+    // SUM("cm","m")
+    address.IncRow();
+    mpDoc->SetFormula(address, "=SUM(A1,E1)");
+    pCell = mpDoc->GetFormulaCell(address);
+    pTokens = pCell->GetCode();
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::ERROR_INPUT_SCALING);
+
     // PRODUCT("cm/","s")+"cm"
     address.IncRow();
     mpDoc->SetFormula(address, "=PRODUCT(C1:D1)+A1");
@@ -803,82 +810,144 @@ void UnitsTest::testRangeConversion() {
     mpDoc->EnsureTable(nTab);
 
     // Column 1: convert [cm] to [cm].
-    ScAddress headerAddress(0, 0, nTab);
-    mpDoc->SetString(headerAddress, "length [cm]");
+    ScAddress headerAddressCol1(0, 0, nTab);
+    mpDoc->SetString(headerAddressCol1, "length [cm]");
 
-    ScAddress address(headerAddress);
+    ScAddress addressCol1(headerAddressCol1);
 
     vector<double> values({10, 20, 30, 40, 1, 0.5, 0.25});
-    address.IncRow();
-    mpDoc->SetValues(address, values);
+    addressCol1.IncRow();
+    mpDoc->SetValues(addressCol1, values);
 
     // Test conversion of range _not_ including header
-    ScAddress endAddress( address.Col(), address.Row() + values.size() - 1, nTab);
+    ScAddress endAddressCol1( addressCol1.Col(), addressCol1.Row() + values.size() - 1, nTab);
 
-    ScRange aRange(address, endAddress);
+    ScRange aRange(addressCol1, endAddressCol1);
     CPPUNIT_ASSERT(mpUnitsImpl->convertCellUnits(aRange, mpDoc, "cm"));
     CPPUNIT_ASSERT(!mpUnitsImpl->convertCellUnits(aRange, mpDoc, "kg"));
 
-    CPPUNIT_ASSERT(mpDoc->GetString(headerAddress) == "length [cm]");
+    CPPUNIT_ASSERT(mpDoc->GetString(headerAddressCol1) == "length [cm]");
 
-    for (double d: values) {
+    for (double d: values)
+    {
         // Test that the value is unchanged
-        CPPUNIT_ASSERT(mpDoc->GetValue(address) == d);
+        CPPUNIT_ASSERT(mpDoc->GetValue(addressCol1) == d);
         // And NO annotation has been added
-        CPPUNIT_ASSERT(mpDoc->GetString(address) == OUString::number(d));
-        address.IncRow();
+        CPPUNIT_ASSERT(mpDoc->GetString(addressCol1) == OUString::number(d));
+        addressCol1.IncRow();
     }
 
     // Test conversion of range including header (from cm to cm)
-    aRange = ScRange(headerAddress, endAddress);
+    aRange = ScRange(headerAddressCol1, endAddressCol1);
     CPPUNIT_ASSERT(mpUnitsImpl->convertCellUnits(aRange, mpDoc, "cm"));
     CPPUNIT_ASSERT(!mpUnitsImpl->convertCellUnits(aRange, mpDoc, "kg"));
 
-    CPPUNIT_ASSERT(mpDoc->GetString(headerAddress) == "length [cm]");
+    CPPUNIT_ASSERT(mpDoc->GetString(headerAddressCol1) == "length [cm]");
 
-    address = headerAddress;
-    address.IncRow();
-    for (double d: values) {
-        CPPUNIT_ASSERT_DOUBLES_EQUAL(mpDoc->GetValue(address), d, 1e-7);
+    addressCol1 = headerAddressCol1;
+    addressCol1.IncRow();
+    for (double d: values)
+    {
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(mpDoc->GetValue(addressCol1), d, 1e-7);
         // And NO annotation has been added
-        CPPUNIT_ASSERT(mpDoc->GetString(address) == OUString::number(d));
-        address.IncRow();
+        CPPUNIT_ASSERT(mpDoc->GetString(addressCol1) == OUString::number(d));
+        addressCol1.IncRow();
     }
 
     // Convert just the values (but not header): [cm] to [m]
-    address.SetRow(1);
-    aRange = ScRange(address, endAddress);
+    addressCol1.SetRow(1);
+    aRange = ScRange(addressCol1, endAddressCol1);
     CPPUNIT_ASSERT(mpUnitsImpl->convertCellUnits(aRange, mpDoc, "m"));
 
-    CPPUNIT_ASSERT(mpDoc->GetString(headerAddress) == "length [cm]");
+    CPPUNIT_ASSERT(mpDoc->GetString(headerAddressCol1) == "length [cm]");
 
-    for (double d: values) {
-        CPPUNIT_ASSERT_DOUBLES_EQUAL(mpDoc->GetValue(address), d/100, 1e-7);
-        // AND test annotation
-        // Disabled for now until the precision problems are figured out
-        // CPPUNIT_ASSERT(mpDoc->GetString(address) == OUString::number(d/100) + "m");
-        address.IncRow();
+    for (double d: values)
+    {
+        OUString aResultStr = mpDoc->GetString(addressCol1);
+        OUString aValStr  = aResultStr.copy( 0, aResultStr.getLength() - 1 ); // value portion of result
+        OUString aUnitStr = aResultStr.copy( aResultStr.getLength() - 1, 1 ); // annotation portion of result
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(aValStr.toDouble(), d/100, 1e-7);
+        CPPUNIT_ASSERT(aUnitStr == "m");
+        addressCol1.IncRow();
     }
 
     // Convert everything (including header) to mm: [m] to [mm]
-    aRange = ScRange(headerAddress, endAddress);
+    aRange = ScRange(headerAddressCol1, endAddressCol1);
     CPPUNIT_ASSERT(mpUnitsImpl->convertCellUnits(aRange, mpDoc, "mm"));
 
-    CPPUNIT_ASSERT(mpDoc->GetString(headerAddress) == "length [mm]");
+    CPPUNIT_ASSERT(mpDoc->GetString(headerAddressCol1) == "length [mm]");
 
-    address.SetRow(1);
+    addressCol1.SetRow(1);
 
-    for (double d: values) {
-        CPPUNIT_ASSERT_DOUBLES_EQUAL(mpDoc->GetValue(address), d*10, 1e-7);
+    for (double d: values)
+    {
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(mpDoc->GetValue(addressCol1), d*10, 1e-7);
         // And the annotation has been REMOVED
-        CPPUNIT_ASSERT(mpDoc->GetString(address) == OUString::number(d*10));
-        address.IncRow();
+        CPPUNIT_ASSERT(mpDoc->GetString(addressCol1) == OUString::number(d*10));
+        addressCol1.IncRow();
     }
 
-    // TODO: we need to test:
-    // 1. mixture of units that can't be converted
-    // 2. mixtures of local and header annotations
-    // 3. actual sensible ranges
+    // Column 2: [kg]
+    ScAddress headerAddressCol2(1, 0, nTab);
+    mpDoc->SetString(headerAddressCol2, "weight [kg]");
+
+    ScAddress addressCol2(headerAddressCol2);
+    addressCol2.IncRow();
+    mpDoc->SetValues(addressCol2, values);
+
+    ScAddress endAddressCol2( addressCol2.Col(), addressCol2.Row() + values.size() - 1, nTab);
+
+    // Column 3: [kg] (replica of Col2, but offset downwards by 1 cell)
+    ScAddress headerAddressCol3(2, 1, nTab);
+    mpDoc->SetString(headerAddressCol3, "weight [kg]");
+
+    ScAddress addressCol3(headerAddressCol3);
+    addressCol3.IncRow();
+    mpDoc->SetValues(addressCol3, values);
+
+    ScAddress endAddressCol3( addressCol3.Col(), addressCol3.Row() + values.size() - 1, nTab);
+
+    // test mixture [mm, kg] convert to [m]
+    addressCol1.SetRow(1);
+    aRange = ScRange(addressCol1, endAddressCol2); // over range of cm and kg values
+
+    CPPUNIT_ASSERT(!mpUnitsImpl->convertCellUnits(aRange, mpDoc, "m"));
+    for (double d: values) // test that convertible units are still converted
+    {
+        OUString aResultStr = mpDoc->GetString(addressCol1);
+        OUString aValStr  = aResultStr.copy( 0, aResultStr.getLength() - 1 ); // value portion of result
+        OUString aUnitStr = aResultStr.copy( aResultStr.getLength() - 1, 1 ); // annotation portion of result
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(aValStr.toDouble(), d/100, 1e-7);
+        CPPUNIT_ASSERT(aUnitStr == "m");
+        addressCol1.IncRow();
+    }
+
+    // test mixture of local (Col2) and header (Col3) annotations
+    addressCol2.SetRow(1);
+    addressCol3.SetRow(2);
+
+    aRange = ScRange(addressCol2, endAddressCol3); // Col2 local, Col3 header
+    CPPUNIT_ASSERT(mpUnitsImpl->convertCellUnits(aRange, mpDoc, "g"));
+    CPPUNIT_ASSERT(mpDoc->GetString(headerAddressCol2) == "weight [kg]");
+    CPPUNIT_ASSERT(mpDoc->GetString(headerAddressCol3) == "weight [g]" );
+    for (double d: values)
+    {
+        OUString aResultStr = mpDoc->GetString(addressCol2);
+        OUString aValStr  = aResultStr.copy( 0, aResultStr.getLength() - 1 ); // value portion of result
+        OUString aUnitStr = aResultStr.copy( aResultStr.getLength() - 1, 1 ); // annotation portion of result
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(aValStr.toDouble(), d*1000, 1e-7);
+        CPPUNIT_ASSERT(aUnitStr == "g");
+        addressCol2.IncRow();
+
+        if (addressCol3 != endAddressCol3)
+        {
+            CPPUNIT_ASSERT_DOUBLES_EQUAL(mpDoc->GetString(addressCol3).toDouble(), d*1000, 1e-7);
+            addressCol3.IncRow();
+        }
+
+        // TODO: we need to test:
+        // 1. actual sensible ranges
+    }
 }
 
 void UnitsTest::testConvertCellUnits()
commit f373ffc59bf90ddda82ed1b8a538b4f1f8074723
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Jun 30 14:38:09 2015 +0200

    refresh cell rendering after changing unit
    
    Change-Id: I6f68c319df89906b29d1f8409f6170a0b68c8b87

diff --git a/sc/source/ui/miscdlgs/unitsconversiondlg.cxx b/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
index edd611e..a3a6744 100644
--- a/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
+++ b/sc/source/ui/miscdlgs/unitsconversiondlg.cxx
@@ -13,6 +13,7 @@
 #include "reffact.hxx"
 #include "units.hxx"
 #include "viewdata.hxx"
+#include "docsh.hxx"
 
 using namespace sc::units;
 
@@ -266,7 +267,13 @@ void ScUnitsConversionDialog::PerformConversion()
 {
     OUString sOutputUnit = mpOutputUnitsEdit->GetText();
 
+    ScDocShell* pDocShell = static_cast<ScDocShell*>(mpDoc->GetDocumentShell());
+    ScDocShellModificator aModificator(*pDocShell);
     mpUnits->convertCellUnits( *mInputRange, mpDoc, sOutputUnit );
+    pDocShell->PostPaint(*mInputRange, PAINT_GRID);
+
+    aModificator.SetDocumentModified();
+    SfxGetpApp()->Broadcast(SfxSimpleHint(SC_HINT_AREAS_CHANGED));
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 123067c884105ee2d1fc252cdd060597c3035139
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Jun 30 09:25:29 2015 +0200

    add test case for unit conversion
    
    Change-Id: I726758c93b25ed16b5708a71645004537f32ac76

diff --git a/sc/qa/unit/units.cxx b/sc/qa/unit/units.cxx
index 1dbf74f..ee6af8a 100644
--- a/sc/qa/unit/units.cxx
+++ b/sc/qa/unit/units.cxx
@@ -14,6 +14,8 @@
 
 #include "helper/qahelper.hxx"
 
+#include "rangelst.hxx"
+
 #include <com/sun/star/util/NumberFormat.hpp>
 
 using namespace sc::units;
@@ -50,6 +52,7 @@ public:
 
     void testUnitsCompatible();
     void testCellConversion();
+    void testConvertCellUnits();
     void testUnitsForRange();
     void testRangeConversion();
 
@@ -64,6 +67,7 @@ public:
 
     CPPUNIT_TEST(testUnitsCompatible);
     CPPUNIT_TEST(testCellConversion);
+    CPPUNIT_TEST(testConvertCellUnits);
     CPPUNIT_TEST(testUnitsForRange);
     CPPUNIT_TEST(testRangeConversion);
 
@@ -877,6 +881,22 @@ void UnitsTest::testRangeConversion() {
     // 3. actual sensible ranges
 }
 
+void UnitsTest::testConvertCellUnits()
+{
+    mpDoc->EnsureTable(0);
+
+    // Set up a column with a normal header and a few data values
+    ScAddress aAddress(20, 0, 0);
+    mpDoc->SetString(aAddress, "100km");
+    ScRange aRange(aAddress);
+    ScRangeList aRangeList(aRange);
+    OUString aOutput("miles");
+    bool bConverted = mpUnitsImpl->convertCellUnits(aRangeList, mpDoc, aOutput);
+    CPPUNIT_ASSERT(bConverted);
+    double nVal = mpDoc->GetValue(aAddress);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(62.1371192932129, nVal, 1e-14);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(UnitsTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit a6576c9a03046b4589b429f718e46a27514c4606
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Jun 30 09:25:07 2015 +0200

    fix crash when converting units
    
    Change-Id: Ic883e13b5c6923c31e65a887597f0910807dc94d

diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index 7d16ae3..4f0057c 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -780,7 +780,7 @@ bool UnitsImpl::convertCellUnitsForColumnRange(const ScRange& rRange,
                 }
             }
 
-            bool bLocalAnnotationRequired = (!rRange.In(*aHeader.address)) &&
+            bool bLocalAnnotationRequired = (aHeader.address && !rRange.In(*aHeader.address)) &&
                 (rOutputUnit != aHeader.unit);
             double nValue = pDoc->GetValue(aCurrent);
 
commit eafdfe0725b156a9f5ace821f5a0d7299d811025
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Jun 29 18:29:52 2015 +0200

    fix build and adapt a few places to calc coding style
    
    Change-Id: I9759b96f7ba53c6737ea1576f16d6b46ad5f472b

diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index 66f5019..7d16ae3 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -281,7 +281,8 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
     return { FormulaStatus::VALID, pOut };
 }
 
-OUString UnitsImpl::extractUnitStringFromFormat(const OUString& rFormatString) {
+OUString UnitsImpl::extractUnitStringFromFormat(const OUString& rFormatString)
+{
     // TODO: decide what we do for different subformats? Simplest solution
     // would be to not allow unit storage for multiple subformats.
     // TODO: we should check the number of subformats here in future?
@@ -291,16 +292,19 @@ OUString UnitsImpl::extractUnitStringFromFormat(const OUString& rFormatString) {
     sal_Int32 nPos = rFormatString.getLength() - 1;
 
     // Only iterate if we have a string item at the end of our format string
-    if (rFormatString[nPos] == '\"') {
+    if (rFormatString[nPos] == '\"')
+    {
        // TODO: deal with escaped strings? (Does that exist in these?)
         while (rFormatString[--nPos] != '\"') {
             if (nPos == 0) {
                 // TODO: plug into our error reporting here to return bad escaping?
-                return "";
+                return OUString("");
             }
         }
-    } else { // otherwise we have no units for this cell
-        return "";
+    }
+    else
+    { // otherwise we have no units for this cell
+        return OUString("");
     }
 
     // Ensure that the parentheses are NOT included in our unit string.
@@ -364,7 +368,7 @@ HeaderUnitDescriptor UnitsImpl::findUnitInStandardHeader(const OUString& rsHeade
         }
     }
 
-    return { false, UtUnit(), boost::optional< ScAddress >(), "", -1 };
+    return { false, UtUnit(), boost::optional< ScAddress >(), OUString(""), -1 };
 }
 
 HeaderUnitDescriptor UnitsImpl::findFreestandingUnitInHeader(const OUString& rsHeader) {
@@ -427,7 +431,7 @@ HeaderUnitDescriptor UnitsImpl::findFreestandingUnitInHeader(const OUString& rsH
         return { true, aUnit, boost::optional< ScAddress >(), sUnitString, nStartPos };
     }
 
-    return { false, UtUnit(), boost::optional< ScAddress >(), "", -1 };
+    return { false, UtUnit(), boost::optional< ScAddress >(), OUString(""), -1 };
 }
 
 HeaderUnitDescriptor UnitsImpl::extractUnitFromHeaderString(const OUString& rsHeader) {
@@ -519,7 +523,7 @@ HeaderUnitDescriptor UnitsImpl::findHeaderUnitForCell(const ScAddress& rCellAddr
         }
     }
 
-    return { false, UtUnit(), boost::optional< ScAddress >(), "", -1 };
+    return { false, UtUnit(), boost::optional< ScAddress >(), OUString(""), -1 };
 }
 
 FormulaStatus UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rFormulaAddress, ScDocument* pDoc) {
@@ -732,7 +736,7 @@ bool UnitsImpl::convertCellUnitsForColumnRange(const ScRange& rRange,
     assert(rRange.aStart.Tab() == rRange.aEnd.Tab());
     assert(rOutputUnit.getInputString());
 
-    HeaderUnitDescriptor aHeader = { false, UtUnit(), boost::optional< ScAddress >(), "", -1 };
+    HeaderUnitDescriptor aHeader = { false, UtUnit(), boost::optional< ScAddress >(), OUString(""), -1 };
 
     SCCOL nCol = rRange.aStart.Col();
     SCROW nStartRow = rRange.aStart.Row();
diff --git a/sc/source/core/units/util.cxx b/sc/source/core/units/util.cxx
index b536e99..a9f01ec 100644
--- a/sc/source/core/units/util.cxx
+++ b/sc/source/core/units/util.cxx
@@ -14,40 +14,42 @@
 namespace sc {
 namespace units {
 
-OUString getUTStatus() {
-    switch(ut_get_status()) {
+OUString getUTStatus()
+{
+    switch(ut_get_status())
+    {
     case UT_SUCCESS:
-        return "UT_SUCCESS: successful!";
+        return OUString("UT_SUCCESS: successful!");
     case UT_BAD_ARG:
-        return "UT_BAD_ARG: invalid argument";
+        return OUString("UT_BAD_ARG: invalid argument");
     case UT_EXISTS:
-        return "UT_EXISTS: unit/prefix/identifier already exists";
+        return OUString("UT_EXISTS: unit/prefix/identifier already exists");
     case UT_NO_UNIT:
-        return "UT_NO_UNIT: no such unit exists";
+        return OUString("UT_NO_UNIT: no such unit exists");
     case UT_OS:
-        return "UT_OS: operating system error (check errno?)";
+        return OUString("UT_OS: operating system error (check errno?)");
     case UT_NOT_SAME_SYSTEM:
-        return "UT_NOT_SAME_SYSTEM: units not in same unit system";
+        return OUString("UT_NOT_SAME_SYSTEM: units not in same unit system");
     case UT_MEANINGLESS:
-        return "UT_MEANINGLESS: operation is meaningless";
+        return OUString("UT_MEANINGLESS: operation is meaningless");
     case UT_NO_SECOND:
-        return "UT_NO_SECOND: no unit named second";
+        return OUString("UT_NO_SECOND: no unit named second");
     case UT_VISIT_ERROR:
-        return "UT_VISIT_ERROR";
+        return OUString("UT_VISIT_ERROR");
     case UT_CANT_FORMAT:
-        return "UT_CANT_FORMAT";
+        return OUString("UT_CANT_FORMAT");
     case UT_SYNTAX:
-        return "UT_SYNTAX: syntax error in unit string";
+        return OUString("UT_SYNTAX: syntax error in unit string");
     case UT_UNKNOWN:
-        return "UT_UNKNOWN: unknown unit encountered";
+        return OUString("UT_UNKNOWN: unknown unit encountered");
     case UT_OPEN_ARG:
-        return "UT_OPEN_ARG: can't open specified unit database (arg)";
+        return OUString("UT_OPEN_ARG: can't open specified unit database (arg)");
     case UT_OPEN_ENV:
-        return "UT_OPEN_ENV: can't open specified unit databse (env)";
+        return OUString("UT_OPEN_ENV: can't open specified unit databse (env)");
     case UT_OPEN_DEFAULT:
-        return "UT_OPEN_DEFAULT: can't open default unit database";
+        return OUString("UT_OPEN_DEFAULT: can't open default unit database");
     default:
-        return "other (unspecified) error encountered";
+        return OUString("other (unspecified) error encountered");
     }
 }
 
diff --git a/sc/source/core/units/utunit.cxx b/sc/source/core/units/utunit.cxx
index 63e7e73..93c9c56 100644
--- a/sc/source/core/units/utunit.cxx
+++ b/sc/source/core/units/utunit.cxx
@@ -13,7 +13,8 @@
 
 using namespace sc::units;
 
-bool UtUnit::createUnit(const OUString& rUnitString, UtUnit& rUnitOut, const boost::shared_ptr< ut_system >& pUTSystem) {
+bool UtUnit::createUnit(const OUString& rUnitString, UtUnit& rUnitOut, const boost::shared_ptr< ut_system >& pUTSystem)
+{
     // ut_parse requires the string to be trimmed of whitespace, it's
     // simplest just to do this during conversion:
     OString sUnitStringUTF8 = OUStringToOString(rUnitString.trim(), RTL_TEXTENCODING_UTF8);
@@ -21,23 +22,28 @@ bool UtUnit::createUnit(const OUString& rUnitString, UtUnit& rUnitOut, const boo
     UtUnit pParsedUnit(ut_parse(pUTSystem.get(), sUnitStringUTF8.getStr(), UT_UTF8),
                        rUnitString);
 
-    if (pParsedUnit.isValid()) {
+    if (pParsedUnit.isValid())
+    {
         rUnitOut = pParsedUnit;
         return true;
-    } else {
+    }
+    else
+    {
         SAL_INFO("sc.units", "error encountered parsing unit \"" << rUnitString << "\": " << getUTStatus());
         return false;
     }
 }
 
 
-OUString UtUnit::getString() const {
+OUString UtUnit::getString() const
+{
     char aBuf[200];
     int nChars = ut_format(mpUnit.get(), aBuf, 200, UT_UTF8);
-    if (nChars == -1) {
+    if (nChars == -1)
+    {
         SAL_INFO("sc.units", "couldn't format unit: " << getUTStatus());
         // Placeholder for unformattable strings.
-        return "?";
+        return OUString("?");
     }
 
     // If the output doesn't fit in the buffer, ut_format doesn't write
commit afebca3e1530a17bfd40345b31f9bf59dd72c916
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Fri Jun 5 10:33:08 2015 +0100

    WIP: udunits2 build on windows
    
    It now builds, but only produces a static library. libtool (which
    udunits2 uses for building) doesn't like the inclusion of expat
    as a static library and refuses to build a dll - I still need
    to investigate more.
    
    Change-Id: Id4ef089fa9ecbf5cac109bf164b3b3278ba74912

diff --git a/external/udunits2/ExternalPackage_udunits2.mk b/external/udunits2/ExternalPackage_udunits2.mk
index 3ac5920..b3d0261 100644
--- a/external/udunits2/ExternalPackage_udunits2.mk
+++ b/external/udunits2/ExternalPackage_udunits2.mk
@@ -12,7 +12,7 @@ $(eval $(call gb_ExternalPackage_ExternalPackage,udunits2,udunits2))
 $(eval $(call gb_ExternalPackage_use_external_project,udunits2,udunits2))
 
 ifeq ($(OS)-$(COM),WNT-MSC)
-$(eval $(call gb_ExternalPackage_add_file,udunits2,$(LIBO_LIB_FOLDER)/iudunits2.dll,lib/.libs/iudunits2.dll))
+$(eval $(call gb_ExternalPackage_add_file,udunits2,$(LIBO_LIB_FOLDER)/iudunits2.lib,lib/.libs/libudunits2.lib))
 else ifeq ($(OS),MACOSX)
 $(eval $(call gb_ExternalPackage_add_file,udunits2,$(LIBO_LIB_FOLDER)/libudunits2.0.dylib,lib/.libs/libudunits2.0.dylib))
 else
diff --git a/external/udunits2/ExternalProject_udunits2.mk b/external/udunits2/ExternalProject_udunits2.mk
index ba6479e..83dd30b 100644
--- a/external/udunits2/ExternalProject_udunits2.mk
+++ b/external/udunits2/ExternalProject_udunits2.mk
@@ -13,6 +13,10 @@ $(eval $(call gb_ExternalProject_use_autoconf,udunits2,configure))
 
 $(eval $(call gb_ExternalProject_use_autoconf,udunits2,build))
 
+$(eval $(call gb_ExternalProject_use_externals,udunits2,\
+	expat \
+))
+
 $(eval $(call gb_ExternalProject_register_targets,udunits2,\
 	configure \
 	build \
@@ -28,8 +32,13 @@ $(call gb_ExternalProject_get_state_target,udunits2,build) : $(call gb_ExternalP
 
 $(call gb_ExternalProject_get_state_target,udunits2,configure) :
 	$(call gb_ExternalProject_run,configure,\
-		MAKE=$(MAKE) ./configure \
+		MAKE=$(MAKE) \
+			CFLAGS="$(if $(SYSTEM_EXPAT),,-I$(call gb_UnpackedTarball_get_dir,expat)/lib)" \
+			LDFLAGS="$(if $(SYSTEM_EXPAT),,-L$(gb_StaticLibrary_WORKDIR))" \
+			./configure \
 			$(if $(ENABLE_DEBUG),--enable-debug) \
+			$(ifeq ($(OS),WNT) --enable-shared) \
+			--enable-shared \
 			--build=$(if $(filter WNT,$(OS)),i686-pc-cygwin,$(BUILD_PLATFORM)) \
 	)
 
diff --git a/external/udunits2/UnpackedTarball_udunits2.mk b/external/udunits2/UnpackedTarball_udunits2.mk
index 820472e..0d68808 100644
--- a/external/udunits2/UnpackedTarball_udunits2.mk
+++ b/external/udunits2/UnpackedTarball_udunits2.mk
@@ -17,4 +17,10 @@ $(eval $(call gb_UnpackedTarball_add_patches,udunits2,\
 ))
 endif
 
+ifeq ($(OS),WNT)
+$(eval $(call gb_UnpackedTarball_add_patches,udunits2,\
+        external/udunits2/udunits2-windows-cygwin.patch.1 \
+))
+endif
+
 # vim: set noet sw=4 ts=4:
diff --git a/external/udunits2/udunits2-windows-cygwin.patch.1 b/external/udunits2/udunits2-windows-cygwin.patch.1
new file mode 100644
index 0000000..3ed69aa
--- /dev/null
+++ b/external/udunits2/udunits2-windows-cygwin.patch.1
@@ -0,0 +1,200 @@
+diff -ur udunits2.org/configure udunits2/configure
+--- udunits2.org/configure	2015-06-04 07:14:02.996631200 -0700
++++ udunits2/configure	2015-06-04 09:34:57.354053000 -0700
+@@ -4704,12 +4704,12 @@
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dirname" >&5
+ $as_echo "$ac_cv_search_dirname" >&6; }
+ ac_res=$ac_cv_search_dirname
+-if test "$ac_res" != no; then :
+-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+-
+-else
+-  as_fn_error $? "cannot find function dirname" "$LINENO" 5
+-fi
++#if test "$ac_res" != no; then :
++#  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
++#
++#else
++#  as_fn_error $? "cannot find function dirname" "$LINENO" 5
++#fi
+ 
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log10" >&5
+ $as_echo_n "checking for library containing log10... " >&6; }
+@@ -4762,12 +4762,12 @@
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log10" >&5
+ $as_echo "$ac_cv_search_log10" >&6; }
+ ac_res=$ac_cv_search_log10
+-if test "$ac_res" != no; then :
+-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+-
+-else
+-  as_fn_error $? "cannot find function log10" "$LINENO" 5
+-fi
++#if test "$ac_res" != no; then :
++#  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
++#
++#else
++#  as_fn_error $? "cannot find function log10" "$LINENO" 5
++#fi
+ 
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing XML_StopParser" >&5
+ $as_echo_n "checking for library containing XML_StopParser... " >&6; }
+@@ -8463,7 +8463,7 @@
+         enable_dlopen=no
+ 
+ 
+-  enable_win32_dll=no
++  enable_win32_dll=yes
+ 
+ 
+             # Check whether --enable-shared was given.
+diff -ur udunits2.org/lib/idToUnitMap.c udunits2/lib/idToUnitMap.c
+--- udunits2.org/lib/idToUnitMap.c	2015-06-04 07:14:03.043506200 -0700
++++ udunits2/lib/idToUnitMap.c	2015-06-04 09:34:57.385303000 -0700
+@@ -16,11 +16,11 @@
+ #endif
+ 
+ #include <assert.h>
+-#ifdef _MSC_VER
+-#include "tsearch.h"
+-#else
++//#ifdef _MSC_VER
++//#include "tsearch.h"
++//#else
+ #include <search.h>
+-#endif
++//#endif
+ 
+ #include <stdlib.h>
+ 
+diff -ur udunits2.org/lib/Makefile.in udunits2/lib/Makefile.in
+--- udunits2.org/lib/Makefile.in	2015-06-04 07:14:03.059131200 -0700
++++ udunits2/lib/Makefile.in	2015-06-04 09:37:49.791553000 -0700
+@@ -349,7 +349,7 @@
+ #pdf_DATA = udunits2lib.pdf
+ AM_MAKEINFOFLAGS = -I $(top_srcdir)
+ AM_MAKEINFOHTMLFLAGS = --no-split -I $(top_srcdir)
+-libudunits2_la_LDFLAGS = -version-number 0:1:0
++libudunits2_la_LDFLAGS = -version-number 0:1:0 -no-undefined -win32-dll
+ lex_prefix = ut
+ LFLAGS = -d -P$(lex_prefix)
+ include_HEADERS = udunits2.h converter.h $(am__append_2)
+diff -ur udunits2.org/lib/prefix.c udunits2/lib/prefix.c
+--- udunits2.org/lib/prefix.c	2015-06-04 07:14:03.059131200 -0700
++++ udunits2/lib/prefix.c	2015-06-04 09:34:57.385303000 -0700
+@@ -17,11 +17,11 @@
+ 
+ #include <ctype.h>
+ #include <errno.h>
+-#ifdef _MSC_VER
+-#include "tsearch.h"
+-#else
++//#ifdef _MSC_VER
++//#include "tsearch.h"
++//#else
+ #include <search.h>
+-#endif
++//#endif
+ #include <stdlib.h>
+ 
+ #include <string.h>
+diff -ur udunits2.org/lib/scanner.c udunits2/lib/scanner.c
+--- udunits2.org/lib/scanner.c	2015-06-04 07:14:03.059131200 -0700
++++ udunits2/lib/scanner.c	2015-06-04 09:34:57.385303000 -0700
+@@ -1047,7 +1047,7 @@
+  * The user has a chance to override it with an option.
+  */
+ /* %if-c-only */
+-#include <unistd.h>
++//#include <unistd.h>
+ /* %endif */
+ /* %if-c++-only */
+ /* %endif */
+diff -ur udunits2.org/lib/systemMap.c udunits2/lib/systemMap.c
+--- udunits2.org/lib/systemMap.c	2015-06-04 07:14:03.152881200 -0700
++++ udunits2/lib/systemMap.c	2015-06-04 09:34:57.385303000 -0700
+@@ -17,11 +17,11 @@
+ #   define _XOPEN_SOURCE 500
+ #endif
+ 
+-#ifdef _MSC_VER
+-#include "tsearch.h"
+-#else
++//#ifdef _MSC_VER
++//#include "tsearch.h"
++//#else
+ #include <search.h>
+-#endif
++//#endif
+ #include <stdlib.h>
+ 
+ #include "systemMap.h"
+diff -ur udunits2.org/lib/udunits.h udunits2/lib/udunits.h
+--- udunits2.org/lib/udunits.h	2015-06-04 07:14:03.043506200 -0700
++++ udunits2/lib/udunits.h	2015-06-04 09:34:57.385303000 -0700
+@@ -13,7 +13,7 @@
+ #define UT_UNITS_H_INCLUDED
+ 
+ #ifdef _MSC_VER
+-<io.h>
++#include <io.h>
+ #define snprintf _snprintf
+ #define close _close
+ #define open _open
+diff -ur udunits2.org/lib/udunits-1.c udunits2/lib/udunits-1.c
+--- udunits2.org/lib/udunits-1.c	2015-06-04 07:14:03.059131200 -0700
++++ udunits2/lib/udunits-1.c	2015-06-04 09:34:57.400928000 -0700
+@@ -7,11 +7,11 @@
+  */
+ 
+ #include <errno.h>
+-#ifdef _MSC_VER
+-#include "tsearch.h"
+-#else
++//#ifdef _MSC_VER
++//#include "tsearch.h"
++//#else
+ #include <search.h>
+-#endif
++//#endif
+ #include <stddef.h>
+ #include <stdlib.h>
+ #include <string.h>
+diff -ur udunits2.org/lib/unitcore.c udunits2/lib/unitcore.c
+--- udunits2.org/lib/unitcore.c	2015-06-04 07:14:03.059131200 -0700
++++ udunits2/lib/unitcore.c	2015-06-04 09:34:57.400928000 -0700
+@@ -56,11 +56,11 @@
+ #include <limits.h>
+ #include <math.h>
+ 
+-#ifdef _MSC_VER
+-#include "tsearch.h"
+-#else
++//#ifdef _MSC_VER
++//#include "tsearch.h"
++//#else
+ #include <search.h>
+-#endif
++//#endif
+ 
+ #include <stddef.h>
+ #include <stdio.h>
+diff -ur udunits2.org/lib/unitToIdMap.c udunits2/lib/unitToIdMap.c
+--- udunits2.org/lib/unitToIdMap.c	2015-06-04 07:14:03.059131200 -0700
++++ udunits2/lib/unitToIdMap.c	2015-06-04 09:34:57.400928000 -0700
+@@ -18,11 +18,11 @@
+ #include <assert.h>
+ #include <errno.h>
+ 
+-#ifdef _MSC_VER
+-#include "tsearch.h"
+-#else
++//#ifdef _MSC_VER
++//#include "tsearch.h"
++//#else
+ #include <search.h>
+-#endif
++//#endif
+ 
+ #include <stdlib.h>
+ 
commit 9374e983c6fb5b341cb19c4ef904fc2473c56bf5
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Thu Jun 4 09:14:24 2015 +0100

    Upgrade to udunits 2.2.19
    
    This has some fixes that should help the windows build
    
    Change-Id: I71b17ee74d5d3a9b7c0eed4805fc0136b8db0607

diff --git a/download.lst b/download.lst
index 5b1dd43..825c2a0 100644
--- a/download.lst
+++ b/download.lst
@@ -135,8 +135,8 @@ export SERF_MD5SUM := 4f8e76c9c6567aee1d66aba49f76a58b
 export SERF_TARBALL := serf-1.2.1.tar.bz2
 export SWING_TARBALL := 35c94d2df8893241173de1d16b6034c0-swingExSrc.zip
 export UCPP_TARBALL := 0168229624cfac409e766913506961a8-ucpp-1.3.2.tar.gz
-export UDUNITS2_MD5SUM := a2492adfbd9ae2f05a331673a2067cab
-export UDUNITS2_TARBALL := udunits-2.2.17.tar.gz
+export UDUNITS2_MD5SUM := 12aeae488567622feb51458d62cf294c
+export UDUNITS2_TARBALL := udunits-2.2.19.tar.gz
 export VIGRA_TARBALL := d62650a6f908e85643e557a236ea989c-vigra1.6.0.tar.gz
 export VISIO_MD5SUM := 617f800ab7639fd76c062ab74896318e
 export VISIO_TARBALL := libvisio-0.1.3.tar.bz2
commit 5c342b7db1e13896f9ca022513e7e596e9b49ef5
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Wed Jun 3 21:28:24 2015 +0100

    Fix udunits2 install_name on OSX
    
    Change-Id: I048d23d647a6d6f38efddc11f7d3bde3b583e752

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 1510ee5..c61be00 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -177,7 +177,7 @@ $(call gb_LinkTarget_add_libs,$(1),\
 )
 else
 $(call gb_LinkTarget_add_libs,$(1),\
-	-L$(call gb_UnpackedTarball_get_dir,udunits2)/lib -ludunits2 \
+	-L$(call gb_UnpackedTarball_get_dir,udunits2)/lib/.libs -ludunits2 \
 )
 endif
 
diff --git a/external/udunits2/UnpackedTarball_udunits2.mk b/external/udunits2/UnpackedTarball_udunits2.mk
index db096ca..820472e 100644
--- a/external/udunits2/UnpackedTarball_udunits2.mk
+++ b/external/udunits2/UnpackedTarball_udunits2.mk
@@ -11,4 +11,10 @@ $(eval $(call gb_UnpackedTarball_UnpackedTarball,udunits2))
 
 $(eval $(call gb_UnpackedTarball_set_tarball,udunits2,$(UDUNITS2_TARBALL)))
 
+ifeq ($(OS),MACOSX)
+$(eval $(call gb_UnpackedTarball_add_patches,udunits2,\
+	external/udunits2/udunits2-macosx.patch.1 \
+))
+endif
+
 # vim: set noet sw=4 ts=4:
diff --git a/external/udunits2/udunits2-macosx.patch.1 b/external/udunits2/udunits2-macosx.patch.1
new file mode 100644
index 0000000..0b6fb4e
--- /dev/null
+++ b/external/udunits2/udunits2-macosx.patch.1
@@ -0,0 +1,27 @@
+diff -ur udunits2.org/configure udunits2/configure
+--- udunits2.org/configure	2015-06-03 21:24:12.440541277 +0100
++++ udunits2/configure	2015-06-03 21:25:59.873829068 +0100
+@@ -10254,9 +10254,9 @@
+   esac
+   if test "$_lt_dar_can_shared" = "yes"; then
+     output_verbose_link_cmd=func_echo_all
+-    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
++    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name @__________________________________________________OOO/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+     module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+-    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
++    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name @__________________________________________________OOO/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+     module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ 
+   else
+@@ -14000,9 +14000,9 @@
+   esac
+   if test "$_lt_dar_can_shared" = "yes"; then
+     output_verbose_link_cmd=func_echo_all
+-    archive_cmds_FC="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
++    archive_cmds_FC="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name @__________________________________________________OOO/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+     module_cmds_FC="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+-    archive_expsym_cmds_FC="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
++    archive_expsym_cmds_FC="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name @__________________________________________________OOO/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+     module_expsym_cmds_FC="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ 
+   else
commit 3c36fd800c06b163ab2862b6067c751b7b9dd1ac
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Wed Jun 3 15:58:29 2015 +0100

    Don't assert on unsupported opcode, return unknown instead
    
    We should eventually support all opcodes, but crashing* isn't
    really the correct response if not.
    
    *or continuing with completely wrong behvaiour in non-debug builds.
    
    Change-Id: I22d7746f4e809bdc3da62b8b6f741216504b3f22

diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index c440df6..66f5019 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -162,7 +162,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
             break;
         default:
             SAL_INFO("sc.units", "unit verification not supported for opcode: " << nOpCode);
-            assert(false);
+            return { FormulaStatus::UNKNOWN, boost::none };
         }
     } else if (nOpCode >= SC_OPCODE_START_2_PAR &&
                nOpCode < SC_OPCODE_STOP_2_PAR) {
commit 09556129755e2aebee2ebf656e9e6689eb562118
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Tue Jun 2 13:53:55 2015 +0100

    Enable --with-system-udunits2
    
    We also have to move udunits2 headers to match the default system
    installation location of ududnits2/udunits2.h (whereas udunits2 bundled
    build puts the headers in lib/udunits2.h by default).
    
    Change-Id: I1d314f6b3e016f90cfb8e19a143bb77ae98e7734

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 933d281..1510ee5 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -151,18 +151,21 @@ ifeq ($(ENABLE_CALC_UNITVERIFICATION),TRUE)
 
 ifneq ($(SYSTEM_UDUNITS2),)
 
-define gb_LinkTarget__use_libudunits2
+define gb_LinkTarget__use_udunits2
+$(call gb_LinkTarget_add_defs,$(1),\
+	-DSYSTEM_UDUNITS2 \
+)
 $(call gb_LinkTarget_set_include,$(1),\
 	$(UDUNITS2_CFLAGS) \
 	$$(INCLUDE) \
 )
-$(call gb_LinkTarget_add_libs,$(1),$(UDUNIT2_LIBS))
+$(call gb_LinkTarget_add_libs,$(1),$(UDUNITS2_LIBS))
 
 endef
 
 else # !SYSTEM_UDUNITS2
 
-define gb_LinkTarget__use_libudunits2
+define gb_LinkTarget__use_udunits2
 $(call gb_LinkTarget_use_package,$(1),udunits2)
 $(call gb_LinkTarget_set_include,$(1),\
 	$$(INCLUDE) \
@@ -184,7 +187,7 @@ endif # !SYSTEM_UDUNITS2
 
 else # !ENABLE_CALC_UNITVERIFICATION
 
-gb_LinkTarget__use_libudunits2 :=
+gb_LinkTarget__use_udunits2 :=
 
 endif # ENABLE_CALC_UNITVERIFICATION
 
diff --git a/config_host.mk.in b/config_host.mk.in
index 417bfee..fc5cc87 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -179,6 +179,9 @@ export ENABLE_TDE=@ENABLE_TDE@
 export ENABLE_TDEAB=@ENABLE_TDEAB@
 export ENABLE_TELEPATHY=@ENABLE_TELEPATHY@
 export ENABLE_CALC_UNITVERIFICATION=@ENABLE_CALC_UNITVERIFICATION@
+export SYSTEM_UDUNITS2=@SYSTEM_UDUNITS2@
+export UDUNITS2_CFLAGS=@UDUNITS2_CFLAGS@
+export UDUNITS2_LIBS=@UDUNITS2_LIBS@
 export ENABLE_VALGRIND=@ENABLE_VALGRIND@
 export ENABLE_VLC=@ENABLE_VLC@
 export ENABLE_WERROR=@ENABLE_WERROR@
diff --git a/configure.ac b/configure.ac
index b02577e..115e85d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1744,7 +1744,7 @@ AC_ARG_WITH(system-firebird,
 
 AC_ARG_WITH(system-udunits2,
     AS_HELP_STRING([--with-system-udunits2],
-        [Use udunits libraries already on system, for building calc unit-verification it.]),,
+        [Use udunits libraries already on system, for building calc unit-verification with it.]),,
     [with_system_udunits2="$with_system_libs"])
 
 AC_ARG_WITH(system-hsqldb,
@@ -8692,48 +8692,26 @@ if test "x$enable_calc_unitverification" = "xyes"; then
     if test "$with_system_udunits2" = "yes"; then
         AC_MSG_RESULT([external])
         SYSTEM_UDUNITS2=TRUE
-        AC_PATH_PROG(FIREBIRDCONFIG, [fb_config])
-        if test -z "$FIREBIRDCONFIG"; then
-            AC_MSG_NOTICE([No fb_config -- using pkg-config])
-            PKG_CHECK_MODULES(FIREBIRD, fbembed)
-            FIREBIRD_VERSION=`pkg-config --modversion fbembed`
-        else
-            AC_MSG_NOTICE([fb_config found])
-            FIREBIRD_VERSION=`$FIREBIRDCONFIG --version`
-            AC_MSG_CHECKING([for Firebird Client library])
-            FIREBIRD_CFLAGS=`$FIREBIRDCONFIG --cflags`
-            FIREBIRD_LIBS=`$FIREBIRDCONFIG --embedlibs`
-        fi
-        AC_MSG_RESULT([includes `$FIREBIRD_CFLAGS', libraries `$FIREBIRD_LIBS'])
-        AC_MSG_CHECKING([Firebird version])
-        if test -n "${FIREBIRD_VERSION}"; then
-            FIREBIRD_MAJOR=`echo $FIREBIRD_VERSION | cut -d"." -f1`
-            FIREBIRD_MINOR=`echo $FIREBIRD_VERSION | cut -d"." -f2`
-            if test "$FIREBIRD_MAJOR" -eq "2" -a "$FIREBIRD_MINOR" -eq "5"; then
-                AC_MSG_RESULT([OK])
-            else
-                AC_MSG_ERROR([Ensure firebird 2.5.x is installed])
-            fi
-        else
-            __save_CFLAGS="${CFLAGS}"
-            CFLAGS="${CFLAGS} ${FIREBIRD_CFLAGS}"
-            AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <ibase.h>
-#if defined(FB_API_VER) && FB_API_VER == 25
-#else
-#error "Wrong Firebird API version"

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list