[Libreoffice-commits] core.git: Branch 'feature/unitver' - 3705 commits - accessibility/inc accessibility/source android/Bootstrap android/source animations/source avmedia/Library_avmediavlc.mk avmedia/source basctl/inc basctl/Library_basctl.mk basctl/source basebmp/source basebmp/test basegfx/inc basegfx/Library_basegfx.mk basegfx/qa basegfx/source basegfx/test basic/inc basic/qa basic/source bean/com bean/qa bean/test binaryurp/source bin/find-duplicated-sids.py bin/find-german-comments bin/find-unused-defines.awk bin/find-unused-defines.sh bin/find-unused-typedefs.py bin/find-unused-typedefs.sh bin/gbuild-to-ide bin/get-bugzilla-attachments-by-mimetype bin/includebloat.awk bin/lint-ui.py bin/lo-commit-stat bin/lo-pack-sources bin/lo-xlate-lang bridges/inc bridges/Library_cpp_uno.mk bridges/source bridges/test canvas/README canvas/source canvas/workben chart2/CppunitTest_chart2_trendcalculators.mk chart2/inc chart2/Library_chartcontroller.mk chart2/Module_chart2.mk chart2/qa chart2/README chart 2/source chart2/uiconfig chart2/UIConfig_chart2.mk chart2/workbench cli_ure/source codemaker/source comphelper/inc comphelper/qa comphelper/source compilerplugins/clang config_host/config_dconf.h.in config_host/config_extension_update.h.in config_host/config_global.h.in config_host/config_opengl.h.in config_host/config_version.h.in config_host.mk.in configmgr/CppunitTest_configmgr_unit.mk configmgr/inc configmgr/Library_configmgr.mk configmgr/qa configmgr/source configure.ac connectivity/inc connectivity/Jar_ConnectivityTools.mk connectivity/qa connectivity/source connectivity/workben cppcanvas/inc cppcanvas/source cppuhelper/inc cppuhelper/qa cppuhelper/source cppuhelper/test cppu/qa cppu/source cpputools/source cui/inc cui/source cui/uiconfig dbaccess/CppunitTest_dbaccess_RowSetClones.mk dbaccess/inc dbaccess/JunitTest_dbaccess_complex.mk dbaccess/qa dbaccess/source desktop/inc desktop/Library_sofficeapp.mk desktop/scripts desktop/source desktop/test desktop/win32 dictionaries dis tro-configs/LibreOfficeLinux.conf distro-configs/LibreOfficeWin32.conf distro-configs/LibreOfficeWin64.conf download.lst drawinglayer/Library_drawinglayer.mk drawinglayer/source dtrans/source dtrans/test editeng/inc editeng/qa editeng/source embeddedobj/source embeddedobj/test embedserv/Library_emser.mk embedserv/source eventattacher/source extensions/Library_oleautobridge.mk extensions/Library_so_activex.mk extensions/Library_so_activex_x64.mk extensions/qa extensions/source extensions/test extensions/uiconfig external/boost external/bzip2 external/clucene external/coinmp external/ct2n external/curl external/expat external/firebird external/glew external/graphite external/icu external/jfreereport external/lcms2 external/libcmis external/libetonyek external/libfreehand external/liblangtag external/libmwaw external/libodfgen external/liborcus external/librevenge external/libvisio external/libwpd external/libwpg external/libwps external/libxml2 external/libxslt external/mdds external/ Module_external.mk external/neon external/nss external/owncloud-android-lib external/poppler external/python3 external/redland external/udunits2 extras/Package_palettes.mk extras/source filter/CppunitTest_filter_utils.mk filter/Module_filter.mk filter/qa filter/source forms/JunitTest_forms_unoapi_1.mk forms/JunitTest_forms_unoapi_2.mk forms/JunitTest_forms_unoapi_3.mk forms/JunitTest_forms_unoapi_4.mk forms/JunitTest_forms_unoapi.mk forms/Module_forms.mk forms/qa forms/source formula/Library_for.mk formula/source fpicker/Library_fps_office.mk fpicker/source fpicker/uiconfig fpicker/UIConfig_fps.mk framework/inc framework/Library_fwk.mk framework/qa framework/source framework/util g .git-hooks/pre-commit .gitignore helpcompiler/inc helpcompiler/source helpcontent2 hwpfilter/source i18nlangtag/qa i18nlangtag/source i18npool/CustomTarget_localedata.mk i18npool/inc i18npool/Library_localedata_en.mk i18npool/Library_localedata_euro.mk i18npool/Library_localedata_others.mk i18npool/qa i18 npool/source icon-themes/breeze icon-themes/crystal icon-themes/galaxy icon-themes/hicontrast icon-themes/human icon-themes/industrial icon-themes/oxygen icon-themes/sifr icon-themes/tango icon-themes/tango_testing idlc/inc idlc/source idlc/test idl/inc idl/source include/animations include/avmedia include/basebmp include/basegfx include/basic include/canvas include/com include/comphelper include/connectivity include/cppcanvas include/cppu include/cppuhelper include/dbaccess include/drawinglayer include/editeng include/filter include/formula include/framework include/i18nlangtag include/i18nutil include/jvmfwk include/LibreOfficeKit include/linguistic include/o3tl include/oox include/osl include/package include/registry include/rtl include/sal include/salhelper include/sax include/sfx2 include/sot include/svl include/svtools include/svx include/systools include/test include/toolkit include/tools include/tubes include/typelib include/ucbhelper include/uno include/unotest include/unot ools include/vbahelper include/vcl include/xmloff include/xmlscript instsetoo_native/CustomTarget_install.mk instsetoo_native/CustomTarget_setup.mk instsetoo_native/inc_common instsetoo_native/inc_openoffice instsetoo_native/util io/source io/test javaunohelper/com javaunohelper/source javaunohelper/test jurt/com jurt/test jvmfwk/distributions jvmfwk/inc jvmfwk/plugins jvmfwk/source l10ntools/inc l10ntools/source Library_merged.mk librelogo/source libreofficekit/Executable_gtktiledviewer.mk libreofficekit/Library_libreofficekitgtk.mk libreofficekit/Module_libreofficekit.mk libreofficekit/qa libreofficekit/source lingucomponent/source linguistic/source logerrit lotuswordpro/inc lotuswordpro/source Makefile.fetch Makefile.in mysqlc/source nlpsolver/ThirdParty o3tl/CppunitTest_o3tl_tests.mk o3tl/qa odk/config odk/docs odk/examples odk/index.html odk/index_online.html odk/README odk/source offapi/com offapi/type_reference offapi/UnoApi_offapi.mk officecfg/registry onlineupdate/Executabl e_mar.mk onlineupdate/Executable_updater.mk onlineupdate/Makefile onlineupdate/Module_onlineupdate.mk onlineupdate/README onlineupdate/source oox/inc oox/source opencl/source package/inc package/source postprocess/CustomTarget_images.mk postprocess/CustomTarget_registry.mk postprocess/qa postprocess/Rdb_services.mk pyuno/inc pyuno/Library_pyuno.mk pyuno/Module_pyuno.mk pyuno/PythonTest_pytests.mk pyuno/PythonTest_pyuno_pytests_testcollections.mk pyuno/qa pyuno/source qadevOOo/qa qadevOOo/runner qadevOOo/testdocs qadevOOo/tests readlicense_oo/docs readlicense_oo/license readlicense_oo/Package_files.mk README.md README.Solaris registry/Executable_regview.mk registry/inc registry/Library_reg.mk registry/source registry/tools remotebridges/source reportbuilder/java reportdesign/inc reportdesign/qa reportdesign/source reportdesign/uiconfig RepositoryExternal.mk Repository.mk RepositoryModule_host.mk ridljar/com rsc/inc rsc/source sal/android sal/cppunittester salhelper/source sal/inc sal /Library_sal.mk sal/osl sal/qa sal/rtl sal/textenc sal/util sax/inc sax/qa sax/source sax/test scaddins/Library_analysis.mk scaddins/source sc/AllLangResTarget_sc.mk sc/CppunitTest_sc_annotationshapeobj.mk sc/CppunitTest_sc_core.mk sc/CppunitTest_sc_ucalc.mk sc/CppunitTest_sc_units.mk sc/inc sc/JunitTest_sc_complex.mk sc/JunitTest_sc_unoapi_1.mk sc/JunitTest_sc_unoapi_2.mk sc/JunitTest_sc_unoapi_3.mk sc/JunitTest_sc_unoapi_4.mk sc/JunitTest_sc_unoapi_5.mk sc/JunitTest_sc_unoapi_6.mk sc/JunitTest_sc_unoapi_7.mk sc/JunitTest_sc_unoapi.mk sc/Library_scfilt.mk sc/Library_sc.mk sc/Module_sc.mk scp2/AutoInstall.mk scp2/inc scp2/source sc/qa sc/README scripting/java scripting/source sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk sd/CppunitTest_sd_export_tests.mk sdext/inc sdext/README sdext/source sd/inc sd/Library_sd.mk sd/qa sd/sdi sd/source sd/uiconfig setup_native/source sfx2/CppunitTest_sfx2_controlleritem.mk sfx2/inc sfx2/JunitTest_sfx2_complex.mk sfx2/Library_sfx.mk sfx2/Module_s fx2.mk sfx2/PythonTest_sfx2_python.mk sfx2/qa sfx2/sdi sfx2/source sfx2/uiconfig shell/inc shell/qa shell/source slideshow/inc slideshow/qa slideshow/source slideshow/test smoketest/com smoketest/org smoketest/smoketest.cxx solenv/bin solenv/gbuild solenv/gdb soltools/cpp sot/inc sot/qa sot/source starmath/inc starmath/Library_sm.mk starmath/sdi starmath/source starmath/uiconfig stoc/source stoc/test store/source svgio/inc svgio/qa svgio/source svl/inc svl/qa svl/source svtools/inc svtools/langsupport svtools/Library_svt.mk svtools/source svtools/uiconfig svx/inc svx/Library_svxcore.mk svx/Library_svx.mk svx/sdi svx/source svx/uiconfig svx/UIConfig_svx.mk svx/workben sw/CppunitTest_sw_odfexport.mk sw/CppunitTest_sw_uiwriter.mk swext/mediawiki sw/inc sw/JunitTest_sw_unoapi_1.mk sw/JunitTest_sw_unoapi_2.mk sw/JunitTest_sw_unoapi_3.mk sw/JunitTest_sw_unoapi_4.mk sw/JunitTest_sw_unoapi.mk sw/Library_sw.mk sw/Module_sw.mk sw/qa sw/sdi sw/source sw/uiconfig sysui/desktop sysui/productlist .mk test/source testtools/com testtools/source toolkit/inc toolkit/JunitTest_toolkit_unoapi_1.mk toolkit/JunitTest_toolkit_unoapi_2.mk toolkit/JunitTest_toolkit_unoapi_3.mk toolkit/JunitTest_toolkit_unoapi_4.mk toolkit/JunitTest_toolkit_unoapi.mk toolkit/Library_tk.mk toolkit/Module_toolkit.mk toolkit/qa toolkit/source toolkit/test tools/CppunitTest_tools_test.mk tools/inc tools/qa tools/source translations tubes/source ucbhelper/source ucb/qa ucb/source ucb/test udkapi/com UnoControls/inc UnoControls/source unodevtools/source unoidl/source unotest/source unotools/source unoxml/source unusedcode.easy uui/source vbahelper/source vcl/android vcl/CppunitTest_vcl_lifecycle.mk vcl/generic vcl/headless vcl/inc vcl/ios vcl/Library_vcl.mk vcl/Module_vcl.mk vcl/opengl vcl/osx vcl/Package_opengl_blacklist.mk vcl/qa vcl/quartz vcl/README.lifecycle vcl/source vcl/unx vcl/win vcl/workben winaccessibility/inc winaccessibility/Library_uacccom.mk winaccessibility/source wizards/com wizards/source w riterfilter/CppunitTest_writerfilter_rtftok.mk writerfilter/documentation writerfilter/inc writerfilter/qa writerfilter/source writerperfect/qa writerperfect/source xmerge/source xmlhelp/Library_ucpchelp1.mk xmlhelp/source xmloff/dtd xmloff/inc xmloff/source xmlscript/source xmlsecurity/inc xmlsecurity/source xmlsecurity/workben

Andrzej Hunt andrzej at ahunt.org
Fri Aug 7 23:55:26 PDT 2015


Rebased ref, commits from common ancestor:
commit 8ce00654d39c6971cb57eb742547c3799bddef08
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 a8386c5..45b85bb 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -2982,8 +2982,7 @@ void ScViewFunc::NotifyUnitConversionRecommended( const ScAddress& rCellAddress,
                                                                                  rCellAddress,
                                                                                  pDoc,
                                                                                  rsHeaderUnit,
-                                                                                 rsCellUnit,
-                                                                                 pDocSh );
+                                                                                 rsCellUnit );
     pButtonConvertCell->SetClickHdl( LINK( this, ScViewFunc, UnitConversionRecommendedHandler ) );
 
     OUString sConvertText = pButtonConvertCell->GetText();
@@ -3000,32 +2999,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 103c64cb4d3e3fbd63d1649c1187eab274f4f8a9
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 c0fef60..a8386c5 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -594,7 +594,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();
@@ -2938,21 +2938,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 )
         {}
 };
 
@@ -2960,8 +2957,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.
@@ -3003,7 +3000,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 960627472b3c50d29ce99258bf10c01c34c30df0
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 4d939207309734ed26790e7ca72ec2a263f823cf
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 bb74d74..d25ef1c 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 3e35c62..dc19247 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 a3175b8..eb9b1f2 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 2e4643e..dc0570f 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();
@@ -247,6 +249,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();
@@ -262,6 +265,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet)
 
     if ( mpLbFormulaSyntax->GetSavedValue() != aSyntaxPos
          || mpCbEnglishFuncName->GetSavedValue() != (bEnglishFuncName ? 1 : 0)
+         || mpCbUnitValidat->GetSavedValue() != (bUnitValidat ? 1 : 0)
          || static_cast<OUString>(mpEdSepFuncArg->GetSavedValue()) != aSep
          || static_cast<OUString>(mpEdSepArrayCol->GetSavedValue()) != aSepArrayCol
          || static_cast<OUString>(mpEdSepArrayRow->GetSavedValue()) != aSepArrayRow
@@ -289,6 +293,7 @@ bool ScTpFormulaOptions::FillItemSet(SfxItemSet* rCoreSet)
 
         aOpt.SetFormulaSyntax(eGram);
         aOpt.SetUseEnglishFuncName(bEnglishFuncName);
+        aOpt.SetUnitValidat(bUnitValidat);
         aOpt.SetFormulaSepArg(aSep);
         aOpt.SetFormulaSepArrayCol(aSepArrayCol);
         aOpt.SetFormulaSepArrayRow(aSepArrayRow);
@@ -342,6 +347,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 6fd17e8..c0fef60 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -469,25 +469,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 );
@@ -583,17 +586,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 89bd89b5ad0429ca2efab70101e50f266bcbaf6b
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 8916e2d07da2e3dfab9b4efbfcb1234129a7a0fa
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 12cab9620ff4a0202f471d75e6c9e4b493822ead
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 03a9405e214d274fba68251966bf19dc26a48ea7
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 e489c57937fb7b31c093b5b42542017c11bfa518
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 e82592e34e45901def936207818a7fcdcb184384
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 c272354fdcb5493747af32231afa52334bcd99db
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 19358723805c305307b56e25173f96d3c124f4aa
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 a11fb8a47080af4cb00b6fece60d200d3d966e90
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 97bfe0b..fee16c0 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 197e4acb57722d6746b93c5186278ee7bd27afff
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 a46d54e..90623fa 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 77a94a04019c33b3fe5a671d79e18ee5c080bd42
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 b087b1267a966b2b24443e3b28f1edb5a9a9c7a2
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 7a079f5..a46d54e 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 ee4d6b9..36be3bc 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -186,6 +186,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 528845d92..2ffe813 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1736,7 +1736,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,
@@ -8732,48 +8732,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 d61a281..ca21f09 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 9d779fbc80e4e9ca10f2a226a8b561204b31bd1a
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 f10c3168667d603c0497dc8e1ae4b4a84249927c
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() {
     mpDoc->SetFormula(address, "=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);
 
 
     // header in [cm], cell with 100*cm
@@ -405,14 +405,14 @@ void UnitsTest::testUnitVerification() {
     mpDoc->SetFormula(address, "=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);
 
     // header in (cm/s), formula resulting in cm/s
     address = ScAddress(6, 1, 0);
     mpDoc->SetFormula(address, "=A1/C1");
     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);
 }
 
 void UnitsTest::testUnitFromFormatStringExtraction() {
diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index d160e17..6332747 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -246,7 +246,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
 
             }
 
-            return { FormulaStatus::VERIFIED, aFirstUnit };
+            return { FormulaStatus::VALID, aFirstUnit };
         }
         case ocProduct:
         {
@@ -269,7 +269,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
                 } while (aIt.next());
             }
 
-            return { FormulaStatus::VERIFIED, aUnit };
+            return { FormulaStatus::VALID, aUnit };
         }
         default:
             return { FormulaStatus::UNKNOWN, boost::none };
@@ -278,7 +278,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
         SAL_INFO("sc.units", "unit verification not supported for opcode: " << nOpCode);
         return { FormulaStatus::UNKNOWN, boost::none };
     }
-    return { FormulaStatus::VERIFIED, pOut };
+    return { FormulaStatus::VALID, pOut };
 }
 
 OUString UnitsImpl::extractUnitStringFromFormat(const OUString& rFormatString) {
@@ -566,7 +566,7 @@ FormulaStatus UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rF
             case FormulaStatus::ERROR_INPUT_INCOMPATIBLE:
             case FormulaStatus::UNKNOWN:
                return aResult.status;
-            case FormulaStatus::VERIFIED:
+            case FormulaStatus::VALID:
                 assert(aResult.units); // ensure that we have the optional unit
                 assert(aResult.units->isValid());
                 aStack.push( { RAUSItemType::UNITS, aResult.units.get() } );
@@ -619,7 +619,7 @@ FormulaStatus UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rF
         }
     }
 
-    return FormulaStatus::VERIFIED;
+    return FormulaStatus::VALID;
 }
 
 bool IsDigit(sal_Unicode c) {
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index b05b1b2..6fd17e8 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -471,7 +471,7 @@ 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::VERIFIED || aStatus == FormulaStatus::UNKNOWN )
+            if ( aStatus == FormulaStatus::VALID || aStatus == FormulaStatus::UNKNOWN )
             {
                 SAL_INFO( "sc.units", "verification successful" );
 
commit 1a40c3d3181841d5b83737efc7439624c5353ceb
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Mon Jun 1 22:11:22 2015 +0100

    Kill unnecessary UnitsStatus
    
    Is redundant now that we've got the public FormulaStatus.
    FormulaStatus adds two new variants that we don't need internally
    however they are only relevant in one location hence it makes sense
    to share the enum.
    
    Change-Id: Idb08a41574e56a2f994c7e8bc816ffd370d86766

diff --git a/sc/source/core/units/unitsimpl.cxx b/sc/source/core/units/unitsimpl.cxx
index 84d5c0e..d160e17 100644
--- a/sc/source/core/units/unitsimpl.cxx
+++ b/sc/source/core/units/unitsimpl.cxx
@@ -96,7 +96,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
         nOpCode < SC_OPCODE_STOP_UN_OP) {
 
         if ((rStack.size() == 0) || (rStack.top().type != RAUSItemType::UNITS)) {
-            return { UnitsStatus::UNITS_UNKNOWN, boost::none };
+            return { FormulaStatus::UNKNOWN, boost::none };
         }
 
         UtUnit pUnit = boost::get<UtUnit>(rStack.top().item);//rStack.top().item.get< UtUnit >();
@@ -105,7 +105,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
         switch (aOpCode) {
         case ocNot:
             if (!pUnit.isDimensionless()) {
-                return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
+                return { FormulaStatus::ERROR_INPUT_INCOMPATIBLE, boost::none };
             }
             // We just keep the same unit (in this case no unit) so can
             // fall through.
@@ -127,13 +127,13 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
         nOpCode < SC_OPCODE_STOP_BIN_OP) {
 
         if ((rStack.size() < 2) || (rStack.top().type != RAUSItemType::UNITS)) {
-            return { UnitsStatus::UNITS_UNKNOWN, boost::none };
+            return { FormulaStatus::UNKNOWN, boost::none };
         }
         UtUnit pSecondUnit = boost::get<UtUnit>(rStack.top().item);
         rStack.pop();
 
         if (rStack.top().type != RAUSItemType::UNITS) {
-            return { UnitsStatus::UNITS_UNKNOWN, boost::none };
+            return { FormulaStatus::UNKNOWN, boost::none };
         }
         UtUnit pFirstUnit = boost::get<UtUnit>(rStack.top().item);
         rStack.pop();
@@ -148,9 +148,9 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
                 pOut = pFirstUnit;
                 SAL_INFO("sc.units", "verified equality for unit " << pFirstUnit);
             } else if (pFirstUnit.areConvertibleTo(pSecondUnit)) {
-                return { UnitsStatus::UNITS_INVALID_SCALING, boost::none };
+                return { FormulaStatus::ERROR_INPUT_SCALING, boost::none };
             } else {
-                return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
+                return { FormulaStatus::ERROR_INPUT_INCOMPATIBLE, boost::none };
             }
 
             break;
@@ -174,7 +174,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
         // (In practice this would probably be nonsensical, but isn't a unit
         //  error per-se.)
         if (nParams == 0) {
-            return { UnitsStatus::UNITS_UNKNOWN, boost::none };
+            return { FormulaStatus::UNKNOWN, boost::none };
         }
 
         // This is still quite an ugly solution, even better would maybe be to have
@@ -218,9 +218,9 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
 
                     if (aFirstUnit.get() != aCurrentUnit) {
                         if (aFirstUnit.get().areConvertibleTo(aCurrentUnit)) {
-                            return { UnitsStatus::UNITS_INVALID_SCALING, boost::none };
+                            return { FormulaStatus::ERROR_INPUT_SCALING, boost::none };
                         } else {
-                            return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
+                            return { FormulaStatus::ERROR_INPUT_INCOMPATIBLE, boost::none };
                         }
                     }
                 }
@@ -236,9 +236,9 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
 
                         if (aFirstUnit.get() != aCurrentUnit) {
                             if (aFirstUnit.get().areConvertibleTo(aCurrentUnit)) {
-                                return { UnitsStatus::UNITS_INVALID_SCALING, boost::none };
+                                return { FormulaStatus::ERROR_INPUT_SCALING, boost::none };
                             } else {
-                                return { UnitsStatus::UNITS_INVALID_INCOMPATIBLE, boost::none };
+                                return { FormulaStatus::ERROR_INPUT_INCOMPATIBLE, boost::none };
                             }
                         }
                     }
@@ -246,7 +246,7 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
 
             }
 
-            return { UnitsStatus::UNITS_VALID, aFirstUnit };
+            return { FormulaStatus::VERIFIED, aFirstUnit };
         }
         case ocProduct:
         {
@@ -269,16 +269,16 @@ UnitsResult UnitsImpl::getOutputUnitsForOpCode(stack< RAUSItem >& rStack, const
                 } while (aIt.next());
             }
 
-            return { UnitsStatus::UNITS_VALID, aUnit };
+            return { FormulaStatus::VERIFIED, aUnit };
         }
         default:
-            return { UnitsStatus::UNITS_UNKNOWN, boost::none };
+            return { FormulaStatus::UNKNOWN, boost::none };
         }
     } else {
         SAL_INFO("sc.units", "unit verification not supported for opcode: " << nOpCode);
-        return { UnitsStatus::UNITS_UNKNOWN, boost::none };
+        return { FormulaStatus::UNKNOWN, boost::none };
     }
-    return { UnitsStatus::UNITS_VALID, pOut };
+    return { FormulaStatus::VERIFIED, pOut };
 }
 
 OUString UnitsImpl::extractUnitStringFromFormat(const OUString& rFormatString) {
@@ -562,18 +562,18 @@ FormulaStatus UnitsImpl::verifyFormula(ScTokenArray* pArray, const ScAddress& rF
             UnitsResult aResult = getOutputUnitsForOpCode(aStack, pToken, pDoc);
 
             switch (aResult.status) {
-            case UnitsStatus::UNITS_INVALID_SCALING:
-                return FormulaStatus::ERROR_INPUT_SCALING;
-            case UnitsStatus::UNITS_INVALID_INCOMPATIBLE:
-                return FormulaStatus::ERROR_INPUT_INCOMPATIBLE;
-            case UnitsStatus::UNITS_UNKNOWN:
-                // Unsupported hence we stop processing.
-                return FormulaStatus::UNKNOWN;
-            case UnitsStatus::UNITS_VALID:
+            case FormulaStatus::ERROR_INPUT_SCALING:
+            case FormulaStatus::ERROR_INPUT_INCOMPATIBLE:
+            case FormulaStatus::UNKNOWN:
+               return aResult.status;
+            case FormulaStatus::VERIFIED:
                 assert(aResult.units); // ensure that we have the optional unit
                 assert(aResult.units->isValid());
                 aStack.push( { RAUSItemType::UNITS, aResult.units.get() } );
                 break;
+            case FormulaStatus::ERROR_OUTPUT_SCALING:
+            case FormulaStatus::ERROR_OUTPUT_INCOMPATIBLE:
+                assert(false);
             }
 
             break;
diff --git a/sc/source/core/units/unitsimpl.hxx b/sc/source/core/units/unitsimpl.hxx
index b0fb137..934bb26 100644
--- a/sc/source/core/units/unitsimpl.hxx
+++ b/sc/source/core/units/unitsimpl.hxx
@@ -42,20 +42,13 @@ namespace test {
     class UnitsTest;
 }
 
-enum class UnitsStatus {
-    UNITS_VALID,
-    UNITS_UNKNOWN,
-    UNITS_INVALID_SCALING,
-    UNITS_INVALID_INCOMPATIBLE
-};
-
 /**
  * The result for a given units operation.
  * If UNITS_VALID then the resulting unit is also included,
  * otherwise units is empty.
  */
 struct UnitsResult {
-    UnitsStatus status;
+    FormulaStatus status;
     boost::optional<UtUnit> units;
 };
 
commit 5e79bc11d50eb476f0522ca91cd91d674ec41e0b
Author: Andrzej Hunt <andrzej at ahunt.org>
Date:   Mon Jun 1 21:34:04 2015 +0100

    Fix building with disabled unit verification.
    
    Change-Id: I78633082a0e0dfcaa27515ce8d9c8635e50735e9

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index e83399a..d61a281 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -487,7 +487,6 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/miscdlgs/solverutil \
     sc/source/ui/miscdlgs/solvrdlg \
     sc/source/ui/miscdlgs/tabopdlg \
-    sc/source/ui/miscdlgs/unitsconversiondlg \
     sc/source/ui/miscdlgs/warnbox \
     sc/source/ui/namedlg/namedefdlg \
     sc/source/ui/namedlg/namedlg \
@@ -700,6 +699,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/core/units/unitsimpl \
 	sc/source/core/units/util \
 	sc/source/core/units/utunit \
+    sc/source/ui/miscdlgs/unitsconversiondlg \
 ))
 endif
 
diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk
index 77c821c..afdf4e1 100644
--- a/sc/UIConfig_scalc.mk
+++ b/sc/UIConfig_scalc.mk
@@ -181,7 +181,9 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\
 	sc/uiconfig/scalc/ui/tpviewpage \
 	sc/uiconfig/scalc/ui/ttestdialog \
 	sc/uiconfig/scalc/ui/ungroupdialog \
-	sc/uiconfig/scalc/ui/unitsconversiondialog \
+    $(if $(ENABLE_CALC_UNITVERIFICATION), \
+		sc/uiconfig/scalc/ui/unitsconversiondialog \
+	) \
 	sc/uiconfig/scalc/ui/validationdialog \
 	sc/uiconfig/scalc/ui/validationcriteriapage \
 	sc/uiconfig/scalc/ui/validationhelptabpage \
diff --git a/sc/source/ui/app/scdll.cxx b/sc/source/ui/app/scdll.cxx
index 8bb182c..643c639 100644
--- a/sc/source/ui/app/scdll.cxx
+++ b/sc/source/ui/app/scdll.cxx
@@ -235,7 +235,9 @@ void ScDLL::Init()
     ScFormulaDlgWrapper         ::RegisterChildWindow(false, pMod);
 
     ScRandomNumberGeneratorDialogWrapper::RegisterChildWindow(false, pMod);
+#ifdef ENABLE_CALC_UNITVERIFICATION
     ScUnitsConversionDialogWrapper      ::RegisterChildWindow(false, pMod);
+#endif
     ScSamplingDialogWrapper             ::RegisterChildWindow(false, pMod);

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list