]> git.lyx.org Git - lyx.git/blobdiff - src/support/lstrings.cpp
Remove non-copyable idioms
[lyx.git] / src / support / lstrings.cpp
index 651dbc1e1dd2a42097f4a677b0e817e7efe8e71c..6d5f86672fda133b10f060ecd346e18bee01b4e4 100644 (file)
@@ -15,6 +15,8 @@
 #include "support/lstrings.h"
 
 #include "support/convert.h"
+#include "support/debug.h"
+#include "support/lyxlib.h"
 #include "support/qstring_helpers.h"
 
 #include "support/lassert.h"
 #include <QString>
 
 #include <cstdio>
+#include <cstring>
 #include <algorithm>
+#include <iomanip>
+#include <sstream>
+#include <typeinfo>
 
 using namespace std;
 
@@ -32,7 +38,7 @@ namespace lyx {
 // without #include "support/docstring" there.
 docstring const & empty_docstring()
 {
-       static docstring s;
+       static const docstring s;
        return s;
 }
 
@@ -40,7 +46,7 @@ docstring const & empty_docstring()
 // without #include <string>
 string const & empty_string()
 {
-       static string s;
+       static const string s;
        return s;
 }
 
@@ -54,7 +60,7 @@ namespace {
  */
 inline char_type qchar_to_ucs4(QChar const & qchar)
 {
-       LASSERT(is_utf16(static_cast<char_type>(qchar.unicode())), /**/);
+       LASSERT(is_utf16(static_cast<char_type>(qchar.unicode())), return '?');
        return static_cast<char_type>(qchar.unicode());
 }
 
@@ -67,7 +73,7 @@ inline char_type qchar_to_ucs4(QChar const & qchar)
  */
 inline QChar const ucs4_to_qchar(char_type const ucs4)
 {
-       LASSERT(is_utf16(ucs4), /**/);
+       LASSERT(is_utf16(ucs4), return QChar('?'));
        return QChar(static_cast<unsigned short>(ucs4));
 }
 
@@ -200,6 +206,29 @@ int compare_no_case(docstring const & s, docstring const & s2)
 }
 
 
+int compare_locale(docstring const & s, docstring const & s2)
+{
+       // FIXME We have a report that this does not work on windows (bug 9030)
+       try
+       {
+               string const l = to_local8bit(s);
+               string const r = to_local8bit(s2);
+               return strcoll(l.c_str(), r.c_str());
+       }
+       catch (bad_cast & e)
+       {
+               // fall back to builtin sorting
+               LYXERR0("Could not compare using the current locale: "
+                       << e.what() << ", using fallback.");
+               if (s < s2)
+                       return -1;
+               if (s > s2)
+                       return 1;
+               return 0;
+       }
+}
+
+
 namespace {
 
 template<typename Char>
@@ -409,14 +438,14 @@ bool isAscii(string const & str)
 
 char lowercase(char c)
 {
-       LASSERT(isASCII(c), /**/);
+       LASSERT(isASCII(c), return '?');
        return char(tolower(c));
 }
 
 
 char uppercase(char c)
 {
-       LASSERT(isASCII(c), /**/);
+       LASSERT(isASCII(c), return '?');
        return char(toupper(c));
 }
 
@@ -481,6 +510,16 @@ docstring const lowercase(docstring const & a)
 }
 
 
+/* Uncomment here and in lstrings.h if you should need this.
+string const lowercase(string const & a)
+{
+       string tmp(a);
+       transform(tmp.begin(), tmp.end(), tmp.begin(), local_lowercase());
+       return tmp;
+}
+*/
+
+
 docstring const uppercase(docstring const & a)
 {
        docstring tmp(a);
@@ -824,7 +863,7 @@ template<typename String> inline
 String const subst_string(String const & a,
                String const & oldstr, String const & newstr)
 {
-       LASSERT(!oldstr.empty(), /**/);
+       LASSERT(!oldstr.empty(), return a);
        String lstr = a;
        size_t i = 0;
        size_t const olen = oldstr.length();
@@ -840,7 +879,7 @@ String const subst_string(String const & a,
 docstring const subst_string(docstring const & a,
                docstring const & oldstr, docstring const & newstr)
 {
-       LASSERT(!oldstr.empty(), /**/);
+       LASSERT(!oldstr.empty(), return a);
        docstring lstr = a;
        size_t i = 0;
        size_t const olen = oldstr.length();
@@ -882,6 +921,18 @@ docstring const subst(docstring const & a,
 }
 
 
+int count_char(string const & str, char chr)
+{
+       int count = 0;
+       string::const_iterator lit = str.begin();
+       string::const_iterator end = str.end();
+       for (; lit != end; ++lit)
+               if ((*lit) == chr)
+                       count++;
+       return count;
+}
+
+
 /// Count all occurences of char \a chr inside \a str
 int count_char(docstring const & str, docstring::value_type chr)
 {
@@ -895,9 +946,34 @@ int count_char(docstring const & str, docstring::value_type chr)
 }
 
 
+int count_bin_chars(string const & str)
+{
+       QString const qstr = toqstr(str).simplified();
+       int count = 0;
+       QString::const_iterator cit = qstr.begin();
+       QString::const_iterator end = qstr.end();
+       for (; cit != end; ++cit)  {
+               switch (cit->category()) {
+               case QChar::Separator_Line:
+               case QChar::Separator_Paragraph:
+               case QChar::Other_Control:
+               case QChar::Other_Format:
+               case QChar::Other_Surrogate:
+               case QChar::Other_PrivateUse:
+               case QChar::Other_NotAssigned:
+                       ++count;
+                       break;
+               default:
+                       break;
+               }
+       }
+       return count;
+}
+
+
 docstring const trim(docstring const & a, char const * p)
 {
-       LASSERT(p, /**/);
+       LASSERT(p, return a);
 
        if (a.empty() || !*p)
                return a;
@@ -916,7 +992,7 @@ docstring const trim(docstring const & a, char const * p)
 
 string const trim(string const & a, char const * p)
 {
-       LASSERT(p, /**/);
+       LASSERT(p, return a);
 
        if (a.empty() || !*p)
                return a;
@@ -934,7 +1010,7 @@ string const trim(string const & a, char const * p)
 
 string const rtrim(string const & a, char const * p)
 {
-       LASSERT(p, /**/);
+       LASSERT(p, return a);
 
        if (a.empty() || !*p)
                return a;
@@ -951,7 +1027,7 @@ string const rtrim(string const & a, char const * p)
 
 docstring const rtrim(docstring const & a, char const * p)
 {
-       LASSERT(p, /**/);
+       LASSERT(p, return a);
 
        if (a.empty() || !*p)
                return a;
@@ -968,7 +1044,7 @@ docstring const rtrim(docstring const & a, char const * p)
 
 string const ltrim(string const & a, char const * p)
 {
-       LASSERT(p, /**/);
+       LASSERT(p, return a);
        if (a.empty() || !*p)
                return a;
        size_t l = a.find_first_not_of(p);
@@ -980,7 +1056,7 @@ string const ltrim(string const & a, char const * p)
 
 docstring const ltrim(docstring const & a, char const * p)
 {
-       LASSERT(p, /**/);
+       LASSERT(p, return a);
        if (a.empty() || !*p)
                return a;
        size_t l = a.find_first_not_of(from_ascii(p));
@@ -998,18 +1074,20 @@ String const doSplit(String const & a, String & piece, Char delim)
        size_t i = a.find(delim);
        if (i == a.length() - 1) {
                piece = a.substr(0, i);
-       } else if (i != String::npos) {
-               piece = a.substr(0, i);
-               tmp = a.substr(i + 1);
        } else if (i == 0) {
                piece.erase();
                tmp = a.substr(i + 1);
+       } else if (i != String::npos) {
+               piece = a.substr(0, i);
+               tmp = a.substr(i + 1);
        } else {
                piece = a;
        }
        return tmp;
 }
 
+
+// FIXME: why is this specialization needed?
 template<typename Char> inline
 docstring const doSplit(docstring const & a, docstring & piece, Char delim)
 {
@@ -1017,12 +1095,12 @@ docstring const doSplit(docstring const & a, docstring & piece, Char delim)
        size_t i = a.find(delim);
        if (i == a.length() - 1) {
                piece = a.substr(0, i);
-       } else if (i != docstring::npos) {
-               piece = a.substr(0, i);
-               tmp = a.substr(i + 1);
        } else if (i == 0) {
                piece.erase();
                tmp = a.substr(i + 1);
+       } else if (i != docstring::npos) {
+               piece = a.substr(0, i);
+               tmp = a.substr(i + 1);
        } else {
                piece = a;
        }
@@ -1107,7 +1185,7 @@ docstring const escape(docstring const & lab)
                        // encode bigger values. Test for 2^24 because we
                        // can encode that with the 6 hex digits that are
                        // needed for 21 bits anyway.
-                       LASSERT(c < (1 << 24), /**/);
+                       LASSERT(c < (1 << 24), continue);
                        enc += '=';
                        enc += hexdigit[(c>>20) & 15];
                        enc += hexdigit[(c>>16) & 15];
@@ -1123,6 +1201,17 @@ docstring const escape(docstring const & lab)
 }
 
 
+bool truncateWithEllipsis(docstring & str, size_t const len)
+{
+       if (str.size() <= len)
+               return false;
+       str.resize(len);
+       if (len > 0)
+               str[len - 1] = 0x2026;// HORIZONTAL ELLIPSIS
+       return true;
+}
+
+
 namespace {
 
 // this doesn't check whether str is empty, so do that first.
@@ -1146,7 +1235,7 @@ vector<docstring> wrapToVec(docstring const & str, int ind,
                size_t const i = s.find_last_of(' ', width - 1);
                if (i == docstring::npos || i <= size_t(ind)) {
                        // no space found
-                       s = s.substr(0, width - 3) + "...";
+                       truncateWithEllipsis(s, width);
                        break;
                }
                retval.push_back(s.substr(0, i));
@@ -1175,7 +1264,6 @@ docstring wrap(docstring const & str, int const ind, size_t const width)
 docstring wrapParas(docstring const & str, int const indent,
                    size_t const width, size_t const maxlines)
 {
-       docstring const dots = from_ascii("...");
        if (str.empty())
                return docstring();
 
@@ -1194,15 +1282,15 @@ docstring wrapParas(docstring const & str, int const indent,
                        tmp.resize(maxlines - curlines);
                        docstring last = tmp.back();
                        size_t const lsize = last.size();
-                       if (lsize > width - 3) {
-                               size_t const i = last.find_last_of(' ', width - 3);
+                       if (lsize > width - 1) {
+                               size_t const i = last.find_last_of(' ', width - 1);
                                if (i == docstring::npos || i <= size_t(indent))
                                        // no space found
-                                       last = last.substr(0, lsize - 3) + dots;
+                                       truncateWithEllipsis(last, lsize);
                                else
-                                       last = last.substr(0, i) + dots;
+                                       truncateWithEllipsis(last, i);
                        } else
-                               last += dots;
+                               last.push_back(0x2026);//HORIZONTAL ELLIPSIS
                        tmp.pop_back();
                        tmp.push_back(last);
                }
@@ -1312,10 +1400,29 @@ int findToken(char const * const str[], string const & search_token)
 }
 
 
+std::string formatFPNumber(double x)
+{
+       // Need manual tweaking, QString::number(x, 'f', 16) does not work either
+       ostringstream os;
+       os << std::fixed;
+       // Prevent outputs of 23.4200000000000017 but output small numbers
+       // with at least 6 significant digits.
+       double const logarithm = log10(fabs(x));
+       os << std::setprecision(max(6 - iround(logarithm), 0)) << x;
+       string result = os.str();
+       if (result.find('.') != string::npos) {
+               result = rtrim(result, "0");
+               if (result[result.length()-1] == '.')
+                       result = rtrim(result, ".");
+       }
+       return result;
+}
+
+
 template<>
 docstring bformat(docstring const & fmt, int arg1)
 {
-       LASSERT(contains(fmt, from_ascii("%1$d")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$d")));
        docstring const str = subst(fmt, from_ascii("%1$d"), convert<docstring>(arg1));
        return subst(str, from_ascii("%%"), from_ascii("%"));
 }
@@ -1324,16 +1431,27 @@ docstring bformat(docstring const & fmt, int arg1)
 template<>
 docstring bformat(docstring const & fmt, long arg1)
 {
-       LASSERT(contains(fmt, from_ascii("%1$d")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$d")));
+       docstring const str = subst(fmt, from_ascii("%1$d"), convert<docstring>(arg1));
+       return subst(str, from_ascii("%%"), from_ascii("%"));
+}
+
+
+#ifdef LYX_USE_LONG_LONG
+template<>
+docstring bformat(docstring const & fmt, long long arg1)
+{
+       LATTEST(contains(fmt, from_ascii("%1$d")));
        docstring const str = subst(fmt, from_ascii("%1$d"), convert<docstring>(arg1));
        return subst(str, from_ascii("%%"), from_ascii("%"));
 }
+#endif
 
 
 template<>
 docstring bformat(docstring const & fmt, unsigned int arg1)
 {
-       LASSERT(contains(fmt, from_ascii("%1$d")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$d")));
        docstring const str = subst(fmt, from_ascii("%1$d"), convert<docstring>(arg1));
        return subst(str, from_ascii("%%"), from_ascii("%"));
 }
@@ -1342,7 +1460,7 @@ docstring bformat(docstring const & fmt, unsigned int arg1)
 template<>
 docstring bformat(docstring const & fmt, docstring arg1)
 {
-       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$s")));
        docstring const str = subst(fmt, from_ascii("%1$s"), arg1);
        return subst(str, from_ascii("%%"), from_ascii("%"));
 }
@@ -1351,7 +1469,7 @@ docstring bformat(docstring const & fmt, docstring arg1)
 template<>
 docstring bformat(docstring const & fmt, char * arg1)
 {
-       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$s")));
        docstring const str = subst(fmt, from_ascii("%1$s"), from_ascii(arg1));
        return subst(str, from_ascii("%%"), from_ascii("%"));
 }
@@ -1360,8 +1478,8 @@ docstring bformat(docstring const & fmt, char * arg1)
 template<>
 docstring bformat(docstring const & fmt, docstring arg1, docstring arg2)
 {
-       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%2$s")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$s")));
+       LATTEST(contains(fmt, from_ascii("%2$s")));
        docstring str = subst(fmt, from_ascii("%1$s"), arg1);
        str = subst(str, from_ascii("%2$s"), arg2);
        return subst(str, from_ascii("%%"), from_ascii("%"));
@@ -1371,8 +1489,8 @@ docstring bformat(docstring const & fmt, docstring arg1, docstring arg2)
 template<>
 docstring bformat(docstring const & fmt, docstring arg1, int arg2)
 {
-       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%2$d")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$s")));
+       LATTEST(contains(fmt, from_ascii("%2$d")));
        docstring str = subst(fmt, from_ascii("%1$s"), arg1);
        str = subst(str, from_ascii("%2$d"), convert<docstring>(arg2));
        return subst(str, from_ascii("%%"), from_ascii("%"));
@@ -1382,10 +1500,10 @@ docstring bformat(docstring const & fmt, docstring arg1, int arg2)
 template<>
 docstring bformat(docstring const & fmt, char const * arg1, docstring arg2)
 {
-       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%2$s")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$s")));
+       LATTEST(contains(fmt, from_ascii("%2$s")));
        docstring str = subst(fmt, from_ascii("%1$s"), from_ascii(arg1));
-       str = subst(fmt, from_ascii("%2$s"), arg2);
+       str = subst(str, from_ascii("%2$s"), arg2);
        return subst(str, from_ascii("%%"), from_ascii("%"));
 }
 
@@ -1393,8 +1511,8 @@ docstring bformat(docstring const & fmt, char const * arg1, docstring arg2)
 template<>
 docstring bformat(docstring const & fmt, int arg1, int arg2)
 {
-       LASSERT(contains(fmt, from_ascii("%1$d")), /**/);
-       LASSERT(contains(fmt, from_ascii("%2$d")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$d")));
+       LATTEST(contains(fmt, from_ascii("%2$d")));
        docstring str = subst(fmt, from_ascii("%1$d"), convert<docstring>(arg1));
        str = subst(str, from_ascii("%2$d"), convert<docstring>(arg2));
        return subst(str, from_ascii("%%"), from_ascii("%"));
@@ -1404,9 +1522,9 @@ docstring bformat(docstring const & fmt, int arg1, int arg2)
 template<>
 docstring bformat(docstring const & fmt, docstring arg1, docstring arg2, docstring arg3)
 {
-       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%2$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%3$s")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$s")));
+       LATTEST(contains(fmt, from_ascii("%2$s")));
+       LATTEST(contains(fmt, from_ascii("%3$s")));
        docstring str = subst(fmt, from_ascii("%1$s"), arg1);
        str = subst(str, from_ascii("%2$s"), arg2);
        str = subst(str, from_ascii("%3$s"), arg3);
@@ -1418,10 +1536,10 @@ template<>
 docstring bformat(docstring const & fmt,
               docstring arg1, docstring arg2, docstring arg3, docstring arg4)
 {
-       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%2$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%3$s")), /**/);
-       LASSERT(contains(fmt, from_ascii("%4$s")), /**/);
+       LATTEST(contains(fmt, from_ascii("%1$s")));
+       LATTEST(contains(fmt, from_ascii("%2$s")));
+       LATTEST(contains(fmt, from_ascii("%3$s")));
+       LATTEST(contains(fmt, from_ascii("%4$s")));
        docstring str = subst(fmt, from_ascii("%1$s"), arg1);
        str = subst(str, from_ascii("%2$s"), arg2);
        str = subst(str, from_ascii("%3$s"), arg3);