[Libreoffice-commits] core.git: Branch 'feature/unitver' - 2152 commits - accessibility/inc accessibility/source android/Bootstrap android/source avmedia/inc avmedia/source basctl/inc basctl/source basctl/uiconfig basebmp/source basegfx/inc basegfx/source basic/inc basic/source bin/distro-install-file-lists bin/find-german-comments bin/findunusedcode bin/gbuild-to-ide bin/module-deps.pl bin/run bin/update_pch_bisect bridges/inc bridges/source canvas/Library_canvasfactory.mk canvas/Library_gdipluscanvas.mk canvas/source canvas/workben chart2/CppunitTest_chart2_common_functors.mk chart2/inc chart2/Library_chartcontroller.mk chart2/Module_chart2.mk chart2/qa chart2/source chart2/uiconfig cli_ure/source codemaker/source comphelper/inc comphelper/Library_comphelper.mk comphelper/source compilerplugins/clang compilerplugins/Makefile-clang.mk config_host/config_python.h.in config_host/config_vclplug.h.in config_host.mk.in configmgr/Library_configmgr.mk configmgr/source configure.ac connectivity/Configur ation_kab.mk connectivity/inc connectivity/Library_kab1.mk connectivity/Library_kabdrv1.mk connectivity/Module_connectivity.mk connectivity/registry connectivity/source cppcanvas/inc cppcanvas/qa cppcanvas/source cppuhelper/inc cppuhelper/source cppu/source cui/inc cui/Library_cui.mk cui/source cui/uiconfig dbaccess/inc dbaccess/qa dbaccess/source desktop/CppunitTest_desktop_lib.mk desktop/inc desktop/Library_sofficeapp.mk desktop/Module_desktop.mk desktop/Pagein_common.mk desktop/qa desktop/source desktop/test desktop/uiconfig dictionaries distro-configs/Jenkins distro-configs/LibreOfficeAndroidAarch64.conf distro-configs/LibreOfficeAndroid.conf distro-configs/LibreOfficeAndroidX86.conf distro-configs/LibreOfficeCoverity.conf distro-configs/LibreOfficeLinux.conf distro-configs/LibreOfficeOpenBSD.conf distro-configs/OxygenOfficeLinux.conf download.lst drawinglayer/source dtrans/Library_mcnttype.mk dtrans/source dtrans/test editeng/inc editeng/qa editeng/source embeddedobj/source emb edserv/source extensions/source external/apr external/boost external/coinmp external/cppunit external/ct2n external/freetype external/glew external/glm external/graphite external/harfbuzz external/hunspell external/icu external/jpeg-turbo external/lcms2 external/libabw external/libcdr external/libebook external/libeot external/libetonyek external/libfreehand external/libgltf external/liblangtag external/libmspub external/libmwaw external/libodfgen external/liborcus external/libpagemaker external/librevenge external/libvisio external/libwpd external/libwpg external/libwps external/libxmlsec external/Module_external.mk external/neon external/nss external/poppler external/python3 external/redland external/udunits2 extras/CustomTarget_autocorr.mk extras/CustomTarget_autotextshare.mk extras/CustomTarget_autotextuser.mk extras/source filter/Configuration_filter.mk filter/CppunitTest_filter_msfilter.mk filter/CppunitTest_filter_utils.mk filter/Module_filter.mk filter/qa filter/source forms /inc forms/source formula/source fpicker/source fpicker/test fpicker/uiconfig framework/inc framework/source .git-hooks/README helpcompiler/inc helpcontent2 hwpfilter/inc hwpfilter/Library_hwp.mk hwpfilter/source i18nlangtag/source i18npool/inc i18npool/Library_localedata_en.mk i18npool/qa i18npool/source i18nutil/Library_i18nutil.mk i18nutil/source icon-themes/breeze icon-themes/sifr idlc/source idl/inc idl/README idl/source include/avmedia include/basebmp include/basegfx include/basic include/canvas include/clew include/comphelper include/connectivity include/cppcanvas include/dbaccess include/drawinglayer include/editeng include/filter include/framework include/i18nlangtag include/i18nutil include/LibreOfficeKit include/linguistic include/o3tl include/oox include/opencl include/osl include/postmac.h include/postwin.h include/premac.h include/prewin.h include/rtl include/sal include/salhelper include/sfx2 include/svl include/svtools include/svx include/systools include/toolkit inc lude/tools include/ucbhelper include/unotools include/vcl include/xmloff instsetoo_native/CustomTarget_install.mk instsetoo_native/CustomTarget_setup.mk instsetoo_native/inc_openoffice io/qa io/source io/test javaunohelper/source jvmfwk/plugins jvmfwk/source l10ntools/inc l10ntools/source librelogo/source libreofficekit/qa libreofficekit/source lingucomponent/source linguistic/inc linguistic/source linguistic/workben lotuswordpro/inc lotuswordpro/source m4/introspection.m4 Makefile.fetch Makefile.in mysqlc/source o3tl/qa o3tl/README odk/CustomTarget_doxygen.mk offapi/com offapi/type_reference offapi/UnoApi_offapi.mk officecfg/Configuration_officecfg.mk officecfg/registry onlineupdate/source oox/CppunitTest_oox_vba_compression.mk oox/inc oox/Library_oox.mk oox/Module_oox.mk oox/qa oox/source opencl/source package/inc package/source postprocess/CustomTarget_registry.mk postprocess/Rdb_services.mk postprocess/signing pyuno/CustomTarget_python_shell.mk pyuno/CustomTarget_pyuno_pythonloa der_ini.mk pyuno/Executable_python.mk pyuno/source pyuno/zipcore readlicense_oo/license registry/source remotebridges/source reportdesign/inc reportdesign/source RepositoryExternal.mk Repository.mk rsc/inc rsc/source sal/cppunittester sal/CppunitTest_sal_rtl_strings.mk salhelper/qa sal/Library_uwinapi.mk sal/osl sal/qa sal/systools sal/textenc sal/workben sax/qa sax/source sax/test scaddins/source sc/AllLangResTarget_sc.mk 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/InstallModule_gnome.mk scp2/InstallModule_ooo.mk scp2/InstallScript_setup_osl.mk scp2/Module_scp2.mk scp2/source sc/qa scripting/source sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk sc/workben sdext/inc sdext/Library_pdfimport.mk sdext/source sd/inc sd/qa sd/res sd/sdi sd/source sd/uiconfig sd/workben setup_native/Library_instooofiltmsi.mk setup_native/Library_qslnkmsi.mk setup_native/Library_reg4allmsdoc.mk setup_native/Library _regactivex.mk setup_native/Library_sdqsmsi.mk setup_native/Library_sellangmsi.mk setup_native/Library_shlxtmsi.mk setup_native/Library_sn_tools.mk sfx2/inc sfx2/PythonTest_sfx2_python.mk sfx2/qa sfx2/source sfx2/uiconfig shell/Library_kdebe.mk shell/Module_shell.mk shell/Package_scripts_kde.mk shell/source slideshow/CppunitTest_slideshow.mk slideshow/Executable_demoshow.mk slideshow/inc slideshow/Library_OGLTrans.mk slideshow/Library_slideshow.mk slideshow/qa slideshow/source slideshow/test smoketest/smoketest.cxx solenv/bin solenv/gbuild sot/inc sot/source sot/workben starmath/inc starmath/qa starmath/source stoc/source stoc/test store/source svgio/inc svgio/source svl/inc svl/qa svl/source svl/unx svtools/inc svtools/Library_svt.mk svtools/qa svtools/source svtools/uiconfig svx/inc svx/Library_svxcore.mk svx/source svx/uiconfig sw/CppunitTest_sw_odfexport.mk sw/inc sw/qa sw/sdi sw/source sw/uiconfig sysui/CustomTarget_share.mk sysui/desktop test/source testtools/source toolkit/so urce tools/inc tools/qa tools/source translations ucbhelper/Library_ucbhelper.mk ucbhelper/source ucb/Library_ucpgvfs1.mk ucb/Module_ucb.mk ucb/source unodevtools/source unoidl/source unotest/source unotools/inc unotools/source unoxml/inc unoxml/qa unoxml/source unusedcode.easy uui/inc uui/source uui/uiconfig vbahelper/inc vbahelper/source vcl/CppunitTest_vcl_bitmap_test.mk vcl/CustomTarget_kde_moc.mk vcl/Executable_fftester.mk vcl/Executable_kdefilepicker.mk vcl/Executable_vcldemo.mk vcl/generic vcl/headless vcl/inc vcl/Library_vcl.mk vcl/Library_vclplug_kde.mk vcl/Module_vcl.mk vcl/opengl vcl/osx vcl/Package_opengl.mk vcl/qa vcl/quartz vcl/README.lifecycle vcl/README.vars vcl/source vcl/unx vcl/win vcl/workben winaccessibility/inc winaccessibility/Library_winaccessibility.mk winaccessibility/source wizards/com wizards/source writerfilter/source writerperfect/inc writerperfect/qa writerperfect/source xmlhelp/source xmloff/inc xmloff/source xmlscript/inc xmlscript/source xmlscript/t est xmlsecurity/inc xmlsecurity/source

Andrzej Hunt andrzej at ahunt.org
Tue Sep 22 09:13:40 PDT 2015


Rebased ref, commits from common ancestor:
commit c322176e067d97e47138949d3df3e0c1e721a658
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 3377965..8bcbd27 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 d1ce472..d3db634 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 2610d5fc8d15e08876a88d4eb3edbf117b6870f4
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 9f6676e..d1ce472 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 8d5cb129dabce76d322c7da60ec65050173c0167
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 2256a42..9f6676e 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 a9f68136761e6749c6a8d50565e91d8145956dac
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 5c5c0c9..3377965 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 fa8595d..2256a42 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 15fd0a9245d865346aabf21e1ce86aa2382a5cb3
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 fc94b5b6b8ec836538c78145108dce448581cc91
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 5b71b2a..b3ad9f6 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;
 
@@ -50,6 +51,9 @@ public:
     void SetUseEnglishFuncName( bool bVal ) { bUseEnglishFuncName = bVal; }
     bool GetUseEnglishFuncName() const { return bUseEnglishFuncName; }
 
+    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 7bb264b..449ffb6 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 ),
     aFormulaSepArg      ( rCpy.aFormulaSepArg ),
     aFormulaSepArrayRow ( rCpy.aFormulaSepArrayRow ),
     aFormulaSepArrayCol ( rCpy.aFormulaSepArrayCol ),
@@ -51,6 +52,7 @@ ScFormulaOptions::~ScFormulaOptions()
 void ScFormulaOptions::SetDefaults()
 {
     bUseEnglishFuncName = false;
+    bUnitValidat = false;
     eFormulaGrammar     = ::formula::FormulaGrammar::GRAM_NATIVE;
     meOOXMLRecalc = RECALC_ASK;
     meODFRecalc = RECALC_ASK;
@@ -127,8 +129,9 @@ const LocaleDataWrapper& ScFormulaOptions::GetLocaleDataWrapper()
 ScFormulaOptions& ScFormulaOptions::operator=( const ScFormulaOptions& rCpy )
 {
     bUseEnglishFuncName = rCpy.bUseEnglishFuncName;
+    bUnitValidat        = rCpy.bUnitValidat;
     eFormulaGrammar     = rCpy.eFormulaGrammar;
-    aCalcConfig = rCpy.aCalcConfig;
+    aCalcConfig         = rCpy.aCalcConfig;
     aFormulaSepArg      = rCpy.aFormulaSepArg;
     aFormulaSepArrayRow = rCpy.aFormulaSepArrayRow;
     aFormulaSepArrayCol = rCpy.aFormulaSepArrayCol;
@@ -140,8 +143,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
         && aFormulaSepArg      == rOpt.aFormulaSepArg
         && aFormulaSepArrayRow == rOpt.aFormulaSepArrayRow
         && aFormulaSepArrayCol == rOpt.aFormulaSepArrayCol
@@ -185,22 +189,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()
 {
@@ -208,6 +213,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
@@ -236,6 +242,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,
@@ -319,6 +326,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;
@@ -531,6 +545,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 1024c7d..689aed6 100644
--- a/sc/source/ui/inc/tpformula.hxx
+++ b/sc/source/ui/inc/tpformula.hxx
@@ -59,6 +59,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 7201fb8..74eeab4 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");
@@ -88,6 +89,7 @@ void ScTpFormulaOptions::dispose()
 {
     mpLbFormulaSyntax.clear();
     mpCbEnglishFuncName.clear();
+    mpCbUnitValidat.clear();
     mpBtnCustomCalcDefault.clear();
     mpBtnCustomCalcCustom.clear();
     mpBtnCustomCalcDetails.clear();
@@ -245,6 +247,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();
@@ -260,6 +263,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
@@ -287,6 +291,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet)
 
         aOpt.SetFormulaSyntax(eGram);
         aOpt.SetUseEnglishFuncName(bEnglishFuncName);
+        aOpt.SetUnitValidat(bUnitValidat);
         aOpt.SetFormulaSepArg(aSep);
         aOpt.SetFormulaSepArrayCol(aSepArrayCol);
         aOpt.SetFormulaSepArrayRow(aSepArrayRow);
@@ -340,6 +345,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 1b6c697..fa8595d 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 36647fb91bace66f759ad683f0f5d8c42c8d824e
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 e8a40f9a556c009ea2591d210d098fa22d9be1d0
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 1d7973d5c5d5d7438a9ccaf8eb2fcc5d7cb8fca2
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 f5cfef2b6d60045b81715f5c9a8bb9ac2d16198e
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 2481e5f37e2bc7c0fbc1dbd4aa3b70b3edde92bf
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 404e3b95d1c2137651fb163e8bece09bfe998d39
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 9399605339b26110aba4dfe8ad47c81907bd3620
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 e06e9fdd385b1b876fd7d3cb8c261ef6414b6019
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 9f745756163109b307cb5fc6bf85e7177ae39e34
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 ce380c1..d40a0db 100644
--- a/download.lst
+++ b/download.lst
@@ -144,8 +144,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 c63c02552c06e578939dac351950a44d169a6458
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 44ef6f0..68d5436 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 c79f91edd843c3c1cb41a454403b2902f3a7e582
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 fb32e3c965882f070483913d3d1735ecc1b89e7d
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 0535826..44ef6f0 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 2f1f716..88a4a37 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -183,6 +183,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 08216b7..4eb39e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1706,7 +1706,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,
@@ -8706,48 +8706,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"
-#endif]])],AC_MSG_RESULT([OK]),AC_MSG_ERROR([Ensure firebird 2.5.x is installed]))
-            CFLAGS="${__save_CFLAGS}"
+
+        PKG_CHECK_MODULES(UDUNITS2, udunits >= 2.2.1, UDUNITS2_PKGCONFIG=yes, UDUNITS2_PKGCONFIG=no)
+
+        if test "x$UDUNITS2_PKGCONFIG" = "xno"; then
+            AC_CHECK_HEADER(udunits2/udunits2.h, [],
+                [AC_MSG_ERROR(udunits2/ududunits2.h not found. install udunits2)], [])
+            AC_CHECK_LIB([udunits2], [ut_read_xml], [:], [AC_MSG_ERROR(udunits2 lib not found or functional)], [])
         fi
-        ENABLE_FIREBIRD_SDBC="TRUE"
+
+        ENABLE_CALC_UNITVERIFICATION="TRUE"
     else
         AC_MSG_RESULT([internal])
         SYSTEM_UDUNITS2=
         UDUNITS2_CFLAGS="-I${WORKDIR}/UnpackedTarball/udunits2/lib"
-        UDUNITS2_LIBS="-ludunits2"
 
         BUILD_TYPE="$BUILD_TYPE UDUNITS2"
         ENABLE_CALC_UNITVERIFICATION="TRUE"
     fi
+
+    UDUNITS2_LIBS="-ludunits2"
 fi
 AC_SUBST(ENABLE_CALC_UNITVERIFICATION)
 AC_SUBST(SYSTEM_UDUNITS2)
diff --git a/external/udunits2/ExternalProject_udunits2.mk b/external/udunits2/ExternalProject_udunits2.mk
index fd54fc4..ba6479e 100644
--- a/external/udunits2/ExternalProject_udunits2.mk
+++ b/external/udunits2/ExternalProject_udunits2.mk
@@ -20,7 +20,10 @@ $(eval $(call gb_ExternalProject_register_targets,udunits2,\
 
 $(call gb_ExternalProject_get_state_target,udunits2,build) : $(call gb_ExternalProject_get_state_target,udunits2,configure)
 	+$(call gb_ExternalProject_run,build,\
-		cd lib && $(MAKE) libudunits2.la \
+		cd lib && \
+	    $(MAKE) libudunits2.la && \
+		mkdir udunits2 && \
+		cp udunits2.h udunits2/ \
 	)
 
 $(call gb_ExternalProject_get_state_target,udunits2,configure) :
diff --git a/sc/CppunitTest_sc_ucalc.mk b/sc/CppunitTest_sc_ucalc.mk
index 4d35f78..db3ecdf 100644
--- a/sc/CppunitTest_sc_ucalc.mk
+++ b/sc/CppunitTest_sc_ucalc.mk
@@ -35,7 +35,7 @@ $(eval $(call gb_CppunitTest_use_externals,sc_ucalc,\
     icui18n \
     icuuc \
     $(if $(ENABLE_CALC_UNITVERIFICATION), \
-        libudunits2 \
+        udunits2 \
     ) \
 	libxml2 \
 	mdds_headers \
diff --git a/sc/CppunitTest_sc_units.mk b/sc/CppunitTest_sc_units.mk
index 241836b..9af3d7e 100644
--- a/sc/CppunitTest_sc_units.mk
+++ b/sc/CppunitTest_sc_units.mk
@@ -29,7 +29,7 @@ $(eval $(call gb_CppunitTest_use_externals,sc_units,\
     icu_headers \
     icui18n \
     icuuc \
-	libudunits2 \
+	udunits2 \
 	libxml2 \
 	mdds_headers \
 	orcus \
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index ca202f9..44b26b0 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -48,7 +48,7 @@ $(eval $(call gb_Library_use_externals,sc,\
     icuuc \
     libxml2 \
     $(if $(ENABLE_CALC_UNITVERIFICATION), \
-        libudunits2 \
+        udunits2 \
     ) \
     mdds_headers \
 ))
diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index 6332747..c440df6 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -55,7 +55,7 @@ UnitsImpl::UnitsImpl() {
     // System udunits will (/should) be able to find it's unit database
     // itself -- however for bundled udunits we always need to find the
     // correct relative path within our LO installation.
-#ifdef USING_SYSTEM_UDUNITS
+#ifdef SYSTEM_UDUNITS2
     const sal_Char* pPath = 0;
 #else
     OUString sDBURL("$BRAND_BASE_DIR/$BRAND_SHARE_SUBDIR/udunits2/udunits2.xml");
diff --git a/sc/source/core/units/unitsimpl.hxx b/sc/source/core/units/unitsimpl.hxx
index 934bb26..f3e2cb8 100644
--- a/sc/source/core/units/unitsimpl.hxx
+++ b/sc/source/core/units/unitsimpl.hxx
@@ -19,7 +19,7 @@
 #include <osl/mutex.hxx>
 #include <rtl/ustring.hxx>
 
-#include <udunits2.h>
+#include <udunits2/udunits2.h>
 
 #include "rangelst.hxx"
 #include "units.hxx"
diff --git a/sc/source/core/units/util.cxx b/sc/source/core/units/util.cxx
index 2146c43..b536e99 100644
--- a/sc/source/core/units/util.cxx
+++ b/sc/source/core/units/util.cxx
@@ -9,7 +9,7 @@
  */
 #include "util.hxx"
 
-#include <udunits2.h>
+#include <udunits2/udunits2.h>
 
 namespace sc {
 namespace units {
diff --git a/sc/source/core/units/utunit.hxx b/sc/source/core/units/utunit.hxx
index 5d1442a..8508f93 100644
--- a/sc/source/core/units/utunit.hxx
+++ b/sc/source/core/units/utunit.hxx
@@ -15,7 +15,7 @@
 #include <boost/optional.hpp>
 #include <boost/shared_ptr.hpp>
 
-#include <udunits2.h>
+#include <udunits2/udunits2.h>
 
 namespace sc {
 namespace units {
commit a12405ccd18db0aff39fa95e5a496489bc7f2841
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Tue Jun 2 12:34:16 2015 +0100

    Enable udunits2 on OSX
    
    My original guess of library was wrong, other than that no special
    treatment is needed for the OSX build.
    
    Change-Id: I2a697c65a6e272bfa3f8070a85b4bbd8b01b5e23

diff --git a/external/udunits2/ExternalPackage_udunits2.mk b/external/udunits2/ExternalPackage_udunits2.mk
index 4073463..3ac5920 100644
--- a/external/udunits2/ExternalPackage_udunits2.mk
+++ b/external/udunits2/ExternalPackage_udunits2.mk
@@ -14,7 +14,7 @@ $(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))
 else ifeq ($(OS),MACOSX)
-$(eval $(call gb_ExternalPackage_add_file,udunits2,$(LIBO_LIB_FOLDER)/libudunits2.dylib,lib/.libs/libudunits2.dylib))
+$(eval $(call gb_ExternalPackage_add_file,udunits2,$(LIBO_LIB_FOLDER)/libudunits2.0.dylib,lib/.libs/libudunits2.0.dylib))
 else
 $(eval $(call gb_ExternalPackage_add_file,udunits2,$(LIBO_LIB_FOLDER)/libudunits2.so,lib/.libs/libudunits2.so))
 $(eval $(call gb_ExternalPackage_add_file,udunits2,$(LIBO_LIB_FOLDER)/libudunits2.so.0,lib/.libs/libudunits2.so.0))
commit 57cd0a6f3c5e5d3b2b3268f0bfbff8e6faa5b748
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Mon Jun 1 22:12:54 2015 +0100

    Rename VERIFIED->VALID for formula status.
    
    Change-Id: I93a07e11546ebecf912449c72e57404731c346e9

diff --git a/sc/inc/units.hxx b/sc/inc/units.hxx
index 411fb84..1e0c5ea 100644
--- a/sc/inc/units.hxx
+++ b/sc/inc/units.hxx
@@ -45,7 +45,7 @@ struct RangeUnits {
  * is used).
  */
 enum class FormulaStatus {
-    VERIFIED,
+    VALID,
     UNKNOWN,
     ERROR_INPUT_SCALING,
     ERROR_INPUT_INCOMPATIBLE,
diff --git a/sc/qa/unit/units.cxx b/sc/qa/unit/units.cxx
index e2ad7cc..1dbf74f 100644
--- a/sc/qa/unit/units.cxx
+++ b/sc/qa/unit/units.cxx
@@ -221,7 +221,7 @@ void UnitsTest::testUnitVerification() {
     mpDoc->SetFormula(address, "=A1+A2");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
     // Test that addition of different units fails - incompatible types
     address = ScAddress(0, 6, 0);
@@ -235,14 +235,14 @@ void UnitsTest::testUnitVerification() {
     mpDoc->SetFormula(address, "=A1*B1+A2*B2");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
     // Test another combination (i.e. cm/s+'cm/s')
     address = ScAddress(0, 8, 0);
     mpDoc->SetFormula(address, "=A1/C1+D1");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
     // Test that another combination fails (cm*kg/s+'cm/s')
     address = ScAddress(0, 9, 0);
@@ -256,7 +256,7 @@ void UnitsTest::testUnitVerification() {
     mpDoc->SetFormula(address, "=A1+100*E1");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
     // 10cm + 100*1m = 110cm
     CPPUNIT_ASSERT_EQUAL(mpDoc->GetValue(address), 110.0);
 
@@ -287,7 +287,7 @@ void UnitsTest::testUnitVerification() {
     mpDoc->SetFormula(address, "=SUM(B1:B3)");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
     // SUM("cm"&"kg")
     address.IncRow();
@@ -315,14 +315,14 @@ void UnitsTest::testUnitVerification() {
     mpDoc->SetFormula(address, "=SUM(A1:A3)/SUM(C1:C3)+SUM(D1:D3)");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
     // PRODUCT("cm/","s")+"cm"
     address.IncRow();
     mpDoc->SetFormula(address, "=PRODUCT(C1:D1)+A1");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
     // PRODUCT("cm/","s")+"kg"
     address.IncRow();
@@ -337,7 +337,7 @@ void UnitsTest::testUnitVerification() {
     mpDoc->SetFormula(address, "=SUM(A1,A2:A3)");
     pCell = mpDoc->GetFormulaCell(address);
     pTokens = pCell->GetCode();
-    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+    CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
     // But mixing the columns fails because of mixed units
     // (This test is primarily to ensure that we can handle arbitrary numbers
@@ -358,7 +358,7 @@ void UnitsTest::testUnitVerification() {
         mpDoc->SetFormula(address, "=" + aFunc + "(A1:A2)+A3");
         pCell = mpDoc->GetFormulaCell(address);
         pTokens = pCell->GetCode();
-        CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VERIFIED);
+        CPPUNIT_ASSERT(mpUnitsImpl->verifyFormula(pTokens, address, mpDoc) == FormulaStatus::VALID);
 
         // FOO(cm) + kg
         address.IncRow();
@@ -376,7 +376,7 @@ void UnitsTest::testUnitVerification() {

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list