]> git.lyx.org Git - lyx.git/blobdiff - src/support/lstrings.cpp
an example for the sweave module, prepared by Gregor Gorjanc
[lyx.git] / src / support / lstrings.cpp
index aa5bbc6cbc024c565be155da640614ddaae2ce67..7e358c940092c9bdd99dd2b576bbdec0fb343cdb 100644 (file)
@@ -3,8 +3,9 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author Jean-Marc Lasgouttes
+ * \author Dekel Tsur
  *
  * Full author contact details are available in file CREDITS.
  */
 #include "support/lstrings.h"
 
 #include "support/convert.h"
-#include "support/debug.h"
-#include "support/lyxlib.h"
 #include "support/qstring_helpers.h"
 #include "support/textutils.h"
 
 #include <boost/tokenizer.hpp>
-#include <boost/assert.hpp>
+#include "support/lassert.h"
 
-#include <cctype>
-#include <cstdlib>
+#include <QString>
+#include <QVector>
 
+#include <cstdio>
 #include <algorithm>
-#include <sstream>
 
 using namespace std;
 
@@ -40,11 +39,11 @@ docstring const & empty_docstring()
        return s;
 }
 
-// Using this allows us to have std::string default arguments in headers
+// Using this allows us to have string default arguments in headers
 // without #include <string>
-std::string const & empty_string()
+string const & empty_string()
 {
-       static std::string s;
+       static string s;
        return s;
 }
 
@@ -57,7 +56,7 @@ std::string const & empty_string()
  */
 static inline char_type qchar_to_ucs4(QChar const & qchar)
 {
-       BOOST_ASSERT(is_utf16(static_cast<char_type>(qchar.unicode())));
+       LASSERT(is_utf16(static_cast<char_type>(qchar.unicode())), /**/);
        return static_cast<char_type>(qchar.unicode());
 }
 
@@ -71,7 +70,7 @@ static inline char_type qchar_to_ucs4(QChar const & qchar)
  */
 static inline QChar const ucs4_to_qchar(char_type const ucs4)
 {
-       BOOST_ASSERT(is_utf16(ucs4));
+       LASSERT(is_utf16(ucs4), /**/);
        return QChar(static_cast<unsigned short>(ucs4));
 }
 
@@ -95,6 +94,14 @@ bool isLetterChar(char_type c)
 }
 
 
+bool isLower(char_type c)
+{
+       if (!is_utf16(c))
+               return false;
+       return ucs4_to_qchar(c).isLower();
+}
+
+
 bool isAlphaASCII(char_type c)
 {
        return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
@@ -378,14 +385,14 @@ bool isAscii(string const & str)
 
 char lowercase(char c)
 {
-       BOOST_ASSERT(static_cast<unsigned char>(c) < 0x80);
+       LASSERT(static_cast<unsigned char>(c) < 0x80, /**/);
        return char(tolower(c));
 }
 
 
 char uppercase(char c)
 {
-       BOOST_ASSERT(static_cast<unsigned char>(c) < 0x80);
+       LASSERT(static_cast<unsigned char>(c) < 0x80, /**/);
        return char(toupper(c));
 }
 
@@ -410,8 +417,8 @@ char_type uppercase(char_type c)
 
 namespace {
 
-// since we cannot use std::tolower and std::toupper directly in the
-// calls to std::transform yet, we use these helper clases. (Lgb)
+// since we cannot use tolower and toupper directly in the
+// calls to transform yet, we use these helper clases. (Lgb)
 
 struct local_lowercase {
        char_type operator()(char_type c) const {
@@ -483,14 +490,7 @@ bool prefixIs(string const & a, string const & pre)
 {
        size_t const prelen = pre.length();
        size_t const alen = a.length();
-
-       if (prelen > alen || a.empty())
-               return false;
-#if defined(STD_STRING_IS_GOOD)
-       return a.compare(0, prelen, pre) == 0;
-#else
-       return ::strncmp(a.c_str(), pre.c_str(), prelen) == 0;
-#endif
+       return prelen <= alen && !a.empty() && a.compare(0, prelen, pre) == 0;
 }
 
 
@@ -498,17 +498,14 @@ bool prefixIs(docstring const & a, docstring const & pre)
 {
        size_t const prelen = pre.length();
        size_t const alen = a.length();
-
-       if (prelen > alen || a.empty())
-               return false;
-       else
-               return a.compare(0, prelen, pre) == 0;
+       return prelen <= alen && !a.empty() && a.compare(0, prelen, pre) == 0;
 }
 
 
 bool suffixIs(string const & a, char c)
 {
-       if (a.empty()) return false;
+       if (a.empty())
+               return false;
        return a[a.length() - 1] == c;
 }
 
@@ -525,16 +522,15 @@ bool suffixIs(string const & a, string const & suf)
 {
        size_t const suflen = suf.length();
        size_t const alen = a.length();
+       return suflen <= alen && a.compare(alen - suflen, suflen, suf) == 0;
+}
 
-       if (suflen > alen)
-               return false;
 
-#if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
-       string tmp(a, alen - suflen);
-       return ::strncmp(tmp.c_str(), suf.c_str(), suflen) == 0;
-#else
-       return a.compare(alen - suflen, suflen, suf) == 0;
-#endif
+bool suffixIs(docstring const & a, docstring const & suf)
+{
+       size_t const suflen = suf.length();
+       size_t const alen = a.length();
+       return suflen <= alen && a.compare(alen - suflen, suflen, suf) == 0;
 }
 
 
@@ -618,14 +614,32 @@ int tokenPos(string const & a, char delim, string const & tok)
 }
 
 
+// this could probably be faster and/or cleaner, but it seems to work (JMarc)
+// rewritten to use new string (Lgb)
+int tokenPos(docstring const & a, char_type delim, docstring const & tok)
+{
+       int i = 0;
+       docstring str = a;
+       docstring tmptok;
+
+       while (!str.empty()) {
+               str = split(str, tmptok, delim);
+               if (tok == tmptok)
+                       return i;
+               ++i;
+       }
+       return -1;
+}
+
+
 namespace {
 
 /// Substitute all \a oldchar with \a newchar
 template<typename Ch> inline
-std::basic_string<Ch> const subst_char(std::basic_string<Ch> const & a,
+basic_string<Ch> const subst_char(basic_string<Ch> const & a,
                Ch oldchar, Ch newchar)
 {
-       typedef std::basic_string<Ch> String;
+       typedef basic_string<Ch> String;
        String tmp(a);
        typename String::iterator lit = tmp.begin();
        typename String::iterator end = tmp.end();
@@ -654,7 +668,7 @@ template<typename String> inline
 String const subst_string(String const & a,
                String const & oldstr, String const & newstr)
 {
-       BOOST_ASSERT(!oldstr.empty());
+       LASSERT(!oldstr.empty(), /**/);
        String lstr = a;
        size_t i = 0;
        size_t const olen = oldstr.length();
@@ -669,7 +683,7 @@ String const subst_string(String const & a,
 docstring const subst_string(docstring const & a,
                docstring const & oldstr, docstring const & newstr)
 {
-       BOOST_ASSERT(!oldstr.empty());
+       LASSERT(!oldstr.empty(), /**/);
        docstring lstr = a;
        size_t i = 0;
        size_t const olen = oldstr.length();
@@ -713,7 +727,7 @@ docstring const subst(docstring const & a,
 
 docstring const trim(docstring const & a, char const * p)
 {
-       BOOST_ASSERT(p);
+       LASSERT(p, /**/);
 
        if (a.empty() || !*p)
                return a;
@@ -732,7 +746,7 @@ docstring const trim(docstring const & a, char const * p)
 
 string const trim(string const & a, char const * p)
 {
-       BOOST_ASSERT(p);
+       LASSERT(p, /**/);
 
        if (a.empty() || !*p)
                return a;
@@ -750,7 +764,7 @@ string const trim(string const & a, char const * p)
 
 string const rtrim(string const & a, char const * p)
 {
-       BOOST_ASSERT(p);
+       LASSERT(p, /**/);
 
        if (a.empty() || !*p)
                return a;
@@ -767,7 +781,7 @@ string const rtrim(string const & a, char const * p)
 
 docstring const rtrim(docstring const & a, char const * p)
 {
-       BOOST_ASSERT(p);
+       LASSERT(p, /**/);
 
        if (a.empty() || !*p)
                return a;
@@ -784,7 +798,7 @@ docstring const rtrim(docstring const & a, char const * p)
 
 string const ltrim(string const & a, char const * p)
 {
-       BOOST_ASSERT(p);
+       LASSERT(p, /**/);
        if (a.empty() || !*p)
                return a;
        size_t l = a.find_first_not_of(p);
@@ -796,7 +810,7 @@ string const ltrim(string const & a, char const * p)
 
 docstring const ltrim(docstring const & a, char const * p)
 {
-       BOOST_ASSERT(p);
+       LASSERT(p, /**/);
        if (a.empty() || !*p)
                return a;
        size_t l = a.find_first_not_of(from_ascii(p));
@@ -898,7 +912,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.
-                       BOOST_ASSERT(c < (1 << 24));
+                       LASSERT(c < (1 << 24), /**/);
                        enc += '=';
                        enc += hexdigit[(c>>20) & 15];
                        enc += hexdigit[(c>>16) & 15];
@@ -914,10 +928,91 @@ docstring const escape(docstring const & lab)
 }
 
 
+namespace {
+
+// this doesn't check whether str is empty, so do that first.
+vector<docstring> wrapToVec(docstring const & str, int const ind,
+                           size_t const width)
+{
+       docstring s = trim(str);
+       if (s.empty())
+               return vector<docstring>();
+
+       docstring indent;
+       if (ind < 0)
+               for (int j = 0; j > ind; --j)
+                       indent += " ";
+       else if (ind > 0)
+               for (int j = 0; j < ind; ++j)
+                       s = " " + s;
+
+       vector<docstring> retval;
+       while (s.size() > width) {
+               int i = width - 1;
+               // find the last space
+               for (; i >= 0; --i)
+                       if (s[i] == ' ')
+                               break;
+               if (i < 0) {
+                       // no space found
+                       s = s.substr(0, width - 3) + "...";
+                       break;
+               }
+               retval.push_back(s.substr(0, i));
+               s = indent + s.substr(i);
+       }
+       if (!s.empty())
+               retval.push_back(s);
+       return retval;
+}
+
+}
+
+
+docstring wrap(docstring const & str, int const ind, size_t const width)
+{
+       docstring s = trim(str);
+       if (s.empty())
+               return docstring();
+
+       vector<docstring> const svec = wrapToVec(str, ind, width);
+       return getStringFromVector(svec, from_ascii("\n"));
+}
+
+
+docstring wrapParas(docstring const & str, int const indent,
+                   size_t const width, size_t const maxlines)
+{
+       if (str.empty())
+               return docstring();
+
+       vector<docstring> pars = getVectorFromString(str, from_ascii("\n"), true);
+       vector<docstring> retval;
+
+       vector<docstring>::iterator it = pars.begin();
+       vector<docstring>::iterator en = pars.end();
+       for (; it != en; ++it) {
+               vector<docstring> tmp = wrapToVec(*it, indent, width);
+               size_t const nlines = tmp.size();
+               if (nlines == 0)
+                       continue;
+               size_t const curlines = retval.size();
+               if (maxlines > 0 && curlines + nlines >= maxlines) {
+                       tmp.resize(maxlines - curlines - 1);
+                       tmp.push_back(from_ascii("..."));
+               }
+               retval.insert(retval.end(), tmp.begin(), tmp.end());
+               if (maxlines > 0 && retval.size() >= maxlines)
+                       break;
+       }
+       return getStringFromVector(retval, from_ascii("\n"));
+}
+
+
 namespace {
 
 template<typename String> vector<String> const
-getVectorFromStringT(String const & str, String const & delim)
+getVectorFromStringT(String const & str, String const & delim, bool keepempty)
 {
 // Lars would like this code to go, but for now his replacement (below)
 // doesn't fullfil the same function. I have, therefore, reactivated the
@@ -934,7 +1029,7 @@ getVectorFromStringT(String const & str, String const & delim)
                        break;
                }
                String const key = trim(keys.substr(0, idx));
-               if (!key.empty())
+               if (!key.empty() || keepempty)
                        vec.push_back(key);
                size_t const start = idx + delim.size();
                keys = keys.substr(start);
@@ -949,39 +1044,54 @@ getVectorFromStringT(String const & str, String const & delim)
 #endif
 }
 
+
+template<typename String> const String
+       getStringFromVector(vector<String> const & vec, String const & delim)
+{
+       String str;
+       typename vector<String>::const_iterator it = vec.begin();
+       typename vector<String>::const_iterator en = vec.end();
+       for (; it != en; ++it) {
+               String item = trim(*it);
+               if (item.empty())
+                       continue;
+               if (!str.empty())
+                       str += delim;
+               str += item;
+       }
+       return str;
+}
+
 } // namespace anon
 
 
 vector<string> const getVectorFromString(string const & str,
-                                        string const & delim)
+                                        string const & delim,
+                                        bool keepempty)
 {
-       return getVectorFromStringT<string>(str, delim);
+       return getVectorFromStringT<string>(str, delim, keepempty);
 }
 
 
 vector<docstring> const getVectorFromString(docstring const & str,
-                                           docstring const & delim)
+                                           docstring const & delim,
+                                           bool keepempty)
 {
-       return getVectorFromStringT<docstring>(str, delim);
+       return getVectorFromStringT<docstring>(str, delim, keepempty);
 }
 
 
-// the same vice versa
 string const getStringFromVector(vector<string> const & vec,
                                 string const & delim)
 {
-       string str;
-       int i = 0;
-       for (vector<string>::const_iterator it = vec.begin();
-            it != vec.end(); ++it) {
-               string item = trim(*it);
-               if (item.empty())
-                       continue;
-               if (i++ > 0)
-                       str += delim;
-               str += item;
-       }
-       return str;
+       return getStringFromVector<string>(vec, delim);
+}
+
+
+docstring const getStringFromVector(vector<docstring> const & vec,
+                                   docstring const & delim)
+{
+       return getStringFromVector<docstring>(vec, delim);
 }
 
 
@@ -997,31 +1107,10 @@ int findToken(char const * const str[], string const & search_token)
 }
 
 
-docstring const externalLineEnding(docstring const & str)
-{
-#if defined(__APPLE__)
-       // The MAC clipboard uses \r for lineendings, and we use \n
-       return subst(str, '\n', '\r');
-#elif defined (_WIN32) || (defined (__CYGWIN__) && defined (X_DISPLAY_MISSING))
-       // Windows clipboard uses \r\n for lineendings, and we use \n
-       return subst(str, from_ascii("\n"), from_ascii("\r\n"));
-#else
-       return str;
-#endif
-}
-
-
-docstring const internalLineEnding(docstring const & str)
-{
-       docstring const s = subst(str, from_ascii("\r\n"), from_ascii("\n"));
-       return subst(s, '\r', '\n');
-}
-
-
 template<>
 docstring bformat(docstring const & fmt, int arg1)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$d")));
+       LASSERT(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("%"));
 }
@@ -1030,7 +1119,7 @@ docstring bformat(docstring const & fmt, int arg1)
 template<>
 docstring bformat(docstring const & fmt, long arg1)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$d")));
+       LASSERT(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("%"));
 }
@@ -1039,7 +1128,7 @@ docstring bformat(docstring const & fmt, long arg1)
 template<>
 docstring bformat(docstring const & fmt, unsigned int arg1)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$d")));
+       LASSERT(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("%"));
 }
@@ -1048,7 +1137,7 @@ docstring bformat(docstring const & fmt, unsigned int arg1)
 template<>
 docstring bformat(docstring const & fmt, docstring arg1)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$s")));
+       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
        docstring const str = subst(fmt, from_ascii("%1$s"), arg1);
        return subst(str, from_ascii("%%"), from_ascii("%"));
 }
@@ -1057,7 +1146,7 @@ docstring bformat(docstring const & fmt, docstring arg1)
 template<>
 docstring bformat(docstring const & fmt, char * arg1)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$s")));
+       LASSERT(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("%"));
 }
@@ -1066,8 +1155,8 @@ docstring bformat(docstring const & fmt, char * arg1)
 template<>
 docstring bformat(docstring const & fmt, docstring arg1, docstring arg2)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$s")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%2$s")));
+       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
+       LASSERT(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("%"));
@@ -1077,8 +1166,8 @@ docstring bformat(docstring const & fmt, docstring arg1, docstring arg2)
 template<>
 docstring bformat(docstring const & fmt, char const * arg1, docstring arg2)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$s")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%2$s")));
+       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
+       LASSERT(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);
        return subst(str, from_ascii("%%"), from_ascii("%"));
@@ -1088,8 +1177,8 @@ docstring bformat(docstring const & fmt, char const * arg1, docstring arg2)
 template<>
 docstring bformat(docstring const & fmt, int arg1, int arg2)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$d")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%2$d")));
+       LASSERT(contains(fmt, from_ascii("%1$d")), /**/);
+       LASSERT(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("%"));
@@ -1099,9 +1188,9 @@ docstring bformat(docstring const & fmt, int arg1, int arg2)
 template<>
 docstring bformat(docstring const & fmt, docstring arg1, docstring arg2, docstring arg3)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$s")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%2$s")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%3$s")));
+       LASSERT(contains(fmt, from_ascii("%1$s")), /**/);
+       LASSERT(contains(fmt, from_ascii("%2$s")), /**/);
+       LASSERT(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);
@@ -1113,10 +1202,10 @@ template<>
 docstring bformat(docstring const & fmt,
               docstring arg1, docstring arg2, docstring arg3, docstring arg4)
 {
-       BOOST_ASSERT(contains(fmt, from_ascii("%1$s")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%2$s")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%3$s")));
-       BOOST_ASSERT(contains(fmt, from_ascii("%4$s")));
+       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")), /**/);
        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);