]> git.lyx.org Git - lyx.git/blobdiff - src/support/lstrings.C
* src/encoding.C (latexChar,read):
[lyx.git] / src / support / lstrings.C
index 324f33e1ee6a7f9d1c7c24f2eef2cace92c984f9..fe161be9913257702d9375a4be697dae9de562db 100644 (file)
@@ -14,6 +14,7 @@
 #include "support/lstrings.h"
 #include "support/lyxlib.h"
 #include "support/convert.h"
+#include "support/qstring_helpers.h"
 
 #include "debug.h"
 
 #include <algorithm>
 #include <sstream>
 
-#ifdef LIBC_WCTYPE_USES_UCS4
-// We can use the libc ctype functions because we unset the LC_CTYPE
-// category of the current locale in gettext.C
-#include <wctype.h>
-#else
-// Steal some code from somewhere else, e.g. glib (look at gunicode.h)
-// The code that we currently use does not really work.
-#endif
-
-
-using lyx::docstring;
 
 using std::transform;
 using std::string;
@@ -58,28 +48,6 @@ using std::toupper;
 namespace lyx {
 namespace support {
 
-int compare_no_case(string const & s, string const & s2)
-{
-       string::const_iterator p = s.begin();
-       string::const_iterator p2 = s2.begin();
-
-       while (p != s.end() && p2 != s2.end()) {
-               int const lc1 = tolower(*p);
-               int const lc2 = tolower(*p2);
-               if (lc1 != lc2)
-                       return (lc1 < lc2) ? -1 : 1;
-               ++p;
-               ++p2;
-       }
-
-       if (s.size() == s2.size())
-               return 0;
-       if (s.size() < s2.size())
-               return -1;
-       return 1;
-}
-
-
 int compare_no_case(docstring const & s, docstring const & s2)
 {
        docstring::const_iterator p = s.begin();
@@ -158,29 +126,6 @@ int compare_ascii_no_case(docstring const & s, docstring const & s2)
 }
 
 
-int compare_no_case(string const & s, string const & s2, unsigned int len)
-{
-       string::const_iterator p = s.begin();
-       string::const_iterator p2 = s2.begin();
-       unsigned int i = 0;
-       while (i < len && p != s.end() && p2 != s2.end()) {
-               int const lc1 = tolower(*p);
-               int const lc2 = tolower(*p2);
-               if (lc1 != lc2)
-                       return (lc1 < lc2) ? -1 : 1;
-               ++i;
-               ++p;
-               ++p2;
-       }
-
-       if (s.size() >= len && s2.size() >= len)
-               return 0;
-       if (s.size() < s2.size())
-               return -1;
-       return 1;
-}
-
-
 bool isStrInt(string const & str)
 {
        if (str.empty()) return false;
@@ -311,48 +256,33 @@ bool isAscii(docstring const & str)
 
 char lowercase(char c)
 {
+       BOOST_ASSERT(static_cast<unsigned char>(c) < 0x80);
        return char(tolower(c));
 }
 
 
 char uppercase(char c)
 {
+       BOOST_ASSERT(static_cast<unsigned char>(c) < 0x80);
        return char(toupper(c));
 }
 
 
-// FIXME UNICODE
-// for lowercase() and uppercase() function below when wchar_t is not used:
-// 1) std::tolower() and std::toupper() are templates that
-// compile fine with char_type. With the test (c >= 256) we
-// do not trust these function to do the right thing with
-// unicode char.
-// 2) these functions use the current locale, which is wrong
-// if it is not latin1 based (latin1 is a subset of UCS4).
-
 char_type lowercase(char_type c)
 {
-#ifdef LIBC_WCTYPE_USES_UCS4
-       return towlower(c);
-#else
-       if (c >= 256)
+       if (!is_utf16(c))
+               // We don't know how to lowercase a non-utf16 char
                return c;
-
-       return tolower(c);
-#endif
+       return qchar_to_ucs4(ucs4_to_qchar(c).toLower());
 }
 
 
 char_type uppercase(char_type c)
 {
-#ifdef LIBC_WCTYPE_USES_UCS4
-       return towupper(c);
-#else
-       if (c >= 256)
+       if (!is_utf16(c))
+               // We don't know how to uppercase a non-utf16 char
                return c;
-
-       return toupper(c);
-#endif
+       return qchar_to_ucs4(ucs4_to_qchar(c).toUpper());
 }
 
 
@@ -362,35 +292,42 @@ namespace {
 // calls to std::transform yet, we use these helper clases. (Lgb)
 
 struct local_lowercase {
-       char operator()(char c) const {
-               return tolower(c);
+       char_type operator()(char_type c) const {
+               if (!is_utf16(c))
+                       // We don't know how to lowercase a non-utf16 char
+                       return c;
+               return qchar_to_ucs4(ucs4_to_qchar(c).toLower());
        }
 };
 
 struct local_uppercase {
-       char operator()(char c) const {
-               return toupper(c);
+       char_type operator()(char_type c) const {
+               if (!is_utf16(c))
+                       // We don't know how to uppercase a non-utf16 char
+                       return c;
+               return qchar_to_ucs4(ucs4_to_qchar(c).toUpper());
        }
 };
 
-struct local_ascii_lowercase {
-       char operator()(char c) const {
+template<typename Char> struct local_ascii_lowercase {
+       Char operator()(Char c) const {
                return ascii_tolower(c);
        }
 };
 
 } // end of anon namespace
 
-string const lowercase(string const & a)
+docstring const lowercase(docstring const & a)
 {
-       string tmp(a);
+       docstring tmp(a);
        transform(tmp.begin(), tmp.end(), tmp.begin(), local_lowercase());
        return tmp;
 }
 
-string const uppercase(string const & a)
+
+docstring const uppercase(docstring const & a)
 {
-       string tmp(a);
+       docstring tmp(a);
        transform(tmp.begin(), tmp.end(), tmp.begin(), local_uppercase());
        return tmp;
 }
@@ -400,11 +337,28 @@ string const ascii_lowercase(string const & a)
 {
        string tmp(a);
        transform(tmp.begin(), tmp.end(), tmp.begin(),
-                 local_ascii_lowercase());
+                 local_ascii_lowercase<char>());
+       return tmp;
+}
+
+
+docstring const ascii_lowercase(docstring const & a)
+{
+       docstring tmp(a);
+       transform(tmp.begin(), tmp.end(), tmp.begin(),
+                 local_ascii_lowercase<char_type>());
        return tmp;
 }
 
 
+bool prefixIs(docstring const & a, char_type c)
+{
+       if (a.empty())
+               return false;
+       return a[0] == c;
+}
+
+
 bool prefixIs(string const & a, string const & pre)
 {
        string::size_type const prelen = pre.length();
@@ -441,6 +395,14 @@ bool suffixIs(string const & a, char c)
 }
 
 
+bool suffixIs(docstring const & a, char_type c)
+{
+       if (a.empty())
+               return false;
+       return a[a.length() - 1] == c;
+}
+
+
 bool suffixIs(string const & a, string const & suf)
 {
        string::size_type const suflen = suf.length();
@@ -648,6 +610,23 @@ string const rtrim(string const & a, char const * p)
 }
 
 
+docstring const rtrim(docstring const & a, char const * p)
+{
+       BOOST_ASSERT(p);
+
+       if (a.empty() || !*p)
+               return a;
+
+       docstring::size_type r = a.find_last_not_of(from_ascii(p));
+
+       // Is this test really needed? (Lgb)
+       if (r == docstring::npos)
+               return docstring();
+
+       return a.substr(0, r + 1);
+}
+
+
 string const ltrim(string const & a, char const * p)
 {
        BOOST_ASSERT(p);
@@ -761,38 +740,57 @@ docstring const escape(docstring const & lab)
 }
 
 
-/// gives a vector of stringparts which have the delimiter delim
-vector<string> const getVectorFromString(string const & str,
-                                        string const & delim)
+namespace {
+
+template<typename String> vector<String> const
+getVectorFromStringT(String const & str, String const & delim)
 {
 // Lars would like this code to go, but for now his replacement (below)
 // doesn't fullfil the same function. I have, therefore, reactivated the
 // old code for now. Angus 11 Nov 2002.
 #if 1
-       vector<string> vec;
+       vector<String> vec;
        if (str.empty())
                return vec;
-       string keys = rtrim(str);
+       String keys = rtrim(str);
        for(;;) {
-               string::size_type const idx = keys.find(delim);
-               if (idx == string::npos) {
+               typename String::size_type const idx = keys.find(delim);
+               if (idx == String::npos) {
                        vec.push_back(ltrim(keys));
                        break;
                }
-               string const key = trim(keys.substr(0, idx));
+               String const key = trim(keys.substr(0, idx));
                if (!key.empty())
                        vec.push_back(key);
-               string::size_type const start = idx + delim.size();
+               typename String::size_type const start = idx + delim.size();
                keys = keys.substr(start);
        }
        return vec;
 #else
-       boost::char_separator<char> sep(delim.c_str());
-       boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
-       return vector<string>(tokens.begin(), tokens.end());
+       typedef boost::char_separator<typename String::value_type> Separator;
+       typedef boost::tokenizer<Separator, typename String::const_iterator, String> Tokenizer;
+       Separator sep(delim.c_str());
+       Tokenizer tokens(str, sep);
+       return vector<String>(tokens.begin(), tokens.end());
 #endif
 }
 
+}
+
+
+vector<string> const getVectorFromString(string const & str,
+                                         string const & delim)
+{
+       return getVectorFromStringT<string>(str, delim);
+}
+
+
+vector<docstring> const getVectorFromString(docstring const & str,
+                                            docstring const & delim)
+{
+       return getVectorFromStringT<docstring>(str, delim);
+}
+
 
 // the same vice versa
 string const getStringFromVector(vector<string> const & vec,