Am Donnerstag, 7. Dezember 2006 18:09 schrieb Andre Poenitz:

> I am able to change my opinion when reality proves me wrong.

Sure, only idiots never change their opinion. I was surprised because to me 
the current status does not look much different from that of 6 weeks ago. 
And to avoid misunderstanding: This does not include the many bugs that 
have been fixed, but rather the cost of the abstraction from qt4 in the 
core.

> > Coincidentally I am seriously thinking to use QFile::encodeName for the 
> > implementation of FileName::toFilesystemEncoding, because it does 
exactly 
> > what is needed.
> 
> The whole file name business is pretty much reinventing the wheel,
> and so is the session stuff and preference management.  Same goes for
> external processes when I think about it, but that does not seem to
> suck much resources nowadays...

Now you ignore the fact that all this stuff (except sessions) exists 
already from the multiple-frontend times, so I don't see much reinventing 
the wheel here. I don't consider introducing the FileName class 
reinventing the wheel either, since it only uses existing code. The 
difficult part was the correct conversion from string, considering 
relative and absolute names.
Of course we could replace the FileName class (+ several of the filetools 
functions) by QFileInfo (or I could have done it in the first place, would 
not make much difference). That would be pretty easy apart from the fact 
that QFileInfo allows relative names, and relative names are dnagerous in 
our case, since they could refer to many possible directories.

Now to the important stuff:
The attached patch makes non-ascii filenames work for me in a latin1 
locale. You can ignore the client part, that has nothing to do with 
filenames, but it shows thet some work is needed there as well.
This patch uses qt to implement FileName::toFilesystemEncoding() and the 
new functions from_local8bit() and to_local8bit().
I don't want to copy the code from qt, since it is really messy, and I 
don't see any point in not using what qt provides. The patch is not very 
clean (see qstring_to_ucs4), I would like to use something similar.

What do others think? Please not that this patch does only introduce Qt in 
the implementation of the support library, so if we should get more 
frontends in the future it would be easy to separate this out (but of 
course the new frontend would need to provide similar functionality).


Georg
Index: src/frontends/qt4/qt_helpers.C
===================================================================
--- src/frontends/qt4/qt_helpers.C	(Revision 16207)
+++ src/frontends/qt4/qt_helpers.C	(Arbeitskopie)
@@ -125,22 +125,6 @@ QString const toqstr(docstring const & 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));
Index: src/support/docstring.C
===================================================================
--- src/support/docstring.C	(Revision 16207)
+++ src/support/docstring.C	(Arbeitskopie)
@@ -13,6 +13,10 @@
 #include "docstring.h"
 #include "unicode.h"
 
+#include "frontends/qt4/qt_helpers.h"
+
+#include <QVector>
+
 #include <locale>
 #include <iostream>
 
@@ -91,6 +95,35 @@ std::string const to_utf8(docstring cons
 }
 
 
+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
+}
+
+
+docstring const from_local8bit(std::string const & s)
+{
+	return qstring_to_ucs4(QString::fromLocal8Bit(s.data(), s.length()));
+}
+
+
+std::string const to_local8bit(docstring const & s)
+{
+	QByteArray const local = toqstr(s).toLocal8Bit();
+	return std::string(local.begin(), local.end());
+}
+
+
 bool operator==(lyx::docstring const & l, char const * r)
 {
 	int const len = l.length();
Index: src/support/filename.C
===================================================================
--- src/support/filename.C	(Revision 16207)
+++ src/support/filename.C	(Arbeitskopie)
@@ -15,6 +15,12 @@
 #include "support/lstrings.h"
 #include "support/os.h"
 
+#include "debug.h"
+
+#include "frontends/qt4/qt_helpers.h"
+
+#include <QFile>
+
 #include <boost/assert.hpp>
 
 #include <map>
@@ -62,8 +68,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());
 }
 
 
Index: src/support/docstring.h
===================================================================
--- src/support/docstring.h	(Revision 16207)
+++ src/support/docstring.h	(Arbeitskopie)
@@ -37,6 +37,12 @@ docstring const from_utf8(std::string co
 /// 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);
+
+/// convert \p s from ucs4 to the encoding of the locale.
+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: src/support/Makefile.am
===================================================================
--- src/support/Makefile.am	(Revision 16207)
+++ src/support/Makefile.am	(Arbeitskopie)
@@ -9,11 +9,13 @@ EXTRA_DIST = package.C.in pch.h \
 
 noinst_LTLIBRARIES = libsupport.la
 
-libsupport_la_LIBADD = $(LIBSHLWAPI)
+libsupport_la_LIBADD = $(LIBSHLWAPI) $(QT4_LIB)
+libsupport_la_LDFLAGS = $(QT4_LDFLAGS)
 
 BUILT_SOURCES = $(PCH_FILE) package.C
 
 AM_CPPFLAGS += $(PCH_FLAGS) -I$(srcdir)/.. $(BOOST_INCLUDES)
+AM_CPPFLAGS += $(QT4_CPPFLAGS) $(QT4_INCLUDES)
 
 libsupport_la_SOURCES = \
 	FileMonitor.h \
Index: src/client/client.C
===================================================================
--- src/client/client.C	(Revision 16207)
+++ src/client/client.C	(Arbeitskopie)
@@ -335,7 +335,7 @@ void LyXDataSocket::writeln(string const
 // 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
 {
 	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: src/lyx_main.C
===================================================================
--- src/lyx_main.C	(Revision 16207)
+++ src/lyx_main.C	(Arbeitskopie)
@@ -332,7 +332,7 @@ 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::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) {
@@ -481,7 +481,7 @@ 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 +1333,8 @@ void LyX::easyParse(int & argc, char * a
 		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);
 

Reply via email to