Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index


On Wed, Feb 29, 2012 at 11:49:38AM +0100, Lionel Elie Mamane wrote:

In the context of fdo#41166 (a bug in how our numbers/date parser
handles ambiguities), I thought "wouldn't it be better if we used a
proper parser generator and wrote a proper grammar instead of a
hand-coded parser"? It would be easier to debug, easier to maintain,
easier to read, ... and thus probably less buggy in the long run.

Well, I've a good "proof of concept" start on making it a
Boost::Spirit grammar.

Grmbl... Forgot the attachments. Here they are.

-- 
Lionel
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 *  Copyright © 2012 Lionel Elie Mamaneb <lionel@mamane.lu> (initial developer)
 * Heavily inspired and copy-pasted from Boost::Spirit:
 *  Copyright (c) 2001-2011 Joel de Guzman
 *  Copyright (c) 2001-2011 Hartmut Kaiser
 *  Copyright (c)      2010 Bryce Lelbach
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#if !defined(LIBO_SPIRIT_CLASSES)
#define LIBO_SPIRIT_CLASSES

#if defined(_MSC_VER)
#pragma once
#endif

#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/support/char_set/basic_chset.hpp>
#include <boost/spirit/home/qi/char/char_parser.hpp>
#include <boost/spirit/home/qi/char/char_class.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/spirit/home/qi/auxiliary/lazy.hpp>
#include <boost/spirit/home/qi/detail/enable_lit.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_const.hpp>

#include "lo_classify.hxx"
#include <unotools/charclass.hxx>

#if defined(_MSC_VER)
#pragma once
#endif

#define LIBO_SPIRIT_CHAR_CODE(name, charset)                                    \
    typedef spirit::terminal<tag::lo_char_code<tag::lo_##name, charset> >       \
        lo_##name##_type;                                                       \
    lo_##name##_type const lo_##name = lo_##name##_type();                      \
                                                                                \
    inline void silence_unused_warnings_lo_##name() { (void) lo_##name; }       \
    /***/

#define LIBO_SPIRIT_DEFINE_CHAR_CODES(charset)                                  \
    namespace boost { namespace spirit { namespace charset                      \
    {                                                                           \
        LIBO_SPIRIT_CHAR_CODE(alnum, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(alpha, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(blank, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(cntrl, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(digit, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(graph, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(print, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(punct, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(space, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(xdigit, spirit::char_encoding::charset)           \
        LIBO_SPIRIT_CHAR_CODE(letter, spirit::char_encoding::charset)           \
        LIBO_SPIRIT_CHAR_CODE(mark, spirit::char_encoding::charset)             \
        LIBO_SPIRIT_CHAR_CODE(number, spirit::char_encoding::charset)           \
        LIBO_SPIRIT_CHAR_CODE(separator, spirit::char_encoding::charset)        \
        LIBO_SPIRIT_CHAR_CODE(other, spirit::char_encoding::charset)            \
        LIBO_SPIRIT_CHAR_CODE(punctuation, spirit::char_encoding::charset)      \
        LIBO_SPIRIT_CHAR_CODE(symbol, spirit::char_encoding::charset)           \
        LIBO_SPIRIT_CHAR_CODE(letternum, spirit::char_encoding::charset)        \
        LIBO_SPIRIT_CHAR_CODE(alphabetic, spirit::char_encoding::charset)       \
        LIBO_SPIRIT_CHAR_CODE(uppercase, spirit::char_encoding::charset)        \
        LIBO_SPIRIT_CHAR_CODE(lowercase, spirit::char_encoding::charset)        \
        LIBO_SPIRIT_CHAR_CODE(white_space, spirit::char_encoding::charset)      \
        LIBO_SPIRIT_CHAR_CODE(hex_digit, spirit::char_encoding::charset)        \
        LIBO_SPIRIT_CHAR_CODE(noncharacter_code_point, spirit::char_encoding::charset)         \
        LIBO_SPIRIT_CHAR_CODE(default_ignorable_code_point, spirit::char_encoding::charset)    \
    }}}

LIBO_SPIRIT_DEFINE_CHAR_CODES(ascii)
LIBO_SPIRIT_DEFINE_CHAR_CODES(iso8859_1)
LIBO_SPIRIT_DEFINE_CHAR_CODES(standard)
LIBO_SPIRIT_DEFINE_CHAR_CODES(standard_wide)
#if defined(BOOST_SPIRIT_UNICODE)
LIBO_SPIRIT_DEFINE_CHAR_CODES(unicode)
#endif

namespace boost { namespace spirit
{
    ///////////////////////////////////////////////////////////////////////////
    // Enablers
    ///////////////////////////////////////////////////////////////////////////
    // enables lo_alnum, lo_alpha, lo_letter, etc.
    template <typename TestClass, typename CharEncoding, typename A0>
    struct use_terminal<qi::domain,
                        terminal_ex< tag::lo_char_code<TestClass, CharEncoding >,
                                     fusion::vector1<A0> > >
      : mpl::true_ {};

}}

namespace boost { namespace spirit { namespace qi
{
    ///////////////////////////////////////////////////////////////////////////
    // Generic char classification parser (for alnum, alpha, graph, etc.)
    ///////////////////////////////////////////////////////////////////////////
    template <typename Tag>
    struct lo_class_parser
      : char_parser< lo_class_parser<Tag>, typename Tag::char_encoding::char_type >
    {
        typedef typename Tag::char_encoding char_encoding;
        typedef typename Tag::char_class classification;

        lo_class_parser(CharClass *r_pCC)
          : pCC(r_pCC) {}

        template <typename CharParam, typename Context>
        bool test(CharParam c, Context&) const
        {
            using spirit::lo_char_class::classify;
            return traits::ischar<CharParam, char_encoding>::call(c) &&
                classify<char_encoding>::is(classification(), pCC, c);
        }

        template <typename Context>
        info what(Context& /*context*/) const
        {
            typedef spirit::lo_char_class::what<char_encoding> what_;
            return info(what_::is(classification()));
        }

        CharClass *pCC;
    };

    ///////////////////////////////////////////////////////////////////////////
    // Parser generators: make_xxx function (objects)
    ///////////////////////////////////////////////////////////////////////////
    template <typename TestClass, typename CharEncoding, typename Modifiers, typename A0>
    struct make_primitive<
        terminal_ex< tag::lo_char_code< TestClass, CharEncoding >, fusion::vector1<A0> >,
        Modifiers >
    {
        typedef typename
            spirit::detail::get_encoding<Modifiers, CharEncoding>::type
        char_encoding;

        typedef tag::lo_char_code<TestClass, char_encoding> tag;

        typedef lo_class_parser< tag > result_type;

        template <typename Terminal>
        result_type operator()(Terminal const& term, unused_type) const
        {
            return result_type(fusion::at_c<0>(term.args));
        }
    };

}}}

#endif
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 *  Copyright © 2012 Lionel Elie Mamaneb <lionel@mamane.lu> (initial developer)
 * Heavily inspired and copy-pasted from Boost::Spirit:
 *  Copyright (c) 2001-2011 Joel de Guzman
 *  Copyright (c) 2001-2011 Hartmut Kaiser
 *  Copyright (c)      2010 Bryce Lelbach
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#if !defined(LIBO_SPIRIT_CLASSIFY)
#define LIBO_SPIRIT_CLASSIFY

#if defined(_MSC_VER)
#pragma once
#endif

#include <rtl/string>

#include <boost/proto/proto.hpp>
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/make_signed.hpp>

#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4800) // 'int' : forcing value to bool 'true' or 'false' warning
#endif

namespace boost { namespace spirit { namespace tag
{
    ///////////////////////////////////////////////////////////////////////////
    // classification tags
    struct lo_alnum {};
    struct lo_alpha {};
    struct lo_digit {};
    struct lo_xdigit {};
    struct lo_cntrl {};
    struct lo_graph {};
    struct lo_print {};
    struct lo_punct {};
    struct lo_space {};
    struct lo_blank {};

///////////////////////////////////////////////////////////////////////////
//  Unicode Major Categories
///////////////////////////////////////////////////////////////////////////
    struct lo_letter {};
    struct lo_mark {};
    struct lo_number {};
    struct lo_separator {};
    struct lo_other {};
    struct lo_punctuation {};
    struct lo_symbol {};

///////////////////////////////////////////////////////////////////////////
//  Unicode Derived Categories
///////////////////////////////////////////////////////////////////////////
    struct lo_letternum {};
    struct lo_alphabetic {};
    struct lo_uppercase {};
    struct lo_lowercase {};
    struct lo_white_space {};
    struct lo_hex_digit {};
    struct lo_noncharacter_code_point {};
    struct lo_default_ignorable_code_point {};

    ///////////////////////////////////////////////////////////////////////////
    // This composite tag type encodes both the character
    // set and the specific char tag (used for classification
    // or conversion). char_code_base and char_encoding_base
    // can be used to test for modifier membership (see modifier.hpp)

    template <typename TestClass, typename CharEncoding>
    struct lo_char_code
        : char_code_base<TestClass>, char_encoding_base<CharEncoding>
    {
        typedef CharEncoding char_encoding; // e.g. ascii
        typedef TestClass char_class;       // e.g. tag::alnum
    };

}}}

namespace boost { namespace spirit { namespace lo_char_class
{
    ///////////////////////////////////////////////////////////////////////////
    // Test characters for classification
    template <typename CharEncoding>
    struct classify
    {
        typedef typename CharEncoding::char_type char_type;

// TODO: don't reimplement the wheel qua UTF32-UTF16 conversion
#define LO_SPIRIT_CLASSIFY(name, isname)                                        \
        template <typename Char>                                                \
        static bool                                                             \
        is(tag::lo_##name, CharClass *pCC, Char ch)                             \
        {                                                                       \
            ::boost::uint32_t c(detail::cast_char< ::boost::uint32_t >(ch));    \
            sal_Unicode c16[2];                                                 \
            int len;                                                            \
            if ( c < 0x10000 )                                                  \
            {                                                                   \
                c16[0] = static_cast<sal_Unicode>(c);                           \
                len = 1;                                                        \
            }                                                                   \
            else                                                                \
            {                                                                   \
                c -= 0x10000;                                                   \
                c16[0] = 0xD800 | ( c >> 10 );                                  \
                c16[1] = 0xDC00 | ( c & 0x3FF );                                \
                len = 2;                                                        \
            }                                                                   \
            OUString s(&c16[0], len);                                           \
            return pCC->isname(s, 1);                                           \
        }
        /***/

        LO_SPIRIT_CLASSIFY(alnum,  isAlphaNumeric)
        LO_SPIRIT_CLASSIFY(alpha,  isAlpha)
        LO_SPIRIT_CLASSIFY(digit,  isDigit)
        LO_SPIRIT_CLASSIFY(letter, isLetter)
        LO_SPIRIT_CLASSIFY(letternum, isLetterNumeric)

#undef LO_SPIRIT_CLASSIFY
    };

    ///////////////////////////////////////////////////////////////////////////
    // Info on character classification
    template <typename CharEncoding>
    struct what
    {
#ifndef SAL_STRINGIFY
#   define SAL_STRINGIFY_ARG(x) #x
#   define SAL_STRINGIFY(x) SAL_STRINGIFY_ARG(x)
#endif
#define LO_SPIRIT_CLASSIFY_WHAT(name)                                           \
        static char const* is(tag::lo_##name)                                   \
        {                                                                       \
            return BOOST_PP_STRINGIZE(lo_##name);                               \
        }                                                                       \
        /***/

        LO_SPIRIT_CLASSIFY_WHAT(alnum)
        LO_SPIRIT_CLASSIFY_WHAT(alpha)
        LO_SPIRIT_CLASSIFY_WHAT(digit)
        LO_SPIRIT_CLASSIFY_WHAT(letter)
        LO_SPIRIT_CLASSIFY_WHAT(letternum)

#undef LO_SPIRIT_CLASSIFY_WHAT
    };
}}}

#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif

#endif
diff --git a/sal/inc/rtl/ustring.hxx b/sal/inc/rtl/ustring.hxx
index 868f6dd..27d3750 100644
--- a/sal/inc/rtl/ustring.hxx
+++ b/sal/inc/rtl/ustring.hxx
@@ -45,6 +45,8 @@
 #include <new>
 #endif
 
+#include <boost/regex/pending/unicode_iterator.hpp>
+
 namespace rtl
 {
 /* ======================================================================= */
@@ -78,6 +80,9 @@ class OUString
 public:
     /** @internal */
     rtl_uString * pData;
+    typedef boost::u16_to_u32_iterator<const sal_Unicode*> const_iterator;
+    const_iterator begin() const { return boost::u16_to_u32_iterator<const 
sal_Unicode*>(getStr()); };
+    const_iterator end()   const { return boost::u16_to_u32_iterator<const sal_Unicode*>(getStr() 
+ getLength()); };
 
 private:
     /** @internal */
diff --git a/svl/source/numbers/spirit/lo_traits.hxx b/svl/source/numbers/spirit/lo_traits.hxx
new file mode 100644
index 0000000..41a77bb
--- /dev/null
+++ b/svl/source/numbers/spirit/lo_traits.hxx
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ *  Copyright © 2012 Lionel Elie Mamaneb <lionel@mamane.lu> (initial developer)
+ * Heavily inspired and copy-pasted from Boost::Spirit:
+ *  Copyright (c) 2001-2011 Joel de Guzman
+ *  Copyright (c) 2001-2011 Hartmut Kaiser
+ *  Copyright (c)      2010 Bryce Lelbach
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#if !defined(LIBO_SPIRIT_TRAITS)
+#define LIBO_SPIRIT_TRAITS
+
+#include <boost/spirit/home/support/string_traits.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/identity.hpp>
+
+#include <rtl/string.hxx>
+#include <tools/string.hxx>
+
+namespace boost { namespace spirit { namespace traits {
+
+#ifdef SAL_UNICODE_NOTEQUAL_WCHAR_T
+    // These are a bit dangerous, since in LibreOffice context
+    // the most straighforward way to get sal_Unicode* does
+    // not necessarily give a NULL-terminated result.
+    // OTOH, not providing them implies a different
+    // behaviour on MSVC than on other platforms :-|
+    template <>
+    struct is_char<sal_Unicode> : mpl::true_ {};
+    template <>
+    struct is_string<sal_Unicode*> : mpl::true_ {};
+    template <>
+    struct is_string<sal_Unicode const*> : mpl::true_ {};
+    template <std::size_t N>
+    struct is_string<sal_Unicode[N]> : mpl::true_ {};
+    template <std::size_t N>
+    struct is_string<sal_Unicode const[N]> : mpl::true_ {};
+    template <std::size_t N>
+    struct is_string<sal_Unicode(&)[N]> : mpl::true_ {};
+    template <std::size_t N>
+    struct is_string<sal_Unicode const(&)[N]> : mpl::true_ {};
+#endif
+
+// OUString
+    template <>
+    struct is_string<rtl::OUString> : mpl::true_ {};
+    template <>
+    struct char_type_of<rtl::OUString> : mpl::identity<sal_uInt32> {};
+
+    template <>
+    struct is_container<rtl::OUString> : mpl::true_ {};
+
+    template <>
+    struct container_value<rtl::OUString> : mpl::identity<sal_uInt32> {};
+
+    // template <typename T>
+    // inline const sal_Unicode* get_begin(rtl::OUString const& str)
+    // { return str.getStr(); }
+
+    // template <typename T>
+    // inline const sal_Unicode* get_end(rtl::OUString const& str)
+    // { return str.getStr() + str.getLength(); }
+
+    // template <typename T>
+    // inline const sal_Unicode* get_begin(rtl::OUString  &str)
+    // { return str.getStr(); }
+
+    // template <typename T>
+    // inline const sal_Unicode* get_end(rtl::OUString &str)
+    // { return str.getStr() + str.getLength(); }
+
+// rtl_uString
+    template <>
+    struct is_string<rtl_uString> : mpl::true_ {};
+    template <>
+    struct char_type_of<rtl_uString> : mpl::identity<sal_Unicode> {};
+
+    template <typename T>
+    inline const sal_Unicode* get_begin(rtl_uString const& str)
+    { return rtl_uString_getStr(&str); }
+
+    template <typename T>
+    inline const sal_Unicode* get_end(rtl_uString const& str)
+    { return rtl_uString_getStr(&str) + rtl_uString_getLength(&str); }
+
+    template <typename T>
+    inline const sal_Unicode* get_begin(rtl_uString  &str)
+    { return rtl_uString_getStr(&str); }
+
+    template <typename T>
+    inline const sal_Unicode* get_end(rtl_uString &str)
+    { return rtl_uString_getStr(&str) + rtl_uString_getLength(&str); }
+
+// rtl::OString
+    template <>
+    struct is_string<rtl::OString> : mpl::true_ {};
+    template <>
+    struct char_type_of<rtl::OString> : mpl::identity<sal_Char> {};
+
+    template <typename T>
+    inline const char* get_begin(rtl::OString const& str)
+    { return str.getStr(); }
+
+    template <typename T>
+    inline const char* get_end(rtl::OString const& str)
+    { return str.getStr() + str.getLength(); }
+
+    template <typename T>
+    inline const char* get_begin(rtl::OString  &str)
+    { return str.getStr(); }
+
+    template <typename T>
+    inline const char* get_end(rtl::OString &str)
+    { return str.getStr() + str.getLength(); }
+
+// rtl_String
+    template <>
+    struct is_string<rtl_String> : mpl::true_ {};
+    template <>
+    struct char_type_of<rtl_String> : mpl::identity<sal_Char> {};
+
+    template <typename T>
+    inline const char* get_begin(rtl_String const& str)
+    { return rtl_string_getStr(&str); }
+
+    template <typename T>
+    inline const char* get_end(rtl_String const& str)
+    { return rtl_string_getStr(&str) + rtl_string_getLength(&str); }
+
+    template <typename T>
+    inline const char* get_begin(rtl_String  &str)
+    { return rtl_string_getStr(&str); }
+
+    template <typename T>
+    inline const char* get_end(rtl_String &str)
+    { return rtl_string_getStr(&str) + rtl_string_getLength(&str); }
+
+// Deprecated strings
+// UniString
+    template <>
+    struct is_string<UniString> : mpl::true_ {};
+    template <>
+    struct char_type_of<UniString> : mpl::identity<sal_Unicode> {};
+
+    // template <typename T>
+    // inline const sal_Unicode* get_begin(UniString const& str)
+    // { return str.GetBuffer(); }
+
+    // template <typename T>
+    // inline const sal_Unicode* get_end(UniString const& str)
+    // { return str.GetBuffer() + str.Len(); }
+
+    // template <typename T>
+    // inline const sal_Unicode* get_begin(UniString  &str)
+    // { return str.GetBufferAccess(); }
+
+    // template <typename T>
+    // inline const sal_Unicode* get_end(UniString &str)
+    // { return str.GetBufferAccess() + str.Len(); }
+
+
+}}}
+
+#endif
diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index 6e1cde0..02c7498 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -27,6 +27,7 @@
  ************************************************************************/
 
 
+#include <cmath>
 #include <ctype.h>
 #include <stdlib.h>
 #include <float.h>
@@ -49,6 +50,10 @@
 #include "zforfind.hxx"
 #undef _ZFORFIND_CXX
 
+#define BOOST_SPIRIT_UNICODE
+#include "spirit/lo_traits.hxx"
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix.hpp>
 
 #ifndef DBG_UTIL
 #define NF_TEST_CALENDAR 0
@@ -60,6 +65,8 @@
 #include <com/sun/star/i18n/XCalendar3.hpp>
 #endif
 
+namespace qi = boost::spirit::qi;
+namespace enc = boost::spirit::unicode;
 
 const sal_uInt8 ImpSvNumberInputScan::nMatchedEndString    = 0x01;
 const sal_uInt8 ImpSvNumberInputScan::nMatchedMidString    = 0x02;
@@ -159,13 +166,15 @@ inline bool ImpSvNumberInputScan::MyIsdigit( sal_Unicode c )
 
 //---------------------------------------------------------------------------
 //
-void ImpSvNumberInputScan::TransformInput( String& rStr )
+void ImpSvNumberInputScan::TransformInput( ::rtl::OUString& rStr )
 {
-    xub_StrLen nPos, nLen;
-    for ( nPos = 0, nLen = rStr.Len(); nPos < nLen; ++nPos )
+    sal_Int32 nPos = 0;
+    const sal_Int32 nLen = rStr.getLength();
+
+    while ( nPos < nLen )
     {
-        if ( 256 <= rStr.GetChar( nPos ) &&
-                pFormatter->GetCharClass()->isDigit( rStr, nPos ) )
+        sal_Int32 c = rStr.iterateCodePoints( &nPos );
+        if ( c >= 256 && pFormatter->GetCharClass()->isDigit( rStr, nPos ) )
             break;
     }
     if ( nPos < nLen )
@@ -180,24 +189,24 @@ void ImpSvNumberInputScan::TransformInput( String& rStr )
 // Only simple unsigned floating point values without any error detection,
 // decimal separator has to be '.'
 
-double ImpSvNumberInputScan::StringToDouble( const String& rStr, bool bForceFraction )
+double ImpSvNumberInputScan::StringToDouble( const ::rtl::OUString& rStr, bool bForceFraction )
 {
     double fNum = 0.0;
     double fFrac = 0.0;
     int nExp = 0;
     xub_StrLen nPos = 0;
-    xub_StrLen nLen = rStr.Len();
+    xub_StrLen nLen = rStr.getLength();
     bool bPreSep = !bForceFraction;
 
     while (nPos < nLen)
     {
-        if (rStr.GetChar(nPos) == '.')
+        if (rStr[nPos] == '.')
             bPreSep = false;
         else if (bPreSep)
-            fNum = fNum * 10.0 + (double) (rStr.GetChar(nPos) - '0');
+            fNum = fNum * 10.0 + (double) (rStr[nPos] - '0');
         else
         {
-            fFrac = fFrac * 10.0 + (double) (rStr.GetChar(nPos) - '0');
+            fFrac = fFrac * 10.0 + (double) (rStr[nPos] - '0');
             --nExp;
         }
         nPos++;
@@ -238,7 +247,7 @@ enum ScanState              // States der Turing-Maschine
 
 bool ImpSvNumberInputScan::NextNumberStringSymbol(
         const sal_Unicode*& pStr,
-        String& rSymbol )
+        ::rtl::OUString& rSymbol )
 {
     bool isNumber = false;
     sal_Unicode cToken;
@@ -285,9 +294,9 @@ bool ImpSvNumberInputScan::NextNumberStringSymbol(
     }   // while
 
     if ( nChars )
-        rSymbol.Assign( pStr, nChars );
+        rSymbol=::rtl::OUString( pStr, nChars );
     else
-        rSymbol.Erase();
+        rSymbol = ::rtl::OUString();
 
     pStr = pHere;
 
@@ -303,11 +312,11 @@ bool ImpSvNumberInputScan::NextNumberStringSymbol(
 
 bool ImpSvNumberInputScan::SkipThousands(
         const sal_Unicode*& pStr,
-        String& rSymbol )
+        ::rtl::OUString& rSymbol )
 {
     bool res = false;
     sal_Unicode cToken;
-    const String& rThSep = pFormatter->GetNumThousandSep();
+    const ::rtl::OUString& rThSep = pFormatter->GetNumThousandSep();
     register const sal_Unicode* pHere = pStr;
     ScanState eState = SsStart;
     xub_StrLen nCounter = 0;                                // counts 3 digits
@@ -322,7 +331,7 @@ bool ImpSvNumberInputScan::SkipThousands(
                 {
                     nCounter = 0;
                     eState = SsGetValue;
-                    pHere += rThSep.Len()-1;
+                    pHere += rThSep.getLength()-1;
                 }
                 else
                 {
@@ -333,7 +342,7 @@ bool ImpSvNumberInputScan::SkipThousands(
             case SsGetValue:
                 if ( MyIsdigit( cToken ) )
                 {
-                    rSymbol += cToken;
+                    rSymbol += ::rtl::OUString(cToken);
                     nCounter++;
                     if (nCounter == 3)
                     {
@@ -355,8 +364,8 @@ bool ImpSvNumberInputScan::SkipThousands(
     if (eState == SsGetValue)               // break witth less than 3 digits
     {
         if ( nCounter )
-            rSymbol.Erase( rSymbol.Len() - nCounter, nCounter );
-        pHere -= nCounter + rThSep.Len();       // put back ThSep also
+            rSymbol.replaceAt( rSymbol.getLength() - nCounter, nCounter, ::rtl::OUString() );
+        pHere -= nCounter + rThSep.getLength();       // put back ThSep also
     }
     pStr = pHere;
 
@@ -367,10 +376,10 @@ bool ImpSvNumberInputScan::SkipThousands(
 //---------------------------------------------------------------------------
 //      NumberStringDivision
 
-void ImpSvNumberInputScan::NumberStringDivision( const String& rString )
+void ImpSvNumberInputScan::NumberStringDivision( const ::rtl::OUString& rString )
 {
-    const sal_Unicode* pStr = rString.GetBuffer();
-    const sal_Unicode* const pEnd = pStr + rString.Len();
+    const sal_Unicode* pStr = rString.getStr();
+    const sal_Unicode* const pEnd = pStr + rString.getLength();
     while ( pStr < pEnd && nAnzStrings < SV_MAX_ANZ_INPUT_STRINGS )
     {
         if ( NextNumberStringSymbol( pStr, sStrArray[nAnzStrings] ) )
@@ -395,11 +404,11 @@ void ImpSvNumberInputScan::NumberStringDivision( const String& rString )
 //---------------------------------------------------------------------------
 // Whether rString contains rWhat at nPos
 
-bool ImpSvNumberInputScan::StringContainsImpl( const String& rWhat,
-            const String& rString, xub_StrLen nPos )
+bool ImpSvNumberInputScan::StringContainsImpl( const ::rtl::OUString& rWhat,
+            const ::rtl::OUString& rString, xub_StrLen nPos )
 {
-    if ( nPos + rWhat.Len() <= rString.Len() )
-        return StringPtrContainsImpl( rWhat, rString.GetBuffer(), nPos );
+    if ( nPos + rWhat.getLength() <= rString.getLength() )
+        return StringPtrContainsImpl( rWhat, rString.getStr(), nPos );
     return false;
 }
 
@@ -407,13 +416,13 @@ bool ImpSvNumberInputScan::StringContainsImpl( const String& rWhat,
 //---------------------------------------------------------------------------
 // Whether pString contains rWhat at nPos
 
-bool ImpSvNumberInputScan::StringPtrContainsImpl( const String& rWhat,
+bool ImpSvNumberInputScan::StringPtrContainsImpl( const ::rtl::OUString& rWhat,
             const sal_Unicode* pString, xub_StrLen nPos )
 {
-    if ( rWhat.Len() == 0 )
+    if ( rWhat.getLength() == 0 )
         return false;
-    register const sal_Unicode* pWhat = rWhat.GetBuffer();
-    register const sal_Unicode* const pEnd = pWhat + rWhat.Len();
+    register const sal_Unicode* pWhat = rWhat.getStr();
+    register const sal_Unicode* const pEnd = pWhat + rWhat.getLength();
     register const sal_Unicode* pStr = pString + nPos;
     while ( pWhat < pEnd )
     {
@@ -431,10 +440,10 @@ bool ImpSvNumberInputScan::StringPtrContainsImpl( const String& rWhat,
 //
 // ueberspringt genau das angegebene Zeichen
 
-inline bool ImpSvNumberInputScan::SkipChar( sal_Unicode c, const String& rString,
+inline bool ImpSvNumberInputScan::SkipChar( sal_Unicode c, const ::rtl::OUString& rString,
         xub_StrLen& nPos )
 {
-    if ((nPos < rString.Len()) && (rString.GetChar(nPos) == c))
+    if ((nPos < rString.getLength()) && (rString[nPos] == c))
     {
         nPos++;
         return true;
@@ -448,12 +457,12 @@ inline bool ImpSvNumberInputScan::SkipChar( sal_Unicode c, const String& 
rString
 //
 // Ueberspringt Leerzeichen
 
-inline void ImpSvNumberInputScan::SkipBlanks( const String& rString,
+inline void ImpSvNumberInputScan::SkipBlanks( const ::rtl::OUString& rString,
         xub_StrLen& nPos )
 {
-    if ( nPos < rString.Len() )
+    if ( nPos < rString.getLength() )
     {
-        register const sal_Unicode* p = rString.GetBuffer() + nPos;
+        register const sal_Unicode* p = rString.getStr() + nPos;
         while ( *p == ' ' )
         {
             nPos++;
@@ -468,12 +477,12 @@ inline void ImpSvNumberInputScan::SkipBlanks( const String& rString,
 //
 // jump over rWhat in rString at nPos
 
-inline bool ImpSvNumberInputScan::SkipString( const String& rWhat,
-        const String& rString, xub_StrLen& nPos )
+inline bool ImpSvNumberInputScan::SkipString( const ::rtl::OUString& rWhat,
+        const ::rtl::OUString& rString, xub_StrLen& nPos )
 {
     if ( StringContains( rWhat, rString, nPos ) )
     {
-        nPos = nPos + rWhat.Len();
+        nPos = nPos + rWhat.getLength();
         return true;
     }
     return false;
@@ -486,14 +495,14 @@ inline bool ImpSvNumberInputScan::SkipString( const String& rWhat,
 // recognizes exactly ,111 in {3} and {3,2} or ,11 in {3,2} grouping
 
 inline bool ImpSvNumberInputScan::GetThousandSep(
-        const String& rString,
+        const ::rtl::OUString& rString,
         xub_StrLen& nPos,
         sal_uInt16 nStringPos )
 {
-    const String& rSep = pFormatter->GetNumThousandSep();
+    const ::rtl::OUString& rSep = pFormatter->GetNumThousandSep();
     // Is it an ordinary space instead of a non-breaking space?
-    bool bSpaceBreak = rSep.GetChar(0) == 0xa0 && rString.GetChar(0) == 0x20 &&
-        rSep.Len() == 1 && rString.Len() == 1;
+    bool bSpaceBreak = rSep[0] == 0xa0 && rString[0] == 0x20 &&
+        rSep.getLength() == 1 && rString.getLength() == 1;
     if (!( (rString == rSep || bSpaceBreak)             // nothing else
                 && nStringPos < nAnzStrings - 1         // safety first!
                 && IsNum[nStringPos+1] ))               // number follows
@@ -507,13 +516,13 @@ inline bool ImpSvNumberInputScan::GetThousandSep(
      * currently there is no track kept where group separators occur. In {3,2}
      * #,###,### and #,##,## would be valid input, which maybe isn't even bad
      * for #,###,###. Other combinations such as #,###,## maybe not. */
-    xub_StrLen nLen = sStrArray[nStringPos+1].Len();
+    xub_StrLen nLen = sStrArray[nStringPos+1].getLength();
     if (nLen == aGrouping.get()                         // with 3 (or so) digits
             || nLen == aGrouping.advance().get()        // or with 2 (or 3 or so) digits
             || nPosThousandString == nStringPos+1       // or concatenated
        )
     {
-        nPos = nPos + rSep.Len();
+        nPos = nPos + rSep.getLength();
         return true;
     }
     return false;
@@ -523,19 +532,19 @@ inline bool ImpSvNumberInputScan::GetThousandSep(
 //---------------------------------------------------------------------------
 //      GetLogical
 //
-// Conversion of text to logial value
+// Conversion of text to logical value
 // "true" =>  1:
 // "false"=> -1:
 // else   =>  0:
 
-short ImpSvNumberInputScan::GetLogical( const String& rString )
+short ImpSvNumberInputScan::GetLogical( const ::rtl::OUString& rString )
 {
     short res;
 
     const ImpSvNumberformatScan* pFS = pFormatter->GetFormatScanner();
-    if ( rString == pFS->GetTrueString() )
+    if ( rString == ::rtl::OUString(pFS->GetTrueString()) )
         res = 1;
-    else if ( rString == pFS->GetFalseString() )
+    else if ( rString == ::rtl::OUString(pFS->GetFalseString()) )
         res = -1;
     else
         res = 0;
@@ -550,16 +559,16 @@ short ImpSvNumberInputScan::GetLogical( const String& rString )
 // Converts a string containing a month name (JAN, January) at nPos into the
 // month number (negative if abbreviated), returns 0 if nothing found
 
-short ImpSvNumberInputScan::GetMonth( const String& rString, xub_StrLen& nPos )
+short ImpSvNumberInputScan::GetMonth( const ::rtl::OUString& rString, xub_StrLen& nPos )
 {
     // #102136# The correct English form of month September abbreviated is
     // SEPT, but almost every data contains SEP instead.
-    static const String aSeptCorrect( RTL_CONSTASCII_USTRINGPARAM( "SEPT" ) );
-    static const String aSepShortened( RTL_CONSTASCII_USTRINGPARAM( "SEP" ) );
+    static const ::rtl::OUString aSeptCorrect( RTL_CONSTASCII_USTRINGPARAM( "SEPT" ) );
+    static const ::rtl::OUString aSepShortened( RTL_CONSTASCII_USTRINGPARAM( "SEP" ) );
 
     short res = 0;      // no month found
 
-    if (rString.Len() > nPos)                           // only if needed
+    if (rString.getLength() > nPos)                           // only if needed
     {
         if ( !bTextInitialized )
             InitText();
@@ -568,44 +577,44 @@ short ImpSvNumberInputScan::GetMonth( const String& rString, xub_StrLen& nPos 
)
         {
             if ( bScanGenitiveMonths && StringContains( pUpperGenitiveMonthText[i], rString, nPos 
) )
             {                                           // genitive full names first
-                nPos = nPos + pUpperGenitiveMonthText[i].Len();
+                nPos = nPos + pUpperGenitiveMonthText[i].getLength();
                 res = i+1;
                 break;  // for
             }
             else if ( bScanGenitiveMonths && StringContains( pUpperGenitiveAbbrevMonthText[i], 
rString, nPos ) )
             {                                           // genitive abbreviated
-                nPos = nPos + pUpperGenitiveAbbrevMonthText[i].Len();
+                nPos = nPos + pUpperGenitiveAbbrevMonthText[i].getLength();
                 res = sal::static_int_cast< short >(-(i+1)); // negative
                 break;  // for
             }
             else if ( bScanPartitiveMonths && StringContains( pUpperPartitiveMonthText[i], 
rString, nPos ) )
             {                                           // partitive full names
-                nPos = nPos + pUpperPartitiveMonthText[i].Len();
+                nPos = nPos + pUpperPartitiveMonthText[i].getLength();
                 res = i+1;
                 break;  // for
             }
             else if ( bScanPartitiveMonths && StringContains( pUpperPartitiveAbbrevMonthText[i], 
rString, nPos ) )
             {                                           // partitive abbreviated
-                nPos = nPos + pUpperPartitiveAbbrevMonthText[i].Len();
+                nPos = nPos + pUpperPartitiveAbbrevMonthText[i].getLength();
                 res = sal::static_int_cast< short >(-(i+1)); // negative
                 break;  // for
             }
             else if ( StringContains( pUpperMonthText[i], rString, nPos ) )
             {                                           // noun full names
-                nPos = nPos + pUpperMonthText[i].Len();
+                nPos = nPos + pUpperMonthText[i].getLength();
                 res = i+1;
                 break;  // for
             }
             else if ( StringContains( pUpperAbbrevMonthText[i], rString, nPos ) )
             {                                           // noun abbreviated
-                nPos = nPos + pUpperAbbrevMonthText[i].Len();
+                nPos = nPos + pUpperAbbrevMonthText[i].getLength();
                 res = sal::static_int_cast< short >(-(i+1)); // negative
                 break;  // for
             }
             else if ( i == 8 && pUpperAbbrevMonthText[i] == aSeptCorrect &&
                     StringContains( aSepShortened, rString, nPos ) )
             {                                           // #102136# SEPT/SEP
-                nPos = nPos + aSepShortened.Len();
+                nPos = nPos + aSepShortened.getLength();
                 res = sal::static_int_cast< short >(-(i+1)); // negative
                 break;  // for
             }
@@ -622,11 +631,11 @@ short ImpSvNumberInputScan::GetMonth( const String& rString, xub_StrLen& nPos 
)
 // Converts a string containing a DayOfWeek name (Mon, Monday) at nPos into the
 // DayOfWeek number + 1 (negative if abbreviated), returns 0 if nothing found
 
-int ImpSvNumberInputScan::GetDayOfWeek( const String& rString, xub_StrLen& nPos )
+int ImpSvNumberInputScan::GetDayOfWeek( const ::rtl::OUString& rString, xub_StrLen& nPos )
 {
     int res = 0;      // no day found
 
-    if (rString.Len() > nPos)                           // only if needed
+    if (rString.getLength() > nPos)                           // only if needed
     {
         if ( !bTextInitialized )
             InitText();
@@ -635,13 +644,13 @@ int ImpSvNumberInputScan::GetDayOfWeek( const String& rString, xub_StrLen& 
nPos
         {
             if ( StringContains( pUpperDayText[i], rString, nPos ) )
             {                                           // full names first
-                nPos = nPos + pUpperDayText[i].Len();
+                nPos = nPos + pUpperDayText[i].getLength();
                 res = i + 1;
                 break;  // for
             }
             if ( StringContains( pUpperAbbrevDayText[i], rString, nPos ) )
             {                                           // abbreviated
-                nPos = nPos + pUpperAbbrevDayText[i].Len();
+                nPos = nPos + pUpperAbbrevDayText[i].getLength();
                 res = -(i + 1);                         // negative
                 break;  // for
             }
@@ -659,12 +668,12 @@ int ImpSvNumberInputScan::GetDayOfWeek( const String& rString, xub_StrLen& 
nPos
 // '$'   => true
 // sonst => false
 
-bool ImpSvNumberInputScan::GetCurrency( const String& rString, xub_StrLen& nPos,
+bool ImpSvNumberInputScan::GetCurrency( const ::rtl::OUString& rString, xub_StrLen& nPos,
             const SvNumberformat* pFormat )
 {
-    if ( rString.Len() > nPos )
+    if ( rString.getLength() > nPos )
     {
-        if ( !aUpperCurrSymbol.Len() )
+        if ( !aUpperCurrSymbol.getLength() )
         {   // if no format specified the currency of the initialized formatter
             LanguageType eLang = (pFormat ? pFormat->GetLanguage() :
                 pFormatter->GetLanguage());
@@ -673,7 +682,7 @@ bool ImpSvNumberInputScan::GetCurrency( const String& rString, xub_StrLen& nPos,
         }
         if ( StringContains( aUpperCurrSymbol, rString, nPos ) )
         {
-            nPos = nPos + aUpperCurrSymbol.Len();
+            nPos = nPos + aUpperCurrSymbol.getLength();
             return true;
         }
         if ( pFormat )
@@ -681,7 +690,7 @@ bool ImpSvNumberInputScan::GetCurrency( const String& rString, xub_StrLen& nPos,
             String aSymbol, aExtension;
             if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) )
             {
-                if ( aSymbol.Len() <= rString.Len() - nPos )
+                if ( aSymbol.Len() <= rString.getLength() - nPos )
                 {
                     pFormatter->GetCharClass()->toUpper( aSymbol );
                     if ( StringContains( aSymbol, rString, nPos ) )
@@ -712,10 +721,10 @@ bool ImpSvNumberInputScan::GetCurrency( const String& rString, xub_StrLen& 
nPos,
 //  "PM"  => -1
 //  sonst =>  0
 
-bool ImpSvNumberInputScan::GetTimeAmPm( const String& rString, xub_StrLen& nPos )
+bool ImpSvNumberInputScan::GetTimeAmPm( const ::rtl::OUString& rString, xub_StrLen& nPos )
 {
 
-    if ( rString.Len() > nPos )
+    if ( rString.getLength() > nPos )
     {
         const CharClass* pChr = pFormatter->GetCharClass();
         const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
@@ -744,14 +753,14 @@ bool ImpSvNumberInputScan::GetTimeAmPm( const String& rString, xub_StrLen& 
nPos
 // ','   => true
 // sonst => false
 
-inline bool ImpSvNumberInputScan::GetDecSep( const String& rString, xub_StrLen& nPos )
+inline bool ImpSvNumberInputScan::GetDecSep( const ::rtl::OUString& rString, xub_StrLen& nPos )
 {
-    if ( rString.Len() > nPos )
+    if ( rString.getLength() > nPos )
     {
-        const String& rSep = pFormatter->GetNumDecimalSep();
-        if ( rString.Equals( rSep, nPos, rSep.Len() ) )
+        const ::rtl::OUString& rSep = pFormatter->GetNumDecimalSep();
+        if ( rString.match( rSep, nPos ) )
         {
-            nPos = nPos + rSep.Len();
+            nPos = nPos + rSep.getLength();
             return true;
         }
     }
@@ -762,14 +771,14 @@ inline bool ImpSvNumberInputScan::GetDecSep( const String& rString, 
xub_StrLen&
 //---------------------------------------------------------------------------
 // read a hundredth seconds separator
 
-inline bool ImpSvNumberInputScan::GetTime100SecSep( const String& rString, xub_StrLen& nPos )
+inline bool ImpSvNumberInputScan::GetTime100SecSep( const ::rtl::OUString& rString, xub_StrLen& 
nPos )
 {
-    if ( rString.Len() > nPos )
+    if ( rString.getLength() > nPos )
     {
-        const String& rSep = pFormatter->GetLocaleData()->getTime100SecSep();
-        if ( rString.Equals( rSep, nPos, rSep.Len() ) )
+        const ::rtl::OUString& rSep = pFormatter->GetLocaleData()->getTime100SecSep();
+        if ( rString.match( rSep, nPos ) )
         {
-            nPos = nPos + rSep.Len();
+            nPos = nPos + rSep.getLength();
             return true;
         }
     }
@@ -786,10 +795,10 @@ inline bool ImpSvNumberInputScan::GetTime100SecSep( const String& rString, 
xub_S
 // '('   => -1, nNegCheck = 1
 // sonst =>  0
 
-int ImpSvNumberInputScan::GetSign( const String& rString, xub_StrLen& nPos )
+int ImpSvNumberInputScan::GetSign( const ::rtl::OUString& rString, xub_StrLen& nPos )
 {
-    if (rString.Len() > nPos)
-        switch (rString.GetChar(nPos))
+    if (rString.getLength() > nPos)
+        switch (rString[nPos])
         {
             case '+':
                 nPos++;
@@ -816,10 +825,10 @@ int ImpSvNumberInputScan::GetSign( const String& rString, xub_StrLen& nPos )
 // '-'   => -1
 // sonst =>  0
 
-short ImpSvNumberInputScan::GetESign( const String& rString, xub_StrLen& nPos )
+short ImpSvNumberInputScan::GetESign( const ::rtl::OUString& rString, xub_StrLen& nPos )
 {
-    if (rString.Len() > nPos)
-        switch (rString.GetChar(nPos))
+    if (rString.getLength() > nPos)
+        switch (rString[nPos])
         {
             case '+':
                 nPos++;
@@ -885,7 +894,7 @@ void ImpSvNumberInputScan::GetTimeRef(
     if (nDecPos == 2 && (nAnz == 3 || nAnz == 2))   // 20:45.5 or 45.5
         nHour = 0;
     else if (nIndex - nStartIndex < nAnz)
-        nHour   = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
+        nHour   = (sal_uInt16) sStrArray[nNums[nIndex++]].toInt32();
     else
     {
         nHour = 0;
@@ -894,9 +903,9 @@ void ImpSvNumberInputScan::GetTimeRef(
     if (nDecPos == 2 && nAnz == 2)                  // 45.5
         nMinute = 0;
     else if (nIndex - nStartIndex < nAnz)
-        nMinute = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
+        nMinute = (sal_uInt16) sStrArray[nNums[nIndex++]].toInt32();
     if (nIndex - nStartIndex < nAnz)
-        nSecond = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
+        nSecond = (sal_uInt16) sStrArray[nNums[nIndex++]].toInt32();
     if (nIndex - nStartIndex < nAnz)
         fSecond100 = StringToDouble( sStrArray[nNums[nIndex]], true );
     if (nAmPm == -1 && nHour != 12)             // PM
@@ -918,9 +927,9 @@ sal_uInt16 ImpSvNumberInputScan::ImplGetDay( sal_uInt16 nIndex )
 {
     sal_uInt16 nRes = 0;
 
-    if (sStrArray[nNums[nIndex]].Len() <= 2)
+    if (sStrArray[nNums[nIndex]].getLength() <= 2)
     {
-        sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
+        sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].toInt32();
         if (nNum <= 31)
             nRes = nNum;
     }
@@ -937,9 +946,9 @@ sal_uInt16 ImpSvNumberInputScan::ImplGetMonth( sal_uInt16 nIndex )
     // preset invalid month number
     sal_uInt16 nRes = pFormatter->GetCalendar()->getNumberOfMonthsInYear();
 
-    if (sStrArray[nNums[nIndex]].Len() <= 2)
+    if (sStrArray[nNums[nIndex]].getLength() <= 2)
     {
-        sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
+        sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].toInt32();
         if ( 0 < nNum && nNum <= nRes )
             nRes = nNum - 1;        // zero based for CalendarFieldIndex::MONTH
     }
@@ -957,9 +966,9 @@ sal_uInt16 ImpSvNumberInputScan::ImplGetYear( sal_uInt16 nIndex )
 {
     sal_uInt16 nYear = 0;
 
-    if (sStrArray[nNums[nIndex]].Len() <= 4)
+    if (sStrArray[nNums[nIndex]].getLength() <= 4)
     {
-        nYear = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
+        nYear = (sal_uInt16) sStrArray[nNums[nIndex]].toInt32();
         nYear = SvNumberFormatter::ExpandTwoDigitYear( nYear, nYear2000 );
     }
 
@@ -973,7 +982,7 @@ bool ImpSvNumberInputScan::MayBeIso8601()
     if (nMayBeIso8601 == 0)
     {
         if (nAnzNums >= 3 && nNums[0] < nAnzStrings &&
-                sStrArray[nNums[0]].ToInt32() > 31)
+                sStrArray[nNums[0]].toInt32() > 31)
             nMayBeIso8601 = 1;
         else
             nMayBeIso8601 = 2;
@@ -1018,7 +1027,7 @@ bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
     for ( int nTryOrder = 1; nTryOrder <= nFormatOrder; nTryOrder++ )
     {
         pCal->setGregorianDateTime( Date( Date::SYSTEM ) );       // today
-        String aOrgCalendar;        // empty => not changed yet
+        ::rtl::OUString aOrgCalendar;        // empty => not changed yet
         DateFormat DateFmt;
         bool bFormatTurn;
         switch ( eEDF )
@@ -1388,7 +1397,7 @@ input for the following reasons:
         else
             res = false;
 
-        if ( aOrgCalendar.Len() )
+        if ( aOrgCalendar.getLength() )
             pCal->loadCalendar( aOrgCalendar, pLoc->getLocale() );  // restore calendar
 
 #if NF_TEST_CALENDAR
@@ -1487,7 +1496,7 @@ input for the following reasons:
 // Alles weg => true
 // sonst     => false
 
-bool ImpSvNumberInputScan::ScanStartString( const String& rString,
+bool ImpSvNumberInputScan::ScanStartString( const ::rtl::OUString& rString,
         const SvNumberformat* pFormat )
 {
     xub_StrLen nPos = 0;
@@ -1501,7 +1510,7 @@ bool ImpSvNumberInputScan::ScanStartString( const String& rString,
         SkipBlanks(rString, nPos);
 
     // #102371# match against format string only if start string is not a sign character
-    if ( nMatchedAllStrings && !(nSign && rString.Len() == 1) )
+    if ( nMatchedAllStrings && !(nSign && rString.getLength() == 1) )
     {   // Match against format in any case, so later on for a "x1-2-3" input
         // we may distinguish between a xy-m-d (or similar) date and a x0-0-0
         // format. No sign detection here!
@@ -1544,11 +1553,11 @@ bool ImpSvNumberInputScan::ScanStartString( const String& rString,
             if ( nDayOfWeek )
             {   // day of week is just parsed away
                 eScannedType = NUMBERFORMAT_DATE;       // !!! it IS a date !!!
-                if ( nPos < rString.Len() )
+                if ( nPos < rString.getLength() )
                 {
                     if ( nDayOfWeek < 0 )
                     {   // abbreviated
-                        if ( rString.GetChar( nPos ) == '.' )
+                        if ( rString[ nPos ] == '.' )
                             ++nPos;
                     }
                     else
@@ -1571,13 +1580,13 @@ bool ImpSvNumberInputScan::ScanStartString( const String& rString,
     }
 
     // skip any trailing '-' or '/' chars
-    if (nPos < rString.Len())
+    if (nPos < rString.getLength())
     {
         while (SkipChar ('-', rString, nPos) || SkipChar ('/', rString, nPos)) {
             // do nothing
         }
     }
-    if (nPos < rString.Len())                       // not everything consumed
+    if (nPos < rString.getLength())                       // not everything consumed
     {
         // Does input StartString equal StartString of format?
         // This time with sign detection!
@@ -1596,7 +1605,7 @@ bool ImpSvNumberInputScan::ScanStartString( const String& rString,
 // Alles weg => true
 // sonst     => false
 
-bool ImpSvNumberInputScan::ScanMidString( const String& rString,
+bool ImpSvNumberInputScan::ScanMidString( const ::rtl::OUString& rString,
         sal_uInt16 nStringPos, const SvNumberformat* pFormat )
 {
     xub_StrLen nPos = 0;
@@ -1673,9 +1682,9 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
     }
 
     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
-    const String& rDate = pFormatter->GetDateSep();
-    const String& rTime = pLoc->getTimeSep();
-    sal_Unicode cTime = rTime.GetChar(0);
+    const ::rtl::OUString& rDate = pFormatter->GetDateSep();
+    const ::rtl::OUString& rTime = pLoc->getTimeSep();
+    sal_Unicode cTime = rTime[0];
     SkipBlanks(rString, nPos);
     if (                      SkipString(rDate, rString, nPos)  // 10., 10-, 10/
         || ((cTime != '.') && SkipChar('.',   rString, nPos))   // TRICKY:
@@ -1773,7 +1782,7 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
             nTimePos = nStringPos + 1;
     }
 
-    if (nPos < rString.Len())
+    if (nPos < rString.getLength())
     {
         switch (eScannedType)
         {
@@ -1784,8 +1793,8 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
                     if (SkipString( pLoc->getLongDateDaySep(), rString, nPos ))
                         SkipBlanks( rString, nPos );
                 }
-                else if (nStringPos == 5 && nPos == 0 && rString.Len() == 1 &&
-                        rString.GetChar(0) == 'T' && MayBeIso8601())
+                else if (nStringPos == 5 && nPos == 0 && rString.getLength() == 1 &&
+                        rString[0] == 'T' && MayBeIso8601())
                 {
                     // ISO 8601 combined date and time, yyyy-mm-ddThh:mm
                     ++nPos;
@@ -1793,11 +1802,11 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
                 break;
 #if NF_RECOGNIZE_ISO8601_TIMEZONES
             case NUMBERFORMAT_DATETIME:
-                if (nPos == 0 && rString.Len() == 1 && nStringPos >= 9 &&
+                if (nPos == 0 && rString.getLength() == 1 && nStringPos >= 9 &&
                         MayBeIso8601())
                 {
                     // ISO 8601 timezone offset
-                    switch (rString.GetChar(0))
+                    switch (rString[0])
                     {
                         case '+':
                         case '-':
@@ -1822,7 +1831,7 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
         }
     }
 
-    if (nPos < rString.Len())                       // not everything consumed?
+    if (nPos < rString.getLength())                       // not everything consumed?
     {
         if ( nMatchedAllStrings & ~nMatchedVirgin )
             eScannedType = eOldScannedType;
@@ -1841,7 +1850,7 @@ bool ImpSvNumberInputScan::ScanMidString( const String& rString,
 // Alles weg => true
 // sonst     => false
 
-bool ImpSvNumberInputScan::ScanEndString( const String& rString,
+bool ImpSvNumberInputScan::ScanEndString( const ::rtl::OUString& rString,
         const SvNumberformat* pFormat )
 {
     xub_StrLen nPos = 0;
@@ -1932,8 +1941,8 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
     }
 
     const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
-    const String& rDate = pFormatter->GetDateSep();
-    const String& rTime = pLoc->getTimeSep();
+    const ::rtl::OUString& rDate = pFormatter->GetDateSep();
+    const ::rtl::OUString& rTime = pLoc->getTimeSep();
     if ( SkipString(rTime, rString, nPos) )         // 10:
     {
         if (nDecPos)                                // already , => error
@@ -1955,7 +1964,7 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
             nTimePos = nAnzStrings;
     }
 
-    sal_Unicode cTime = rTime.GetChar(0);
+    sal_Unicode cTime = rTime[0];
     if (                      SkipString(rDate, rString, nPos)  // 10., 10-, 10/
         || ((cTime != '.') && SkipChar('.',   rString, nPos))   // TRICKY:
         || ((cTime != '/') && SkipChar('/',   rString, nPos))   // short boolean
@@ -2031,25 +2040,25 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
             return MatchedReturn();
     }
 
-    if ( nPos < rString.Len() &&
+    if ( nPos < rString.getLength() &&
             (eScannedType == NUMBERFORMAT_DATE
             || eScannedType == NUMBERFORMAT_DATETIME) )
     {   // day of week is just parsed away
         xub_StrLen nOldPos = nPos;
-        const String& rSep = pFormatter->GetLocaleData()->getLongDateDayOfWeekSep();
+        const ::rtl::OUString& rSep = pFormatter->GetLocaleData()->getLongDateDayOfWeekSep();
         if ( StringContains( rSep, rString, nPos ) )
         {
-            nPos = nPos + rSep.Len();
+            nPos = nPos + rSep.getLength();
             SkipBlanks(rString, nPos);
         }
         int nDayOfWeek = GetDayOfWeek( rString, nPos );
         if ( nDayOfWeek )
         {
-            if ( nPos < rString.Len() )
+            if ( nPos < rString.getLength() )
             {
                 if ( nDayOfWeek < 0 )
                 {   // short
-                    if ( rString.GetChar( nPos ) == '.' )
+                    if ( rString[ nPos ] == '.' )
                         ++nPos;
                 }
                 SkipBlanks(rString, nPos);
@@ -2061,14 +2070,14 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
 
 #if NF_RECOGNIZE_ISO8601_TIMEZONES
     if (nPos == 0 && eScannedType == NUMBERFORMAT_DATETIME &&
-            rString.Len() == 1 && rString.GetChar(0) == 'Z' && MayBeIso8601())
+            rString.getLength() == 1 && rString[0] == 'Z' && MayBeIso8601())
     {
         // ISO 8601 timezone UTC yyyy-mm-ddThh:mmZ
         ++nPos;
     }
 #endif
 
-    if (nPos < rString.Len())                       // everything consumed?
+    if (nPos < rString.getLength())                       // everything consumed?
     {
         // does input EndString equal EndString in Format?
         if ( !ScanStringNumFor( rString, nPos, pFormat, 0xFFFF ) )
@@ -2080,7 +2089,7 @@ bool ImpSvNumberInputScan::ScanEndString( const String& rString,
 
 
 bool ImpSvNumberInputScan::ScanStringNumFor(
-        const String& rString,          // String to scan
+        const ::rtl::OUString& rString,          // String to scan
         xub_StrLen nPos,                // Position until which was consumed
         const SvNumberformat* pFormat,  // The format to match
         sal_uInt16 nString,                 // Substring of format, 0xFFFF => last
@@ -2168,6 +2177,209 @@ bool ImpSvNumberInputScan::ScanStringNumFor(
     return true;
 }
 
+namespace {
+    struct make_double_impl
+    {
+        template <typename Arg1, typename Arg2>
+        struct result
+        {
+            typedef double type;
+        };
+
+        template <typename Arg1, typename Arg2>
+        double operator()(Arg1 ip, Arg2 fp) const
+        {
+            return ip + ::rtl::math::pow10Exp(fp, -ceil(log10(fp)));
+        }
+    };
+
+    boost::phoenix::function<make_double_impl> make_double;
+
+    struct make_date_impl
+    {
+        template <typename Arg1, typename Arg2>
+        struct result
+        {
+            typedef double type;
+        };
+
+        template <typename Arg1, typename Arg2>
+        double operator()(Arg1 pNullDate, Arg2 pCal) const
+        {
+            const double fDiff = DateTime(*pNullDate) - pCal->getEpochStart();
+            double fDays = ::rtl::math::approxFloor( pCal->getLocalDateTime() );
+            fDays -= fDiff;
+            return fDays;
+        }
+    };
+
+    boost::phoenix::function<make_date_impl> make_date;
+
+    struct reset_date_impl
+    {
+        template <typename Arg1>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename Arg1>
+        void operator()(Arg1 pCal) const
+        {
+            using namespace ::com::sun::star::i18n;
+            pCal->setGregorianDateTime( Date( Date::SYSTEM ) ); // today
+            // For incomplete dates, always assume first day of month if not specified.
+            pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
+        }
+    };
+
+    boost::phoenix::function<reset_date_impl> reset_date;
+
+}
+
+
+template <typename Iterator>
+struct ImpSvNumberInputScan::number_grammar : qi::grammar<Iterator, enc::space_type>
+{
+    // Did not find a CharClass::isSpace so use spirit's notion.
+    // TODO: should we use space, white_space, ...?
+    //       Maybe language-dependent?
+    typedef enc::space_type Skipper;
+    ImpSvNumberInputScan &parent;
+    double &fOutNumber;
+    number_grammar( ImpSvNumberInputScan &_parent, double &_fOutNumber ) :
+        number_grammar::base_type(start, "LibreOffice number parser"),
+        parent(_parent),
+        fOutNumber(_fOutNumber),
+        pCal( parent.pFormatter->GetCalendar() )
+    {
+        using namespace qi;
+        using boost::phoenix::ref;
+
+        if ( !parent.bTextInitialized )
+            parent.InitText();
+
+        const ImpSvNumberformatScan* pFS = parent.pFormatter->GetFormatScanner();
+
+        ::rtl::OUString sTrue (pFS->GetTrueString());
+        ::rtl::OUString sFalse(pFS->GetTrueString());
+        rBoolean =   (qi::lit(sTrue)  >> qi::eoi) [ ref(fOutNumber) =  1, ref(parent.eScannedType) 
= NUMBERFORMAT_LOGICAL ]
+                   | (qi::lit(sFalse) >> qi::eoi) [ ref(fOutNumber) = -1, ref(parent.eScannedType) 
= NUMBERFORMAT_LOGICAL ];
+        rInteger =   (qi::int_ >> qi::eoi) [ ref(fOutNumber) = qi::_1, ref(parent.eScannedType) = 
NUMBERFORMAT_NUMBER ];
+        ::rtl::OUString sDecSep(parent.pFormatter->GetNumDecimalSep());
+        rFloat   =   ( qi::int_ >> qi::lit(sDecSep) >> qi::uint_ >> qi::eoi)
+                         [ ref(fOutNumber) = make_double(qi::_1, qi::_2),
+                           ref(parent.eScannedType) = NUMBERFORMAT_NUMBER ];
+        make_rDate();
+
+        start =   rBoolean
+                | rInteger
+                | rFloat
+                | rDate;
+
+#if 0
+        start.name("start");
+        debug ( start );
+        rBoolean.name("rBoolean");
+        debug( rBoolean );
+        rDate.name("rDate");
+        debug( rDate );
+        rInteger.name("rInteger");
+        debug( rInteger );
+        rFloat.name("rFloat");
+        debug( rFloat );
+#endif
+    };
+
+    void make_rDate()
+    {
+        using namespace qi;
+        using boost::phoenix::ref;
+        using boost::phoenix::bind;
+        using namespace ::com::sun::star::i18n;
+
+        const int nDays = pCal->getNumberOfDaysInWeek();
+        const rtl::OUString * const dayEnd = parent.pUpperDayText + nDays;
+        for ( const rtl::OUString *pDay = parent.pUpperDayText, *pAbbrDay = 
parent.pUpperAbbrevDayText;
+              pDay < dayEnd;
+              ++pDay, ++pAbbrDay )
+        {
+            dow.add(*pDay)(*pAbbrDay);
+        }
+
+        const int nMonths =  pCal->getNumberOfMonthsInYear();
+        for ( int i = 0; i < nMonths; ++i)
+        {
+            month.add(parent.pUpperMonthText[i], i)(parent.pUpperAbbrevMonthText[i],i);
+        }
+
+        // TODO: how is this internationalised? It seems not to be...
+        rDateSep = omit[unicode::char_("-/")];
+
+        // yyyy-mm-dd
+        rISO8601 =
+            int_ [ _pass = _1 > 31,
+                         bind(&CalendarWrapper::setValue, ref(pCal), CalendarFieldIndex::YEAR, _1 
) ]
+            >> -rDateSep
+            >> uint_ [ _pass = _1 <= nMonths,
+                       bind(&CalendarWrapper::setValue, ref(pCal), CalendarFieldIndex::MONTH, _1) ]
+            >> -rDateSep
+            >> uint_ [ bind(&CalendarWrapper::setValue, ref(pCal), 
CalendarFieldIndex::DAY_OF_MONTH, _1 ) ];
+
+        rDayOfMonth = ushort_ [ bind(&CalendarWrapper::setValue, ref(pCal), 
CalendarFieldIndex::DAY_OF_MONTH, _1 ) ];
+        rMonth = ushort_ [ _pass = _1 <= nMonths,
+                           bind(&CalendarWrapper::setValue, ref(pCal), CalendarFieldIndex::MONTH, 
_1 - 1 ) ]
+            | month      [ bind(&CalendarWrapper::setValue, ref(pCal), CalendarFieldIndex::MONTH, 
_1 ) ];
+        // TODO: with the current parser "7" is 2007, not year 7.
+        //       See what the exact rule is and do the same.
+        rYear = int_ [ bind(&CalendarWrapper::setValue, ref(pCal), CalendarFieldIndex::YEAR, _1 ) 
];
+        // TODO: this is not (fully) internationalised: some languages have MDY, others DMY
+        if ( true /* DMY format */ )
+            rPlainDate =
+                  ( eps [ reset_date(pCal) ] >> rDayOfMonth >> -rDateSep >> rMonth >> eoi )
+                | ( eps [ reset_date(pCal) ] >> rMonth >> -rDateSep >> rYear >> eoi )
+                | ( eps [ reset_date(pCal) ] >> rDayOfMonth >> -rDateSep >> rMonth  >> -rDateSep 
rYear >> eoi );
+        else /* MDY format */
+            rPlainDate =
+                  ( eps [ reset_date(pCal) ] >> rMonth >> -rDateSep >> rDayOfMonth >> eoi )
+                | ( eps [ reset_date(pCal) ] >> rMonth >> -rDateSep >> rYear >> eoi )
+                | ( eps [ reset_date(pCal) ] >> rMonth >> -rDateSep >> rDayOfMonth >> -rDateSep >> 
rYear >> eoi );
+
+#if 0
+        rISO8601.name("rISO8601");
+        debug(rISO8601);
+        rPlainDate.name("rPlainDate");
+        debug(rPlainDate);
+        rDayOfMonth.name("rDOM");
+        debug(rDayOfMonth);
+        rMonth.name("rMonth");
+        debug(rMonth);
+        rYear.name("rYear");
+        debug(rYear);
+#endif
+
+        rDate = -dow >>
+            (   ( eps [ reset_date(pCal) ] >> rISO8601 >> eoi )
+              | rPlainDate )
+            >> eoi [ ref(parent.eScannedType) = NUMBERFORMAT_DATE,
+                     ref(fOutNumber) =  make_date(parent.pNullDate, ref(pCal)) ];
+    }
+
+    CalendarWrapper *pCal;
+    qi::rule<Iterator, Skipper> start;
+    qi::rule<Iterator, Skipper> rBoolean;
+    qi::rule<Iterator, Skipper> rDate;
+    qi::rule<Iterator, Skipper> rInteger;
+    qi::rule<Iterator, Skipper> rFloat;
+    qi::symbols <sal_uInt32, qi::unused_type> dow;   // day of week
+    qi::symbols <sal_uInt32, unsigned short>  month; // month as string
+    qi::rule<Iterator, Skipper> rDateSep;
+    qi::rule<Iterator, Skipper> rISO8601;
+    qi::rule<Iterator, Skipper> rPlainDate;
+    qi::rule<Iterator, Skipper> rMonth;
+    qi::rule<Iterator, Skipper> rYear;
+    qi::rule<Iterator, Skipper> rDayOfMonth;
+};
 
 //---------------------------------------------------------------------------
 //      IsNumberFormatMain
@@ -2176,11 +2388,22 @@ bool ImpSvNumberInputScan::ScanStringNumFor(
 // Else text => return false
 
 bool ImpSvNumberInputScan::IsNumberFormatMain(
-        const String& rString,                  // string to be analyzed
-        double& ,                               // OUT: result as number, if possible
+        const ::rtl::OUString& rString,                  // string to be analyzed
+        double& fOutNumber,                       // OUT: result as number, if possible
         const SvNumberformat* pFormat )         // maybe number format set to match against
 {
     Reset();
+
+    std::cerr << "***** DBG before parse ****** r=(undefined)\tfOutNumber=" << fOutNumber << 
"\teScannedType=" << eScannedType << std::endl;
+    std::cerr << "To parse: '" << ::rtl::OUStringToOString( rString, RTL_TEXTENCODING_UTF8 
).getStr() << "'" << std::endl;
+
+    bool r = qi::phrase_parse(rString.begin(),
+                              rString.end(),
+                              number_grammar<rtl::OUString::const_iterator>(*this, fOutNumber),
+                              enc::space);
+
+    std::cerr << "***** DBG after  parse ****** r=" << r << "\tfOutNumber=" << fOutNumber << 
"\teScannedType=" << eScannedType << std::endl;
+
     NumberStringDivision( rString );            // breakdown into strings and numbers
     if (nAnzStrings >= SV_MAX_ANZ_INPUT_STRINGS) // too many elements
         return false;                           // Njet, Nope, ...
@@ -2191,9 +2414,8 @@ bool ImpSvNumberInputScan::IsNumberFormatMain(
         {
             // Here we may change the original, we don't need it anymore.
             // This saves copies and ToUpper() in GetLogical() and is faster.
-            String& rStrArray = sStrArray[0];
-            rStrArray.EraseTrailingChars( ' ' );
-            rStrArray.EraseLeadingChars( ' ' );
+            ::rtl::OUString& rStrArray = sStrArray[0];
+            rStrArray.trim();
             nLogical = GetLogical( rStrArray );
             if ( nLogical )
             {
@@ -2220,7 +2442,7 @@ bool ImpSvNumberInputScan::IsNumberFormatMain(
                 if (eSetType == NUMBERFORMAT_FRACTION)  // Fraction 1 = 1/1
                 {
                     if (i >= nAnzStrings ||     // no end string nor decimal separator
-                        sStrArray[i] == pFormatter->GetNumDecimalSep())
+                        sStrArray[i] == ::rtl::OUString(pFormatter->GetNumDecimalSep()))
                     {
                         eScannedType = NUMBERFORMAT_FRACTION;
                         nMatchedAllStrings &= ~nMatchedVirgin;
@@ -2241,7 +2463,7 @@ bool ImpSvNumberInputScan::IsNumberFormatMain(
                     eScannedType == NUMBERFORMAT_UNDEFINED &&   // not date or currency
                     nDecPos == 0 &&             // no previous decimal separator
                     (i >= nAnzStrings ||        // no end string nor decimal separator
-                        sStrArray[i] == pFormatter->GetNumDecimalSep())
+                     sStrArray[i] == ::rtl::OUString(pFormatter->GetNumDecimalSep()))
                 )
                 {
                     eScannedType = NUMBERFORMAT_FRACTION;
@@ -2452,8 +2674,8 @@ void ImpSvNumberInputScan::InitText()
     ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > xElems
         = pCal->getMonths();
     nElems = xElems.getLength();
-    pUpperMonthText = new String[nElems];
-    pUpperAbbrevMonthText = new String[nElems];
+    pUpperMonthText = new ::rtl::OUString[nElems];
+    pUpperAbbrevMonthText = new ::rtl::OUString[nElems];
     for ( j=0; j<nElems; j++ )
     {
         pUpperMonthText[j] = pChrCls->upper( xElems[j].FullName );
@@ -2465,8 +2687,8 @@ void ImpSvNumberInputScan::InitText()
     xElems = pCal->getGenitiveMonths();
     bScanGenitiveMonths = (nElems != xElems.getLength());
     nElems = xElems.getLength();
-    pUpperGenitiveMonthText = new String[nElems];
-    pUpperGenitiveAbbrevMonthText = new String[nElems];
+    pUpperGenitiveMonthText = new ::rtl::OUString[nElems];
+    pUpperGenitiveAbbrevMonthText = new ::rtl::OUString[nElems];
     for ( j=0; j<nElems; j++ )
     {
         pUpperGenitiveMonthText[j] = pChrCls->upper( xElems[j].FullName );
@@ -2482,8 +2704,8 @@ void ImpSvNumberInputScan::InitText()
     xElems = pCal->getPartitiveMonths();
     bScanPartitiveMonths = (nElems != xElems.getLength());
     nElems = xElems.getLength();
-    pUpperPartitiveMonthText = new String[nElems];
-    pUpperPartitiveAbbrevMonthText = new String[nElems];
+    pUpperPartitiveMonthText = new ::rtl::OUString[nElems];
+    pUpperPartitiveAbbrevMonthText = new ::rtl::OUString[nElems];
     for ( j=0; j<nElems; j++ )
     {
         pUpperPartitiveMonthText[j] = pChrCls->upper( xElems[j].FullName );
@@ -2498,8 +2720,8 @@ void ImpSvNumberInputScan::InitText()
     delete [] pUpperAbbrevDayText;
     xElems = pCal->getDays();
     nElems = xElems.getLength();
-    pUpperDayText = new String[nElems];
-    pUpperAbbrevDayText = new String[nElems];
+    pUpperDayText = new ::rtl::OUString[nElems];
+    pUpperAbbrevDayText = new ::rtl::OUString[nElems];
     for ( j=0; j<nElems; j++ )
     {
         pUpperDayText[j] = pChrCls->upper( xElems[j].FullName );
@@ -2526,7 +2748,12 @@ void ImpSvNumberInputScan::ChangeIntl()
                           cDecSep == '.' ||
                           cDecSep == pFormatter->GetDateSep().GetChar(0) );
     bTextInitialized = false;
-    aUpperCurrSymbol.Erase();
+    aUpperCurrSymbol = ::rtl::OUString();
+
+    namespace enc = boost::spirit::unicode;
+    using enc::string;
+    using boost::phoenix::ref;
+
 }
 
 
@@ -2551,19 +2778,19 @@ void ImpSvNumberInputScan::ChangeNullDate(
 // => does rString represent a number (also date, time et al)
 
 bool ImpSvNumberInputScan::IsNumberFormat(
-        const String& rString,                  // string to be analyzed
+        const ::rtl::OUString& rString,                  // string to be analyzed
         short& F_Type,                          // IN: old type, OUT: new type
         double& fOutNumber,                     // OUT: number if convertable
         const SvNumberformat* pFormat )         // maybe a number format to match against
 {
-    String sResString;
-    String aString;
+    ::rtl::OUString sResString;
+    ::rtl::OUString aString;
     bool res;                                   // return value
     eSetType = F_Type;                          // old type set
 
-    if ( !rString.Len() )
+    if ( !rString.getLength() )
         res = false;
-    else if (rString.Len() > 308)               // arbitrary
+    else if (rString.getLength() > 308)               // arbitrary
         res = false;
     else
     {
@@ -2713,15 +2940,15 @@ bool ImpSvNumberInputScan::IsNumberFormat(
             case NUMBERFORMAT_DEFINED:          // if no category detected handle as number
             {
                 if ( nDecPos == 1 )                         // . at start
-                    sResString.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "0." ) );
+                    sResString = ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM( "0." ) );
                 else
-                    sResString.Erase();
+                    sResString = ::rtl::OUString();
                 sal_uInt16 k;
                 for ( k = 0; k <= nThousand; k++)
                     sResString += sStrArray[nNums[k]];  // integer part
                 if ( nDecPos == 2 && k < nAnzNums )     // . somewhere
                 {
-                    sResString += '.';
+                    sResString += ::rtl::OUString('.');
                     sal_uInt16 nStop = (eScannedType == NUMBERFORMAT_SCIENTIFIC ?
                             nAnzNums-1 : nAnzNums);
                     for ( ; k < nStop; k++)
@@ -2732,9 +2959,9 @@ bool ImpSvNumberInputScan::IsNumberFormat(
                     fOutNumber = StringToDouble(sResString);
                 else
                 {                                           // append exponent
-                    sResString += 'E';
+                    sResString += ::rtl::OUString('E');
                     if ( nESign == -1 )
-                        sResString += '-';
+                        sResString += ::rtl::OUString('-');
                     sResString += sStrArray[nNums[nAnzNums-1]];
                     rtl_math_ConversionStatus eStatus;
                     fOutNumber = ::rtl::math::stringToDouble(
diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx
index 9c557b7..effe65d 100644
--- a/svl/source/numbers/zforfind.hxx
+++ b/svl/source/numbers/zforfind.hxx
@@ -29,7 +29,9 @@
 #ifndef _ZFORFIND_HXX
 #define _ZFORFIND_HXX
 
-#include <tools/string.hxx>
+#include <rtl/string.hxx>
+#define BOOST_SPIRIT_UNICODE
+#include <boost/spirit/include/qi_rule.hpp>
 
 class Date;
 class SvNumberformat;
@@ -43,6 +45,8 @@ public:
     ImpSvNumberInputScan( SvNumberFormatter* pFormatter );
     ~ImpSvNumberInputScan();
 
+    template <typename Iterator> struct number_grammar;
+
 /*!*/   void ChangeIntl();                      // MUST be called if language changes
 
     /// set reference date for offset calculation
@@ -53,7 +57,7 @@ public:
 
     /// convert input string to number
     bool IsNumberFormat(
-            const String& rString,              /// input string
+            const rtl::OUString& rString,              /// input string
             short& F_Type,                      /// format type (in + out)
             double& fOutNumber,                 /// value determined (out)
             const SvNumberformat* pFormat = NULL    /// optional a number format to which compare 
against
@@ -75,21 +79,21 @@ public:
 
 private:
     SvNumberFormatter*  pFormatter;
-    String* pUpperMonthText;                    // Array of month names, uppercase
-    String* pUpperAbbrevMonthText;              // Array of month names, abbreviated, uppercase
-    String* pUpperGenitiveMonthText;            // Array of genitive month names, uppercase
-    String* pUpperGenitiveAbbrevMonthText;      // Array of genitive month names, abbreviated, 
uppercase
-    String* pUpperPartitiveMonthText;           // Array of partitive month names, uppercase
-    String* pUpperPartitiveAbbrevMonthText;     // Array of partitive month names, abbreviated, 
uppercase
-    String* pUpperDayText;                      // Array of day of week names, uppercase
-    String* pUpperAbbrevDayText;                // Array of day of week names, abbreviated, 
uppercase
-    String  aUpperCurrSymbol;                   // Currency symbol, uppercase
+    rtl::OUString* pUpperMonthText;                    // Array of month names, uppercase
+    rtl::OUString* pUpperAbbrevMonthText;              // Array of month names, abbreviated, 
uppercase
+    rtl::OUString* pUpperGenitiveMonthText;            // Array of genitive month names, uppercase
+    rtl::OUString* pUpperGenitiveAbbrevMonthText;      // Array of genitive month names, 
abbreviated, uppercase
+    rtl::OUString* pUpperPartitiveMonthText;           // Array of partitive month names, uppercase
+    rtl::OUString* pUpperPartitiveAbbrevMonthText;     // Array of partitive month names, 
abbreviated, uppercase
+    rtl::OUString* pUpperDayText;                      // Array of day of week names, uppercase
+    rtl::OUString* pUpperAbbrevDayText;                // Array of day of week names, abbreviated, 
uppercase
+    rtl::OUString  aUpperCurrSymbol;                   // Currency symbol, uppercase
     bool    bTextInitialized;                   // Whether days and months are initialized
     bool    bScanGenitiveMonths;                // Whether to scan an input for genitive months
     bool    bScanPartitiveMonths;               // Whether to scan an input for partitive months
     Date* pNullDate;                            // 30Dec1899
                                                 // Variables for provisional results:
-    String sStrArray[SV_MAX_ANZ_INPUT_STRINGS]; // Array of scanned substrings
+    rtl::OUString sStrArray[SV_MAX_ANZ_INPUT_STRINGS]; // Array of scanned substrings
     bool       IsNum[SV_MAX_ANZ_INPUT_STRINGS]; // Whether a substring is numeric
     sal_uInt16 nNums[SV_MAX_ANZ_INPUT_STRINGS]; // Sequence of offsets to numeric strings
     sal_uInt16 nAnzStrings;                     // Total count of scanned substrings
@@ -131,6 +135,8 @@ private:
     sal_uInt16  nTimezonePos;                   // Index of timezone separator (+1)
     sal_uInt8    nMayBeIso8601;                 // 0:=dontknowyet, 1:=yes, 2:=no
 
+    boost::spirit::qi::rule< sal_Unicode*, void() > prBool;
+
 #ifdef _ZFORFIND_CXX        // methods private to implementation
     void Reset();                               // Reset all variables before start of analysis
 
@@ -142,19 +148,19 @@ private:
     // If bForceFraction==true the string is taken to be the fractional part
     // of 0.1234 without the leading 0. (thus being just "1234").
     double StringToDouble(
-            const String& rStr,
+            const rtl::OUString& rStr,
             bool bForceFraction = false );
 
     bool NextNumberStringSymbol(                // Next number/string symbol
             const sal_Unicode*& pStr,
-            String& rSymbol );
+            rtl::OUString& rSymbol );
 
     bool SkipThousands(                         // Concatenate ,000,23 blocks
             const sal_Unicode*& pStr,           // in input to 000123
-            String& rSymbol );
+            rtl::OUString& rSymbol );
 
     void NumberStringDivision(                  // Divide numbers/strings into
-            const String& rString );            // arrays and variables above.
+            const rtl::OUString& rString );            // arrays and variables above.
                                                 // Leading blanks and blanks
                                                 // after numbers are thrown away
 
@@ -162,75 +168,75 @@ private:
                                                 // optimized substring versions
 
     static inline bool StringContains(          // Whether rString contains rWhat at nPos
-            const String& rWhat,
-            const String& rString,
+            const rtl::OUString& rWhat,
+            const rtl::OUString& rString,
             xub_StrLen nPos )
                 {   // mostly used with one character
-                    if ( rWhat.GetChar(0) != rString.GetChar(nPos) )
+                    if ( rWhat[0] != rString[nPos] )
                         return false;
                     return StringContainsImpl( rWhat, rString, nPos );
                 }
     static inline bool StringPtrContains(       // Whether pString contains rWhat at nPos
-            const String& rWhat,
+            const rtl::OUString& rWhat,
             const sal_Unicode* pString,
             xub_StrLen nPos )                   // nPos MUST be a valid offset from pString
                 {   // mostly used with one character
-                    if ( rWhat.GetChar(0) != *(pString+nPos) )
+                    if ( rWhat[0] != *(pString+nPos) )
                         return false;
                     return StringPtrContainsImpl( rWhat, pString, nPos );
                 }
     static bool StringContainsImpl(             //! DO NOT use directly
-            const String& rWhat,
-            const String& rString,
+            const rtl::OUString& rWhat,
+            const rtl::OUString& rString,
             xub_StrLen nPos );
     static bool StringPtrContainsImpl(          //! DO NOT use directly
-            const String& rWhat,
+            const rtl::OUString& rWhat,
             const sal_Unicode* pString,
             xub_StrLen nPos );
 
 
     static inline bool SkipChar(                // Skip a special character
             sal_Unicode c,
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
     static inline void SkipBlanks(              // Skip blank
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
     static inline bool SkipString(              // Jump over rWhat in rString at nPos
-            const String& rWhat,
-            const String& rString,
+            const rtl::OUString& rWhat,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
 
     inline bool GetThousandSep(                 // Recognizes exactly ,111 as group separator
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos,
             sal_uInt16 nStringPos );
     short GetLogical(                           // Get boolean value
-            const String& rString );
+            const rtl::OUString& rString );
     short GetMonth(                             // Get month and advance string position
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
     int GetDayOfWeek(                           // Get day of week and advance string position
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
     bool GetCurrency(                           // Get currency symbol and advance string position
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos,
             const SvNumberformat* pFormat = NULL ); // optional number format to match against
     bool GetTimeAmPm(                           // Get symbol AM or PM and advance string position
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
     inline bool GetDecSep(                      // Get decimal separator and advance string 
position
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
     inline bool GetTime100SecSep(               // Get hundredth seconds separator and advance 
string position
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
     int GetSign(                                // Get sign  and advance string position
-            const String& rString,              // Including special case '('
+            const rtl::OUString& rString,              // Including special case '('
             xub_StrLen& nPos );
     short GetESign(                             // Get sign of exponent and advance string position
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen& nPos );
 
     inline bool GetNextNumber(                  // Get next number as array offset
@@ -250,20 +256,20 @@ private:
             const SvNumberformat* pFormat = NULL ); // optional number format to match against
 
     bool ScanStartString(                       // Analyze start of string
-            const String& rString,
+            const rtl::OUString& rString,
             const SvNumberformat* pFormat = NULL );
     bool ScanMidString(                         // Analyze middle substring
-            const String& rString,
+            const rtl::OUString& rString,
             sal_uInt16 nStringPos,
             const SvNumberformat* pFormat = NULL );
     bool ScanEndString(                         // Analyze end of string
-            const String& rString,
+            const rtl::OUString& rString,
             const SvNumberformat* pFormat = NULL );
 
     // Compare rString to substring of array indexed by nString
     // nString == 0xFFFF => last substring
     bool ScanStringNumFor(
-            const String& rString,
+            const rtl::OUString& rString,
             xub_StrLen nPos,
             const SvNumberformat* pFormat,
             sal_uInt16 nString,
@@ -277,7 +283,7 @@ private:
     //! case and if it contained native humber digits that they are already
     //! converted to ASCII.
     bool IsNumberFormatMain(                    // Main anlyzing function
-            const String& rString,
+            const rtl::OUString& rString,
             double& fOutNumber,                 // return value if string is numeric
             const SvNumberformat* pFormat = NULL    // optional number format to match against
             );
@@ -285,7 +291,7 @@ private:
     static inline bool MyIsdigit( sal_Unicode c );
 
     // native number transliteration if necessary
-    void TransformInput( String& rString );
+    void TransformInput( rtl::OUString& rString );
 
 #endif  // _ZFORFIND_CXX
 };

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.