]> git.lyx.org Git - features.git/commitdiff
Make libQtCore a support library like boost and implement encoding conversion
authorGeorg Baum <Georg.Baum@post.rwth-aachen.de>
Tue, 12 Dec 2006 20:19:46 +0000 (20:19 +0000)
committerGeorg Baum <Georg.Baum@post.rwth-aachen.de>
Tue, 12 Dec 2006 20:19:46 +0000 (20:19 +0000)
from/to the local 8bit encoding with it.
Only the autotools build system is updated, scons and cmake users need to
add qt4 cpp flags when compiling libsupport, and link libsupport against
libQtCore.

* src/frontends/qt4/qt_helpers.[Ch]
(toqstr, qchar_to_ucs4, ucs4_to_qchar, ucs4_to_qstring,
 qstring_to_ucs4, fromqstr): Move these qstring conversion functions
from here ...

* src/support/qstring_helpers.[Ch] ... to these new files

* src/support/docstring.[Ch]
(from_local8bit): new conversion function from local 8bit encoding
to ucs4
(to_local8bit): new conversion function from ucs4 to local 8bit
encoding to ucs4
(to_local8bit_failure): exception that is thrown by to_local8bit if
the argument cannot be converted to the local encoding

* src/support/filename.C
(FileName::toFilesystemEncoding): implement with the help of QFile

* src/support/Makefile.am: Add new files, qt4 cpp flags and link
against libQtCore

* src/client/client.C: Convert commandline input from local encoding
to ucs4. Convert stuff that is sent to to the server to utf8,
because LyX interprets it as utf8 on the other end of the pipe.

* src/lyx_main.C
(LyX::exec): convert commandline input from local encoding to utf8
(LyX::init): ditto
(LyX::easyParse): ditto

* development/scons/scons_manifest.py: Add new files

* config/qt4.m4: Define new variables QT4_CORE_INCLUDES,
QT4_CORE_LDFLAGS and QT4_CORE_LIB

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16257 a592a061-630c-0410-9148-cb99ea01b6c8

12 files changed:
config/qt4.m4
development/scons/scons_manifest.py
src/client/client.C
src/frontends/qt4/qt_helpers.C
src/frontends/qt4/qt_helpers.h
src/lyx_main.C
src/support/Makefile.am
src/support/docstring.C
src/support/docstring.h
src/support/filename.C
src/support/qstring_helpers.C [new file with mode: 0644]
src/support/qstring_helpers.h [new file with mode: 0644]

index 098845f8ba9ddcf97efc26cb170bab98026c3b14..6414bbaabb4e697ba58159887899f1427f8011d8 100644 (file)
@@ -28,6 +28,14 @@ AC_DEFUN([QT4_CHECK_COMPILE],
                AC_LANG_CPLUSPLUS
                SAVE_CXXFLAGS=$CXXFLAGS
                CXXFLAGS="$CXXFLAGS $QT4_INCLUDES $QT4_LDFLAGS"
+               for libname in '-lQtCore -lQtCore4'
+               do
+                       QT4_TRY_LINK($libname)
+                       if test -n "$qt4_cv_libname"; then
+                               QT4_CORE_LIB="$qt4_cv_libname"
+                               break;
+                       fi
+               done
                for libname in '-lQtCore -lQtGui' \
                               '-lQtCore4 -lQtGui4'
                do
@@ -142,6 +150,15 @@ AC_DEFUN([QT4_DO_PKG_CONFIG],
          PKG_CONFIG_PATH=$qt4_cv_dir/lib:$PKG_CONFIG_PATH
          export PKG_CONFIG_PATH
        fi
+       PKG_CHECK_MODULES(QT4_CORE, QtCore)
+       if test "$pkg_failed" == "no" ; then
+               QT4_CORE_INCLUDES=$QT4_CORE_CFLAGS
+               AC_SUBST(QT4_CORE_INCLUDES)
+               QT4_CORE_LDFLAGS=`$PKG_CONFIG --libs-only-L QtCore`
+               AC_SUBST(QT4_CORE_LDFLAGS)
+               QT4_CORE_LIB=`$PKG_CONFIG --libs-only-l QtCore`
+               AC_SUBST(QT4_CORE_LIB)
+       fi
        PKG_CHECK_MODULES(QT4_FRONTEND, QtCore QtGui)
        if test "$pkg_failed" == "no" ; then
                QT4_INCLUDES=$QT4_FRONTEND_CFLAGS
@@ -153,8 +170,6 @@ AC_DEFUN([QT4_DO_PKG_CONFIG],
                AC_SUBST(QT4_VERSION)
                QT4_LIB=`$PKG_CONFIG --libs-only-l QtCore QtGui`
                AC_SUBST(QT4_LIB)
-       else
-               QT4_DO_MANUAL_CONFIG
        fi
        PKG_CONFIG_PATH=$save_PKG_CONFIG_PATH
 ])
@@ -164,22 +179,29 @@ AC_DEFUN([QT4_DO_MANUAL_CONFIG],
        dnl flags for compilation
        QT4_INCLUDES=
        QT4_LDFLAGS=
+       QT4_CORE_INCLUDES=
+       QT4_CORE_LDFLAGS=
        if test -n "$qt4_cv_includes"; then
                QT4_INCLUDES="-I$qt4_cv_includes"
                for i in Qt QtCore QtGui; do
                        QT4_INCLUDES="$QT4_INCLUDES -I$qt4_cv_includes/$i"
                done
+               QT4_CORE_INCLUDES="-I$qt4_cv_includes -I$qt4_cv_includes/QtCore"
        fi
        if test -n "$qt4_cv_libraries"; then
                QT4_LDFLAGS="-L$qt4_cv_libraries"
+               QT4_CORE_LDFLAGS="-L$qt4_cv_libraries"
        fi
        AC_SUBST(QT4_INCLUDES)
+       AC_SUBST(QT4_CORE_INCLUDES)
        AC_SUBST(QT4_LDFLAGS)
+       AC_SUBST(QT4_CORE_LDFLAGS)
 
        QT4_CHECK_COMPILE
 
        QT4_LIB=$qt4_cv_libname;
        AC_SUBST(QT4_LIB)
+       AC_SUBST(QT4_CORE_LIB)
 
        if test -n "$qt4_cv_libname"; then
                QT4_GET_VERSION
index 38d8cb323c04149f6930df8ed96b83b1fc1d2a80..b401cdd1a7cd37a8f6b0a9c2d6f3cffac40c15fe 100644 (file)
@@ -117,6 +117,7 @@ src_support_header_files = Split('''
     os_win32.h
     package.h
     path.h
+    qstring_helpers.h
     socktools.h
     std_istream.h
     std_ostream.h
@@ -155,6 +156,7 @@ src_support_files = Split('''
     os.C
     package.C
     path.C
+    qstring_helpers.C
     rename.C
     socktools.C
     systemcall.C
index 424f78623480d7588b0e1811514e441207b5e575..5b116d410318a20ae198d3ebc2835c397da7e019 100644 (file)
@@ -335,7 +335,7 @@ void LyXDataSocket::writeln(string const & line)
 // Class CmdLineParser -------------------------------------------------------
 class CmdLineParser {
 public:
-       typedef int (*optfunc)(vector<char *> const & args);
+       typedef int (*optfunc)(vector<docstring> const & args);
        std::map<string, optfunc> helper;
        std::map<string, bool> isset;
        bool parse(int, char * []);
@@ -347,12 +347,12 @@ bool CmdLineParser::parse(int argc, char * argv[])
 {
        int opt = 1;
        while (opt < argc) {
-               vector<char *> args;
+               vector<docstring> args;
                if (helper[argv[opt]]) {
                        isset[argv[opt]] = true;
                        int arg = opt + 1;
                        while ((arg < argc) && (!helper[argv[arg]])) {
-                               args.push_back(argv[arg]);
+                               args.push_back(from_local8bit(argv[arg]));
                                ++arg;
                        }
                        int taken = helper[argv[opt]](args);
@@ -407,16 +407,16 @@ void usage()
 }
 
 
-int h(vector<char *> const &)
+int h(vector<docstring> const &)
 {
        usage();
        exit(0);
 }
 
 
-string clientName(support::itoa(::getppid()) + ">" + support::itoa(::getpid()));
+docstring clientName(from_ascii(support::itoa(::getppid()) + ">" + support::itoa(::getpid())));
 
-int n(vector<char *> const & arg)
+int n(vector<docstring> const & arg)
 {
        if (arg.size() < 1) {
                cerr << "lyxclient: The option -n requires 1 argument."
@@ -428,10 +428,10 @@ int n(vector<char *> const & arg)
 }
 
 
-string singleCommand;
+docstring singleCommand;
 
 
-int c(vector<char *> const & arg)
+int c(vector<docstring> const & arg)
 {
        if (arg.size() < 1) {
                cerr << "lyxclient: The option -c requires 1 argument."
@@ -443,7 +443,7 @@ int c(vector<char *> const & arg)
 }
 
 
-int g(vector<char *> const & arg)
+int g(vector<docstring> const & arg)
 {
        if (arg.size() < 2) {
                cerr << "lyxclient: The option -g requires 2 arguments."
@@ -451,17 +451,17 @@ int g(vector<char *> const & arg)
                return -1;
        }
        singleCommand = "LYXCMD:server-goto-file-row "
-               + string(arg[0]) + ' '
-               + string(arg[1]);
+               + arg[0] + ' '
+               + arg[1];
        return 2;
 }
 
 
-// 0 if LYXSOCKET is not set in the environment
-char * serverAddress = getenv("LYXSOCKET");
+// empty if LYXSOCKET is not set in the environment
+docstring serverAddress;
 
 
-int a(vector<char *> const & arg)
+int a(vector<docstring> const & arg)
 {
        if (arg.size() < 1) {
                cerr << "lyxclient: The option -a requires 1 argument."
@@ -474,10 +474,10 @@ int a(vector<char *> const & arg)
 }
 
 
-string mainTmp("/tmp");
+docstring mainTmp(from_ascii("/tmp"));
 
 
-int t(vector<char *> const & arg)
+int t(vector<docstring> const & arg)
 {
        if (arg.size() < 1) {
                cerr << "lyxclient: The option -t requires 1 argument."
@@ -492,14 +492,14 @@ int t(vector<char *> const & arg)
 string serverPid; // Init to empty string
 
 
-int p(vector<char *> const & arg)
+int p(vector<docstring> const & arg)
 {
        if (arg.size() < 1) {
                cerr << "lyxclient: The option -p requires 1 argument."
                     << endl;
                return -1;
        }
-       serverPid = arg[0];
+       serverPid = to_ascii(arg[0]);
        return 1;
 }
 
@@ -514,6 +514,10 @@ int main(int argc, char * argv[])
        using namespace lyx;
        lyxerr.rdbuf(cerr.rdbuf());
 
+       char const * const lyxsocket = getenv("LYXSOCKET");
+       if (lyxsocket)
+               cmdline::serverAddress = from_local8bit(lyxsocket);
+
        CmdLineParser args;
        args.helper["-h"] = cmdline::h;
        args.helper["-c"] = cmdline::c;
@@ -533,17 +537,17 @@ int main(int argc, char * argv[])
 
        scoped_ptr<LyXDataSocket> server;
 
-       if (cmdline::serverAddress) {
-               server.reset(new LyXDataSocket(cmdline::serverAddress));
+       if (!cmdline::serverAddress.empty()) {
+               server.reset(new LyXDataSocket(to_utf8(cmdline::serverAddress)));
                if (!server->connected()) {
                        cerr << "lyxclient: " << "Could not connect to "
-                            << cmdline::serverAddress << endl;
+                            << to_utf8(cmdline::serverAddress) << endl;
                        return EXIT_FAILURE;
                }
        } else {
                // We have to look for an address.
                // serverPid can be empty.
-               vector<fs::path> addrs = support::lyxSockets(cmdline::mainTmp, cmdline::serverPid);
+               vector<fs::path> addrs = support::lyxSockets(to_utf8(cmdline::mainTmp), cmdline::serverPid);
                vector<fs::path>::const_iterator addr = addrs.begin();
                vector<fs::path>::const_iterator end = addrs.end();
                for (; addr != end; ++addr) {
@@ -570,7 +574,7 @@ int main(int argc, char * argv[])
        string answer;
 
        // Send greeting
-       server->writeln("HELLO:" + cmdline::clientName);
+       server->writeln("HELLO:" + to_utf8(cmdline::clientName));
        // wait at most 2 seconds until server responds
        iowatch.wait(2.0);
        if (iowatch.isset(serverfd) && server->readln(answer)) {
@@ -585,7 +589,7 @@ int main(int argc, char * argv[])
        }
 
        if (args.isset["-g"] || args.isset["-c"]) {
-               server->writeln(cmdline::singleCommand);
+               server->writeln(to_utf8(cmdline::singleCommand));
                iowatch.wait(2.0);
                if (iowatch.isset(serverfd) && server->readln(answer)) {
                        cout << answer;
index d6b5f0b8340119e701e58604c5d7a8f5f231957c..c6abe3f27108c886a33a7aeeef156de66ceb2861 100644 (file)
 
 namespace lyx {
 
-
-using lyx::support::isStrDbl;
-using lyx::char_type;
-using lyx::docstring;
+using support::isStrDbl;
 
 using std::vector;
 using std::make_pair;
@@ -111,36 +108,6 @@ void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
 }
 
 
-#if QT_VERSION < 0x040200
-// We use QString::fromUcs4 in Qt 4.2 and higher
-QString const toqstr(docstring const & str)
-{
-       QString s;
-       int i = static_cast<int>(str.size()); 
-       s.resize(i);
-       for (; --i >= 0;)
-               s[i] = ucs4_to_qchar(str[i]);
-       return s;
-}
-#endif
-
-
-docstring const qstring_to_ucs4(QString const & qstr)
-{
-#if QT_VERSION >= 0x040200
-       QVector<uint> const ucs4 = qstr.toUcs4();
-       return docstring(ucs4.begin(), ucs4.end());
-#else
-       // This does not properly convert surrogate pairs
-       int const ls = qstr.size();
-       docstring ucs4;
-       for (int i = 0; i < ls; ++i)
-               ucs4 += static_cast<char_type>(qstr[i].unicode());
-       return ucs4;
-#endif
-}
-
-
 QString const qt_(char const * str, const char *)
 {
        return toqstr(_(str));
@@ -153,12 +120,6 @@ QString const qt_(string const & str)
 }
 
 
-string const fromqstr(QString const & str)
-{
-       return str.isEmpty() ? string() : string(str.toUtf8());
-}
-
-
 docstring const formatted(docstring const & text, int w)
 {
        docstring sout;
index 463e4eb7c4f77f42b4b1c2a97757283f63f016dc..5c52b1fdfac128e5c120df3006c81fe36904819b 100644 (file)
 
 #include "lyxlength.h"
 #include "support/docstring.h"
+#include "support/qstring_helpers.h"
 
-#include <QChar>
 #include <QString>
 
-#include <vector>
 #include <utility>
-#include <boost/assert.hpp>
 
 class QComboBox;
 class QLineEdit;
@@ -46,103 +44,6 @@ void lengthToWidgets(QLineEdit * input, LengthCombo * combo,
 docstring const formatted(docstring const & text, int w = 80);
 
 
-/**
- * toqstr - convert a UTF8 encoded char * into a QString
- *
- * This should not be used, since all possibly non-ASCII stuff should be
- * stored in a docstring.
- */
-inline QString const toqstr(char const * str)
-{
-       return QString::fromUtf8(str);
-}
-
-
-/**
- * toqstr - convert a UTF8 encoded std::string into a QString
- *
- * This should not be used, since all possibly non-ASCII stuff should be
- * stored in a docstring.
- */
-inline QString const toqstr(std::string const & str)
-{
-       return toqstr(str.c_str());
-}
-
-
-/**
- * Convert a QChar into a UCS4 character.
- * This is a hack (it does only make sense for the common part of the UCS4
- * and UTF16 encodings) and should not be used.
- * This does only exist because of performance reasons (a real conversion
- * using iconv is too slow on windows).
- */
-inline char_type const qchar_to_ucs4(QChar const & qchar)
-{
-       return static_cast<char_type>(qchar.unicode());
-}
-
-
-/**
- * Convert a UCS4 character into a QChar.
- * This is a hack (it does only make sense for the common part of the UCS4
- * and UTF16 encodings) and should not be used.
- * This does only exist because of performance reasons (a real conversion
- * using iconv is too slow on windows).
- */
-inline QChar const ucs4_to_qchar(char_type const ucs4)
-{
-       // FIXME: The following cast is not a real conversion but it work
-       // for the ucs2 subrange of unicode. Instead of an assertion we should
-       // return some special characters that indicates that its display is
-       // not supported.
-       BOOST_ASSERT(ucs4 < 65536);
-       return QChar(static_cast<unsigned short>(ucs4));
-}
-
-
-/**
- * toqstr - convert a UCS4 encoded docstring into a QString
- *
- * This is the preferred method of converting anything that possibly
- * contains non-ASCII stuff to QString.
- */
-#if QT_VERSION >= 0x040200
-inline QString const toqstr(docstring const & ucs4)
-{
-       // If possible we let qt do the work, since this version does not
-       // need to be superfast.
-       return QString::fromUcs4(reinterpret_cast<uint const *>(ucs4.data()), ucs4.length());
-}
-#else
-QString const toqstr(docstring const & ucs4);
-#endif
-
-
-/**
- * ucs4_to_qstring - convert a UCS4 encoded char_type * into a QString
- *
- * This is a hack for the painter and font metrics and should not be used
- * elsewhere. Since it uses ucs4_to_qchar it has the same limitations.
- */
-inline void ucs4_to_qstring(char_type const * str, size_t ls, QString & s)
-{
-       int i = static_cast<int>(ls);
-       s.resize(i);
-       for (; --i >= 0;)
-               s[i] = ucs4_to_qchar(str[i]);
-}
-
-
-/**
- * qstring_to_ucs4 - convert a QString into a UCS4 encoded docstring
- *
- * This is the preferred method of converting anything that possibly
- * contains non-ASCII stuff to docstring.
- */
-docstring const qstring_to_ucs4(QString const & qstr);
-
-
 /**
  * qt_ - i18nize string and convert to QString
  *
@@ -158,15 +59,6 @@ QString const qt_(char const * str, const char * comment = 0);
  */
 QString const qt_(std::string const & str);
 
-
-/**
- * fromqstr - convert a QString into a UTF8 encoded std::string
- *
- * This should not be used except for output to lyxerr, since all possibly
- * non-ASCII stuff should be stored in a docstring.
- */
-std::string const fromqstr(QString const & str);
-
 } // namespace lyx
 
 #endif // QTHELPERS_H
index ca36f2c081c1e808128c08db1b7a632e9178e1d7..cccd96a80576caeb32349fa4f689e045be57e1e0 100644 (file)
@@ -332,8 +332,9 @@ int LyX::exec(int & argc, char * argv[])
        // we need to parse for "-dbg" and "-help"
        easyParse(argc, argv);
 
-       support::init_package(argv[0], cl_system_support, cl_user_support,
-                                  support::top_build_dir_is_one_level_up);
+       support::init_package(to_utf8(from_local8bit(argv[0])),
+                             cl_system_support, cl_user_support,
+                             support::top_build_dir_is_one_level_up);
 
        if (!use_gui) {
                // FIXME: create a ConsoleApplication
@@ -481,7 +482,8 @@ int LyX::init(int & argc, char * argv[])
        for (int argi = argc - 1; argi >= 1; --argi) {
                // get absolute path of file and add ".lyx" to
                // the filename if necessary
-               pimpl_->files_to_load_.push_back(fileSearch(string(), os::internal_path(argv[argi]), "lyx"));
+               pimpl_->files_to_load_.push_back(fileSearch(string(),
+                       os::internal_path(to_utf8(from_local8bit(argv[argi]))), "lyx"));
        }
 
        if (first_start)
@@ -1333,8 +1335,8 @@ void LyX::easyParse(int & argc, char * argv[])
                if (it == cmdmap.end())
                        continue;
 
-               string arg((i + 1 < argc) ? argv[i + 1] : "");
-               string arg2((i + 2 < argc) ? argv[i + 2] : "");
+               string const arg((i + 1 < argc) ? to_utf8(from_local8bit(argv[i + 1])) : string());
+               string const arg2((i + 2 < argc) ? to_utf8(from_local8bit(argv[i + 2])) : string());
 
                int const remove = 1 + it->second(arg, arg2);
 
index b3c3f775e37265c0c77f7c0b4884d1f2dc70df33..2226954e6f2bb8585cb31e00252657e3ecb6db44 100644 (file)
@@ -9,11 +9,13 @@ EXTRA_DIST = package.C.in pch.h \
 
 noinst_LTLIBRARIES = libsupport.la
 
-libsupport_la_LIBADD = $(LIBSHLWAPI)
+libsupport_la_LIBADD = $(LIBSHLWAPI) $(QT4_CORE_LIB)
+libsupport_la_LDFLAGS = $(QT4_CORE_LDFLAGS)
 
 BUILT_SOURCES = $(PCH_FILE) package.C
 
 AM_CPPFLAGS += $(PCH_FLAGS) -I$(srcdir)/.. $(BOOST_INCLUDES)
+AM_CPPFLAGS += $(QT4_CPPFLAGS) $(QT4_CORE_INCLUDES)
 
 libsupport_la_SOURCES = \
        FileMonitor.h \
@@ -67,6 +69,8 @@ libsupport_la_SOURCES = \
        path.h \
        package.C \
        package.h \
+       qstring_helpers.C \
+       qstring_helpers.h \
        rename.C \
        socktools.C \
        socktools.h \
index 5e8d05f715bc852294f085f68a0402c94f624d11..3c1c80abb20fcd37d713854b0ec4f4c066c6426d 100644 (file)
@@ -11,6 +11,7 @@
 #include <config.h>
 
 #include "docstring.h"
+#include "qstring_helpers.h"
 #include "unicode.h"
 
 #include <locale>
@@ -91,6 +92,30 @@ std::string const to_utf8(docstring const & ucs4)
 }
 
 
+docstring const from_local8bit(std::string const & s)
+{
+       return qstring_to_ucs4(QString::fromLocal8Bit(s.data(), s.length()));
+}
+
+
+const char* to_local8bit_failure::what() const throw()
+{
+       return "A string could not be converted from unicode to the local 8 bit encoding.";
+}
+
+
+std::string const to_local8bit(docstring const & s)
+{
+       // This conversion can fail, depending on input.
+       if (s.empty())
+               return std::string();
+       QByteArray const local = toqstr(s).toLocal8Bit();
+       if (local.size() == 0)
+               throw to_local8bit_failure();
+       return std::string(local.begin(), local.end());
+}
+
+
 bool operator==(lyx::docstring const & l, char const * r)
 {
        int const len = l.length();
index 629d77e21f9cba8a72d60b9dbbe83b22ebd3622c..0f097063076ee971fe4a6abc5f9b0161084bd91d 100644 (file)
@@ -16,6 +16,7 @@
 #include "support/types.h"
 
 #include <string>
+#include <typeinfo>
 
 namespace lyx {
 
@@ -37,6 +38,24 @@ docstring const from_utf8(std::string const &);
 /// Creates a UTF8 string from a docstring. This should go eventually.
 std::string const to_utf8(docstring const &);
 
+/// convert \p s from the encoding of the locale to ucs4.
+docstring const from_local8bit(std::string const & s);
+
+/// Exception thrown by to_local8bit if the string could not be converted
+class to_local8bit_failure : public std::bad_cast {
+public:
+       to_local8bit_failure() throw() : std::bad_cast() {}
+       virtual ~to_local8bit_failure() throw() {}
+       virtual const char* what() const throw();
+};
+
+/**
+ * Convert \p s from ucs4 to the encoding of the locale.
+ * This may fail and throw an exception, the caller is expected to act
+ * appropriately.
+ */
+std::string const to_local8bit(docstring const & s);
+
 /// Compare a docstring with a C string of ASCII characters
 bool operator==(lyx::docstring const &, char const *);
 
index 8762717ec1a98a74fd0ebc8322f8b6fcb0a5e67e..8b8a4aee57b8b5d0a0185a8c22f3cf56f338f596 100644 (file)
@@ -14,6 +14,9 @@
 #include "support/filetools.h"
 #include "support/lstrings.h"
 #include "support/os.h"
+#include "support/qstring_helpers.h"
+
+#include <QFile>
 
 #include <boost/assert.hpp>
 
@@ -62,8 +65,8 @@ void FileName::erase()
 
 string const FileName::toFilesystemEncoding() const
 {
-       // FIXME UNICODE: correct encoding not implemented yet
-       return name_;
+       QByteArray const encoded = QFile::encodeName(toqstr(name_));
+       return string(encoded.begin(), encoded.end());
 }
 
 
diff --git a/src/support/qstring_helpers.C b/src/support/qstring_helpers.C
new file mode 100644 (file)
index 0000000..d1a2ef8
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * \file qstring_helpers.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Dekel Tsur
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "qstring_helpers.h"
+
+#include <QVector>
+
+
+namespace lyx {
+
+using std::string;
+
+#if QT_VERSION < 0x040200
+// We use QString::fromUcs4 in Qt 4.2 and higher
+QString const toqstr(docstring const & str)
+{
+       QString s;
+       int i = static_cast<int>(str.size()); 
+       s.resize(i);
+       for (; --i >= 0;)
+               s[i] = ucs4_to_qchar(str[i]);
+       return s;
+}
+#endif
+
+
+docstring const qstring_to_ucs4(QString const & qstr)
+{
+#if QT_VERSION >= 0x040200
+       QVector<uint> const ucs4 = qstr.toUcs4();
+       return docstring(ucs4.begin(), ucs4.end());
+#else
+       // This does not properly convert surrogate pairs
+       int const ls = qstr.size();
+       docstring ucs4;
+       for (int i = 0; i < ls; ++i)
+               ucs4 += static_cast<char_type>(qstr[i].unicode());
+       return ucs4;
+#endif
+}
+
+
+string const fromqstr(QString const & str)
+{
+       return str.isEmpty() ? string() : string(str.toUtf8());
+}
+
+} // namespace lyx
diff --git a/src/support/qstring_helpers.h b/src/support/qstring_helpers.h
new file mode 100644 (file)
index 0000000..d1525de
--- /dev/null
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+/**
+ * \file qstring_helpers.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Dekel Tsur
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef QSTRING_HELPERS_H
+#define QSTRING_HELPERS_H
+
+#include "support/docstring.h"
+
+#include <QChar>
+#include <QString>
+
+#include <boost/assert.hpp>
+
+namespace lyx {
+
+/**
+ * toqstr - convert a UTF8 encoded char * into a QString
+ *
+ * This should not be used, since all possibly non-ASCII stuff should be
+ * stored in a docstring.
+ */
+inline QString const toqstr(char const * str)
+{
+       return QString::fromUtf8(str);
+}
+
+
+/**
+ * toqstr - convert a UTF8 encoded std::string into a QString
+ *
+ * This should not be used, since all possibly non-ASCII stuff should be
+ * stored in a docstring.
+ */
+inline QString const toqstr(std::string const & str)
+{
+       return toqstr(str.c_str());
+}
+
+
+/**
+ * Convert a QChar into a UCS4 character.
+ * This is a hack (it does only make sense for the common part of the UCS4
+ * and UTF16 encodings) and should not be used.
+ * This does only exist because of performance reasons (a real conversion
+ * using iconv is too slow on windows).
+ */
+inline char_type const qchar_to_ucs4(QChar const & qchar)
+{
+       return static_cast<char_type>(qchar.unicode());
+}
+
+
+/**
+ * Convert a UCS4 character into a QChar.
+ * This is a hack (it does only make sense for the common part of the UCS4
+ * and UTF16 encodings) and should not be used.
+ * This does only exist because of performance reasons (a real conversion
+ * using iconv is too slow on windows).
+ */
+inline QChar const ucs4_to_qchar(char_type const ucs4)
+{
+       // FIXME: The following cast is not a real conversion but it work
+       // for the ucs2 subrange of unicode. Instead of an assertion we should
+       // return some special characters that indicates that its display is
+       // not supported.
+       BOOST_ASSERT(ucs4 < 65536);
+       return QChar(static_cast<unsigned short>(ucs4));
+}
+
+
+/**
+ * toqstr - convert a UCS4 encoded docstring into a QString
+ *
+ * This is the preferred method of converting anything that possibly
+ * contains non-ASCII stuff to QString.
+ */
+#if QT_VERSION >= 0x040200
+inline QString const toqstr(docstring const & ucs4)
+{
+       // If possible we let qt do the work, since this version does not
+       // need to be superfast.
+       return QString::fromUcs4(reinterpret_cast<uint const *>(ucs4.data()), ucs4.length());
+}
+#else
+QString const toqstr(docstring const & ucs4);
+#endif
+
+
+/**
+ * ucs4_to_qstring - convert a UCS4 encoded char_type * into a QString
+ *
+ * This is a hack for the painter and font metrics and should not be used
+ * elsewhere. Since it uses ucs4_to_qchar it has the same limitations.
+ */
+inline void ucs4_to_qstring(char_type const * str, size_t ls, QString & s)
+{
+       int i = static_cast<int>(ls);
+       s.resize(i);
+       for (; --i >= 0;)
+               s[i] = ucs4_to_qchar(str[i]);
+}
+
+
+/**
+ * qstring_to_ucs4 - convert a QString into a UCS4 encoded docstring
+ *
+ * This is the preferred method of converting anything that possibly
+ * contains non-ASCII stuff to docstring.
+ */
+docstring const qstring_to_ucs4(QString const & qstr);
+
+
+/**
+ * fromqstr - convert a QString into a UTF8 encoded std::string
+ *
+ * This should not be used except for output to lyxerr, since all possibly
+ * non-ASCII stuff should be stored in a docstring.
+ */
+std::string const fromqstr(QString const & str);
+
+} // namespace lyx
+
+#endif // QSTRING_HELPERS_H