]> git.lyx.org Git - features.git/commitdiff
Rename .C ==> .cpp for files in src/client, part two
authorBo Peng <bpeng@lyx.org>
Thu, 26 Apr 2007 04:50:47 +0000 (04:50 +0000)
committerBo Peng <bpeng@lyx.org>
Thu, 26 Apr 2007 04:50:47 +0000 (04:50 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@18021 a592a061-630c-0410-9148-cb99ea01b6c8

12 files changed:
src/client/Messages.cpp [new file with mode: 0644]
src/client/Messages.h [new file with mode: 0644]
src/client/boost.C [deleted file]
src/client/boost.cpp [new file with mode: 0644]
src/client/client.C [deleted file]
src/client/client.cpp [new file with mode: 0644]
src/client/debug.C [deleted file]
src/client/debug.cpp [new file with mode: 0644]
src/client/gettext.C [deleted file]
src/client/gettext.cpp [new file with mode: 0644]
src/client/messages.C [deleted file]
src/client/messages.h [deleted file]

diff --git a/src/client/Messages.cpp b/src/client/Messages.cpp
new file mode 100644 (file)
index 0000000..04f1d49
--- /dev/null
@@ -0,0 +1,197 @@
+/* \file Messages.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "Messages.h"
+#include "debug.h"
+#include "support/filetools.h"
+#include "support/package.h"
+#include "support/unicode.h"
+
+#include <boost/current_function.hpp>
+
+#include <cerrno>
+
+
+namespace lyx {
+
+using lyx::support::package;
+using std::endl;
+using std::string;
+
+
+#ifdef ENABLE_NLS
+
+
+#if 0
+
+-#include <locale>
+
+// This version of the Pimpl utilizes the message capability of
+// libstdc++ that is distributed with GNU G++.
+class Messages::Pimpl {
+public:
+       typedef std::messages<char>::catalog catalog;
+
+       Pimpl(string const & l)
+               : lang_(l),
+                 loc_gl(lang_.c_str()),
+                 mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
+       {
+               //lyxerr << "Messages: language(" << l
+               //       << ") in dir(" << dir << ")" << std::endl;
+
+               string const locale_dir = package().locale_dir().toFilesystemEncoding();
+               cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
+
+       }
+
+       ~Pimpl()
+       {
+               mssg_gl.close(cat_gl);
+       }
+
+       string const get(string const & msg) const
+       {
+               return mssg_gl.get(cat_gl, 0, 0, msg);
+       }
+private:
+       ///
+       string lang_;
+       ///
+       std::locale loc_gl;
+       ///
+       std::messages<char> const & mssg_gl;
+       ///
+       catalog cat_gl;
+};
+#else
+
+#ifdef HAVE_LOCALE_H
+#  include <locale.h>
+#endif
+
+#  if HAVE_GETTEXT
+#    include <libintl.h>      // use the header already in the system *EK*
+#  else
+#    include "../intl/libintl.h"
+#  endif
+
+// This is a more traditional variant.
+class Messages::Pimpl {
+public:
+       Pimpl(string const & l)
+               : lang_(l)
+       {
+               //lyxerr << "Messages: language(" << l
+               //       << ") in dir(" << dir << ")" << std::endl;
+
+       }
+
+       ~Pimpl() {}
+
+       docstring const get(string const & m) const
+       {
+               if (m.empty())
+                       return from_ascii(m);
+
+               char * o = setlocale(LC_ALL, 0);
+               string old;
+               if (o)
+                       old = o;
+               char * n = setlocale(LC_ALL, lang_.c_str());
+               if (!n)
+                       // If we are unable to honour the request we just
+                       // return what we got in.
+                       return from_ascii(m);
+               errno = 0;
+               string const locale_dir = package().locale_dir().toFilesystemEncoding();
+               char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
+               int e = errno;
+               if (e) {
+                       LYXERR(Debug::DEBUG)
+                               << BOOST_CURRENT_FUNCTION << '\n'
+                               << "Error code: " << errno << '\n'
+                               << "Lang, mess: " << lang_ << " " << m << '\n'
+                               << "Directory : " << package().locale_dir().absFilename() << '\n'
+                               << "Rtn value : " << c << endl;
+               }
+
+               if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
+                       LYXERR(Debug::DEBUG)
+                               << BOOST_CURRENT_FUNCTION << '\n'
+                               << "Error code: " << errno << '\n'
+                               << "Codeset   : " << ucs4_codeset << '\n'
+                               << endl;
+               }
+
+               textdomain(PACKAGE);
+
+               char const * tmp = m.c_str();
+               char const * msg = gettext(tmp);
+               docstring translated;
+               if (!msg) {
+                       lyxerr << "Undefined result from gettext" << endl;
+                       translated = from_ascii(tmp);
+               } else if (msg == tmp) {
+                       //lyxerr << "Same as entered returned" << endl;
+                       translated = from_ascii(tmp);
+               } else {
+                       LYXERR(Debug::DEBUG) << "We got a translation" << endl;
+                       char_type const * ucs4 = reinterpret_cast<char_type const *>(msg);
+                       translated = ucs4;
+               }
+               setlocale(LC_ALL, old.c_str());
+               return translated;
+       }
+private:
+       ///
+       string lang_;
+};
+#endif
+
+#else // ENABLE_NLS
+// This is the dummy variant.
+class Messages::Pimpl {
+public:
+       Pimpl(string const &) {}
+
+       ~Pimpl() {}
+
+       docstring const get(string const & m) const
+       {
+               return from_ascii(m);
+       }
+};
+#endif
+
+
+Messages::Messages()
+       : pimpl_(new Pimpl(""))
+{}
+
+
+Messages::Messages(string const & l)
+       : pimpl_(new Pimpl(l))
+{}
+
+
+// We need this for the sake of scoped_ptr
+Messages::~Messages()
+{}
+
+
+docstring const Messages::get(string const & msg) const
+{
+       return pimpl_->get(msg);
+}
+
+
+} // namespace lyx
diff --git a/src/client/Messages.h b/src/client/Messages.h
new file mode 100644 (file)
index 0000000..5eb9447
--- /dev/null
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+/* \file Messages.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef MESSAGES_H
+#define MESSAGES_H
+
+#include "support/docstring.h"
+
+#include <boost/scoped_ptr.hpp>
+
+
+namespace lyx {
+
+///
+class Messages {
+public:
+       ///
+       Messages();
+       ///
+       Messages(std::string const & l);
+       ///
+       ~Messages();
+       ///
+       docstring const get(std::string const & msg) const;
+private:
+       class Pimpl;
+       boost::scoped_ptr<Pimpl> pimpl_;
+};
+
+
+} // namespace lyx
+
+#endif
diff --git a/src/client/boost.C b/src/client/boost.C
deleted file mode 100644 (file)
index 3cef121..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * \file boost.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "LyX.h"
-#include "debug.h"
-#include "support/lyxlib.h"
-
-#include <boost/assert.hpp>
-
-#include <exception>
-
-
-namespace lyx {
-
-using std::endl;
-
-namespace boost {
-
-void throw_exception(std::exception const & e)
-{
-       lyxerr << "Exception caught:\n"
-           << e.what() << endl;
-       BOOST_ASSERT(false);
-}
-
-
-void assertion_failed(char const * expr, char const * function,
-                     char const * file, long line)
-{
-       lyxerr << "Assertion triggered in " << function
-              << " by failing check \"" << expr << "\""
-              << " in file " << file << ":" << line << endl;
-       lyx::support::abort();
-}
-
-
-}
-
-
-} // namespace lyx
diff --git a/src/client/boost.cpp b/src/client/boost.cpp
new file mode 100644 (file)
index 0000000..3cef121
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * \file boost.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "LyX.h"
+#include "debug.h"
+#include "support/lyxlib.h"
+
+#include <boost/assert.hpp>
+
+#include <exception>
+
+
+namespace lyx {
+
+using std::endl;
+
+namespace boost {
+
+void throw_exception(std::exception const & e)
+{
+       lyxerr << "Exception caught:\n"
+           << e.what() << endl;
+       BOOST_ASSERT(false);
+}
+
+
+void assertion_failed(char const * expr, char const * function,
+                     char const * file, long line)
+{
+       lyxerr << "Assertion triggered in " << function
+              << " by failing check \"" << expr << "\""
+              << " in file " << file << ":" << line << endl;
+       lyx::support::abort();
+}
+
+
+}
+
+
+} // namespace lyx
diff --git a/src/client/client.C b/src/client/client.C
deleted file mode 100644 (file)
index 7cffd78..0000000
+++ /dev/null
@@ -1,638 +0,0 @@
-/**
- * \file client.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author João Luis M. Assirati
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-
-#include <config.h>
-
-#include "debug.h"
-#include "support/filename.h"
-#include "support/unicode.h"
-#include "support/lstrings.h"
-
-#include <boost/filesystem/operations.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/scoped_ptr.hpp>
-
-// getpid(), getppid()
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-// struct timeval
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-// select()
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-#endif
-
-// socket(), connect()
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#include <sys/un.h>
-
-// fcntl()
-#include <fcntl.h>
-
-#include <cerrno>
-#include <cstdlib>
-#include <string>
-#include <vector>
-#include <map>
-#include <iostream>
-
-
-namespace lyx {
-
-using support::FileName;
-using support::prefixIs;
-
-using boost::scoped_ptr;
-namespace fs = boost::filesystem;
-
-using std::string;
-using std::vector;
-using std::cout;
-using std::cerr;
-using std::cin;
-using std::endl;
-
-
-namespace support {
-
-string itoa(unsigned int i)
-{
-       return boost::lexical_cast<string>(i);
-}
-
-
-/// Returns the absolute pathnames of all lyx local sockets in
-/// file system encoding.
-/// Parts stolen from lyx::support::DirList().
-vector<fs::path> lyxSockets(string const & dir, string const & pid)
-{
-       vector<fs::path> dirlist;
-
-       fs::path dirpath(dir);
-
-       if (!fs::exists(dirpath) || !fs::is_directory(dirpath)) {
-               lyxerr << dir << " does not exist or is not a directory."
-                      << endl;
-               return dirlist;
-       }
-
-       fs::directory_iterator beg((fs::path(dir)));
-       fs::directory_iterator end;
-
-       for (; beg != end; ++beg) {
-               if (prefixIs(beg->leaf(), "lyx_tmpdir" + pid)) {
-                       fs::path lyxsocket = beg->path() / "lyxsocket";
-                       if (fs::exists(lyxsocket)) {
-                               dirlist.push_back(lyxsocket);
-                       }
-               }
-       }
-
-       return dirlist;
-}
-
-
-namespace socktools {
-
-
-/// Connect to the socket \p name.
-int connect(FileName const & name)
-{
-       int fd; // File descriptor for the socket
-       sockaddr_un addr; // Structure that hold the socket address
-
-       string const encoded = name.toFilesystemEncoding();
-       // char sun_path[108]
-       string::size_type len = encoded.size();
-       if (len > 107) {
-               cerr << "lyxclient: Socket address '" << name
-                    << "' too long." << endl;
-               return -1;
-       }
-       // Synonims for AF_UNIX are AF_LOCAL and AF_FILE
-       addr.sun_family = AF_UNIX;
-       encoded.copy(addr.sun_path, 107);
-       addr.sun_path[len] = '\0';
-
-       if ((fd = ::socket(PF_UNIX, SOCK_STREAM, 0))== -1) {
-               cerr << "lyxclient: Could not create socket descriptor: "
-                    << strerror(errno) << endl;
-               return -1;
-       }
-       if (::connect(fd,
-                     reinterpret_cast<struct sockaddr *>(&addr),
-                     sizeof(addr)) == -1) {
-               cerr << "lyxclient: Could not connect to socket " << name.absFilename()
-                    << ": " << strerror(errno) << endl;
-               ::close(fd);
-               return -1;
-       }
-       if (::fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
-               cerr << "lyxclient: Could not set O_NONBLOCK for socket: "
-                    << strerror(errno) << endl;
-               ::close(fd);
-               return -1;
-       }
-       return fd;
-}
-
-
-} // namespace socktools
-} // namespace support
-
-
-
-// Class IOWatch ------------------------------------------------------------
-class IOWatch {
-public:
-       IOWatch();
-       void clear();
-       void addfd(int);
-       bool wait(double);
-       bool wait();
-       bool isset(int fd);
-private:
-       fd_set des;
-       fd_set act;
-};
-
-
-IOWatch::IOWatch()
-{
-       clear();
-}
-
-
-void IOWatch::clear()
-{
-       FD_ZERO(&des);
-}
-
-
-void IOWatch::addfd(int fd)
-{
-       FD_SET(fd, &des);
-}
-
-
-bool IOWatch::wait(double timeout)
-{
-       timeval to;
-       to.tv_sec = static_cast<long int>(timeout);
-       to.tv_usec = static_cast<long int>((timeout - to.tv_sec)*1E6);
-       act = des;
-       return select(FD_SETSIZE, &act,
-                     (fd_set *)0, (fd_set *)0, &to);
-}
-
-
-bool IOWatch::wait()
-{
-       act = des;
-       return select(FD_SETSIZE, &act,
-                     (fd_set *)0, (fd_set *)0, (timeval *)0);
-}
-
-
-bool IOWatch::isset(int fd) {
-       return FD_ISSET(fd, &act);
-}
-// ~Class IOWatch ------------------------------------------------------------
-
-
-// Class LyXDataSocket -------------------------------------------------------
-// Modified LyXDataSocket class for use with the client
-class LyXDataSocket {
-public:
-       LyXDataSocket(FileName const &);
-       ~LyXDataSocket();
-       // File descriptor of the connection
-       int fd() const;
-       // Connection status
-       bool connected() const;
-       // Line buffered input from the socket
-       bool readln(string &);
-       // Write the string + '\n' to the socket
-       void writeln(string const &);
-private:
-       // File descriptor for the data socket
-       int fd_;
-       // True if the connection is up
-       bool connected_;
-       // buffer for input data
-       string buffer;
-};
-
-
-LyXDataSocket::LyXDataSocket(FileName const & address)
-{
-       if ((fd_ = support::socktools::connect(address)) == -1) {
-               connected_ = false;
-       } else {
-               connected_ = true;
-       }
-}
-
-
-LyXDataSocket::~LyXDataSocket()
-{
-       ::close(fd_);
-}
-
-
-int LyXDataSocket::fd() const
-{
-       return fd_;
-}
-
-
-bool LyXDataSocket::connected() const
-{
-       return connected_;
-}
-
-
-// Returns true if there was a complete line to input
-// A line is of the form <key>:<value>
-//   A line not of this form will not be passed
-// The line read is splitted and stored in 'key' and 'value'
-bool LyXDataSocket::readln(string & line)
-{
-       int const charbuf_size = 100;
-       char charbuf[charbuf_size]; // buffer for the ::read() system call
-       int count;
-       string::size_type pos;
-
-       // read and store characters in buffer
-       while ((count = ::read(fd_, charbuf, charbuf_size - 1)) > 0) {
-               charbuf[count] = '\0'; // turn it into a c string
-               buffer += charbuf;
-       }
-
-       // Error conditions. The buffer must still be
-       // processed for lines read
-       if (count == 0) { // EOF -- connection closed
-               connected_ = false;
-       } else if ((count == -1) && (errno != EAGAIN)) { // IO error
-               cerr << "lyxclient: IO error." << endl;
-               connected_ = false;
-       }
-
-       // Cut a line from buffer
-       if ((pos = buffer.find('\n')) == string::npos)
-               return false; // No complete line stored
-       line = buffer.substr(0, pos);
-       buffer = buffer.substr(pos + 1);
-       return true;
-}
-
-
-// Write a line of the form <key>:<value> to the socket
-void LyXDataSocket::writeln(string const & line)
-{
-       string linen(line + '\n');
-       int size = linen.size();
-       int written = ::write(fd_, linen.c_str(), size);
-       if (written < size) { // Allways mean end of connection.
-               if ((written == -1) && (errno == EPIPE)) {
-                       // The program will also receive a SIGPIPE
-                       // that must be catched
-                       cerr << "lyxclient: connection closed while writing."
-                            << endl;
-               } else {
-                       // Anything else, including errno == EAGAIN, must be
-                       // considered IO error. EAGAIN should never happen
-                       // when line is small
-                       cerr << "lyxclient: IO error: " << strerror(errno);
-               }
-               connected_ = false;
-       }
-}
-// ~Class LyXDataSocket -------------------------------------------------------
-
-
-// Class CmdLineParser -------------------------------------------------------
-class CmdLineParser {
-public:
-       typedef int (*optfunc)(vector<docstring> const & args);
-       std::map<string, optfunc> helper;
-       std::map<string, bool> isset;
-       bool parse(int, char * []);
-       vector<char *> nonopt;
-};
-
-
-bool CmdLineParser::parse(int argc, char * argv[])
-{
-       int opt = 1;
-       while (opt < argc) {
-               vector<docstring> args;
-               if (helper[argv[opt]]) {
-                       isset[argv[opt]] = true;
-                       int arg = opt + 1;
-                       while ((arg < argc) && (!helper[argv[arg]])) {
-                               args.push_back(from_local8bit(argv[arg]));
-                               ++arg;
-                       }
-                       int taken = helper[argv[opt]](args);
-                       if (taken == -1)
-                               return false;
-                       opt += 1 + taken;
-               } else {
-                       if (argv[opt][0] == '-') {
-                               if ((argv[opt][1] == '-')
-                                  && (argv[opt][2]== '\0')) {
-                                       ++opt;
-                                       while (opt < argc) {
-                                               nonopt.push_back(argv[opt]);
-                                               ++opt;
-                                       }
-                                       return true;
-                               } else {
-                                       cerr << "lyxclient: unknown option "
-                                            << argv[opt] << endl;
-                                       return false;
-                               }
-                       }
-                       nonopt.push_back(argv[opt]);
-                       ++opt;
-               }
-       }
-       return true;
-}
-// ~Class CmdLineParser -------------------------------------------------------
-
-
-
-namespace cmdline {
-
-void usage()
-{
-       cerr << "Usage: lyxclient [options]" << endl
-            << "Options are:" << endl
-            << "  -a address    set address of the lyx socket" << endl
-            << "  -t directory  set system temporary directory" << endl
-            << "  -p pid        select a running lyx by pid" << endl
-            << "  -c command    send a single command and quit" << endl
-            << "  -g file row   send a command to go to file and row" << endl
-            << "  -n name       set client name" << endl
-            << "  -h name       display this help end exit" << endl
-            << "If -a is not used, lyxclient will use the arguments of -t and -p to look for" << endl
-            << "a running lyx. If -t is not set, 'directory' defaults to /tmp. If -p is set," << endl
-            << "lyxclient will connect only to a lyx with the specified pid. Options -c and -g" << endl
-            << "cannot be set simultaneoulsly. If no -c or -g options are given, lyxclient" << endl
-            << "will read commands from standard input and disconnect when command read is BYE:"
-            << endl;
-}
-
-
-int h(vector<docstring> const &)
-{
-       usage();
-       exit(0);
-}
-
-
-docstring clientName(from_ascii(support::itoa(::getppid()) + ">" + support::itoa(::getpid())));
-
-int n(vector<docstring> const & arg)
-{
-       if (arg.size() < 1) {
-               cerr << "lyxclient: The option -n requires 1 argument."
-                    << endl;
-               return -1;
-       }
-       clientName = arg[0];
-       return 1;
-}
-
-
-docstring singleCommand;
-
-
-int c(vector<docstring> const & arg)
-{
-       if (arg.size() < 1) {
-               cerr << "lyxclient: The option -c requires 1 argument."
-                    << endl;
-               return -1;
-       }
-       singleCommand = arg[0];
-       return 1;
-}
-
-
-int g(vector<docstring> const & arg)
-{
-       if (arg.size() < 2) {
-               cerr << "lyxclient: The option -g requires 2 arguments."
-                    << endl;
-               return -1;
-       }
-       singleCommand = "LYXCMD:server-goto-file-row "
-               + arg[0] + ' '
-               + arg[1];
-       return 2;
-}
-
-
-// empty if LYXSOCKET is not set in the environment
-docstring serverAddress;
-
-
-int a(vector<docstring> const & arg)
-{
-       if (arg.size() < 1) {
-               cerr << "lyxclient: The option -a requires 1 argument."
-                    << endl;
-               return -1;
-       }
-       // -a supercedes LYXSOCKET environment variable
-       serverAddress = arg[0];
-       return 1;
-}
-
-
-docstring mainTmp(from_ascii("/tmp"));
-
-
-int t(vector<docstring> const & arg)
-{
-       if (arg.size() < 1) {
-               cerr << "lyxclient: The option -t requires 1 argument."
-                    << endl;
-               return -1;
-       }
-       mainTmp = arg[0];
-       return 1;
-}
-
-
-string serverPid; // Init to empty string
-
-
-int p(vector<docstring> const & arg)
-{
-       if (arg.size() < 1) {
-               cerr << "lyxclient: The option -p requires 1 argument."
-                    << endl;
-               return -1;
-       }
-       serverPid = to_ascii(arg[0]);
-       return 1;
-}
-
-
-} // namespace cmdline
-
-} // namespace lyx
-
-
-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;
-       args.helper["-g"] = cmdline::g;
-       args.helper["-n"] = cmdline::n;
-       args.helper["-a"] = cmdline::a;
-       args.helper["-t"] = cmdline::t;
-       args.helper["-p"] = cmdline::p;
-
-       // Command line failure conditions:
-       if ((!args.parse(argc, argv))
-          || (args.isset["-c"] && args.isset["-g"])
-          || (args.isset["-a"] && args.isset["-p"])) {
-               cmdline::usage();
-               return 1;
-       }
-
-       scoped_ptr<LyXDataSocket> server;
-
-       if (!cmdline::serverAddress.empty()) {
-               server.reset(new LyXDataSocket(FileName(to_utf8(cmdline::serverAddress))));
-               if (!server->connected()) {
-                       cerr << "lyxclient: " << "Could not connect to "
-                            << 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(to_filesystem8bit(cmdline::mainTmp), cmdline::serverPid);
-               vector<fs::path>::const_iterator addr = addrs.begin();
-               vector<fs::path>::const_iterator end = addrs.end();
-               for (; addr != end; ++addr) {
-                       // Caution: addr->string() is in filesystem encoding
-                       server.reset(new LyXDataSocket(FileName(to_utf8(from_filesystem8bit(addr->string())))));
-                       if (server->connected())
-                               break;
-                       lyxerr << "lyxclient: " << "Could not connect to "
-                            << addr->string() << endl;
-               }
-               if (addr == end) {
-                       lyxerr << "lyxclient: No suitable server found."
-                              << endl;
-                       return EXIT_FAILURE;
-               }
-               cerr << "lyxclient: " << "Connected to " << addr->string() << endl;
-       }
-
-       int const serverfd = server->fd();
-
-       IOWatch iowatch;
-       iowatch.addfd(serverfd);
-
-       // Used to read from server
-       string answer;
-
-       // Send greeting
-       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)) {
-               if (prefixIs(answer, "BYE:")) {
-                       cerr << "lyxclient: Server disconnected." << endl;
-                       cout << answer << endl;
-                       return EXIT_FAILURE;
-               }
-       } else {
-               cerr << "lyxclient: No answer from server." << endl;
-               return EXIT_FAILURE;
-       }
-
-       if (args.isset["-g"] || args.isset["-c"]) {
-               server->writeln(to_utf8(cmdline::singleCommand));
-               iowatch.wait(2.0);
-               if (iowatch.isset(serverfd) && server->readln(answer)) {
-                       cout << answer;
-                       if (prefixIs(answer, "ERROR:"))
-                               return EXIT_FAILURE;
-                       return EXIT_SUCCESS;
-               } else {
-                       cerr << "lyxclient: No answer from server." << endl;
-                       return EXIT_FAILURE;
-               }
-       }
-
-       // Take commands from stdin
-       iowatch.addfd(0); // stdin
-       bool saidbye = false;
-       while ((!saidbye) && server->connected()) {
-               iowatch.wait();
-               if (iowatch.isset(0)) {
-                       string command;
-                       cin >> command;
-                       if (command == "BYE:") {
-                               server->writeln("BYE:");
-                               saidbye = true;
-                       } else {
-                               server->writeln("LYXCMD:" + command);
-                       }
-               }
-               if (iowatch.isset(serverfd)) {
-                       while(server->readln(answer))
-                               cout << answer << endl;
-               }
-       }
-
-       return EXIT_SUCCESS;
-}
-
-
-namespace boost {
-
-void assertion_failed(char const* a, char const* b, char const* c, long d)
-{
-       lyx::lyxerr << "Assertion failed: " << a << ' ' << b << ' ' << c << ' '
-               << d << '\n';
-}
-
-} // namespace boost
-
diff --git a/src/client/client.cpp b/src/client/client.cpp
new file mode 100644 (file)
index 0000000..7cffd78
--- /dev/null
@@ -0,0 +1,638 @@
+/**
+ * \file client.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author João Luis M. Assirati
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+
+#include <config.h>
+
+#include "debug.h"
+#include "support/filename.h"
+#include "support/unicode.h"
+#include "support/lstrings.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
+
+// getpid(), getppid()
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+// struct timeval
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+// select()
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+// socket(), connect()
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#include <sys/un.h>
+
+// fcntl()
+#include <fcntl.h>
+
+#include <cerrno>
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include <map>
+#include <iostream>
+
+
+namespace lyx {
+
+using support::FileName;
+using support::prefixIs;
+
+using boost::scoped_ptr;
+namespace fs = boost::filesystem;
+
+using std::string;
+using std::vector;
+using std::cout;
+using std::cerr;
+using std::cin;
+using std::endl;
+
+
+namespace support {
+
+string itoa(unsigned int i)
+{
+       return boost::lexical_cast<string>(i);
+}
+
+
+/// Returns the absolute pathnames of all lyx local sockets in
+/// file system encoding.
+/// Parts stolen from lyx::support::DirList().
+vector<fs::path> lyxSockets(string const & dir, string const & pid)
+{
+       vector<fs::path> dirlist;
+
+       fs::path dirpath(dir);
+
+       if (!fs::exists(dirpath) || !fs::is_directory(dirpath)) {
+               lyxerr << dir << " does not exist or is not a directory."
+                      << endl;
+               return dirlist;
+       }
+
+       fs::directory_iterator beg((fs::path(dir)));
+       fs::directory_iterator end;
+
+       for (; beg != end; ++beg) {
+               if (prefixIs(beg->leaf(), "lyx_tmpdir" + pid)) {
+                       fs::path lyxsocket = beg->path() / "lyxsocket";
+                       if (fs::exists(lyxsocket)) {
+                               dirlist.push_back(lyxsocket);
+                       }
+               }
+       }
+
+       return dirlist;
+}
+
+
+namespace socktools {
+
+
+/// Connect to the socket \p name.
+int connect(FileName const & name)
+{
+       int fd; // File descriptor for the socket
+       sockaddr_un addr; // Structure that hold the socket address
+
+       string const encoded = name.toFilesystemEncoding();
+       // char sun_path[108]
+       string::size_type len = encoded.size();
+       if (len > 107) {
+               cerr << "lyxclient: Socket address '" << name
+                    << "' too long." << endl;
+               return -1;
+       }
+       // Synonims for AF_UNIX are AF_LOCAL and AF_FILE
+       addr.sun_family = AF_UNIX;
+       encoded.copy(addr.sun_path, 107);
+       addr.sun_path[len] = '\0';
+
+       if ((fd = ::socket(PF_UNIX, SOCK_STREAM, 0))== -1) {
+               cerr << "lyxclient: Could not create socket descriptor: "
+                    << strerror(errno) << endl;
+               return -1;
+       }
+       if (::connect(fd,
+                     reinterpret_cast<struct sockaddr *>(&addr),
+                     sizeof(addr)) == -1) {
+               cerr << "lyxclient: Could not connect to socket " << name.absFilename()
+                    << ": " << strerror(errno) << endl;
+               ::close(fd);
+               return -1;
+       }
+       if (::fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+               cerr << "lyxclient: Could not set O_NONBLOCK for socket: "
+                    << strerror(errno) << endl;
+               ::close(fd);
+               return -1;
+       }
+       return fd;
+}
+
+
+} // namespace socktools
+} // namespace support
+
+
+
+// Class IOWatch ------------------------------------------------------------
+class IOWatch {
+public:
+       IOWatch();
+       void clear();
+       void addfd(int);
+       bool wait(double);
+       bool wait();
+       bool isset(int fd);
+private:
+       fd_set des;
+       fd_set act;
+};
+
+
+IOWatch::IOWatch()
+{
+       clear();
+}
+
+
+void IOWatch::clear()
+{
+       FD_ZERO(&des);
+}
+
+
+void IOWatch::addfd(int fd)
+{
+       FD_SET(fd, &des);
+}
+
+
+bool IOWatch::wait(double timeout)
+{
+       timeval to;
+       to.tv_sec = static_cast<long int>(timeout);
+       to.tv_usec = static_cast<long int>((timeout - to.tv_sec)*1E6);
+       act = des;
+       return select(FD_SETSIZE, &act,
+                     (fd_set *)0, (fd_set *)0, &to);
+}
+
+
+bool IOWatch::wait()
+{
+       act = des;
+       return select(FD_SETSIZE, &act,
+                     (fd_set *)0, (fd_set *)0, (timeval *)0);
+}
+
+
+bool IOWatch::isset(int fd) {
+       return FD_ISSET(fd, &act);
+}
+// ~Class IOWatch ------------------------------------------------------------
+
+
+// Class LyXDataSocket -------------------------------------------------------
+// Modified LyXDataSocket class for use with the client
+class LyXDataSocket {
+public:
+       LyXDataSocket(FileName const &);
+       ~LyXDataSocket();
+       // File descriptor of the connection
+       int fd() const;
+       // Connection status
+       bool connected() const;
+       // Line buffered input from the socket
+       bool readln(string &);
+       // Write the string + '\n' to the socket
+       void writeln(string const &);
+private:
+       // File descriptor for the data socket
+       int fd_;
+       // True if the connection is up
+       bool connected_;
+       // buffer for input data
+       string buffer;
+};
+
+
+LyXDataSocket::LyXDataSocket(FileName const & address)
+{
+       if ((fd_ = support::socktools::connect(address)) == -1) {
+               connected_ = false;
+       } else {
+               connected_ = true;
+       }
+}
+
+
+LyXDataSocket::~LyXDataSocket()
+{
+       ::close(fd_);
+}
+
+
+int LyXDataSocket::fd() const
+{
+       return fd_;
+}
+
+
+bool LyXDataSocket::connected() const
+{
+       return connected_;
+}
+
+
+// Returns true if there was a complete line to input
+// A line is of the form <key>:<value>
+//   A line not of this form will not be passed
+// The line read is splitted and stored in 'key' and 'value'
+bool LyXDataSocket::readln(string & line)
+{
+       int const charbuf_size = 100;
+       char charbuf[charbuf_size]; // buffer for the ::read() system call
+       int count;
+       string::size_type pos;
+
+       // read and store characters in buffer
+       while ((count = ::read(fd_, charbuf, charbuf_size - 1)) > 0) {
+               charbuf[count] = '\0'; // turn it into a c string
+               buffer += charbuf;
+       }
+
+       // Error conditions. The buffer must still be
+       // processed for lines read
+       if (count == 0) { // EOF -- connection closed
+               connected_ = false;
+       } else if ((count == -1) && (errno != EAGAIN)) { // IO error
+               cerr << "lyxclient: IO error." << endl;
+               connected_ = false;
+       }
+
+       // Cut a line from buffer
+       if ((pos = buffer.find('\n')) == string::npos)
+               return false; // No complete line stored
+       line = buffer.substr(0, pos);
+       buffer = buffer.substr(pos + 1);
+       return true;
+}
+
+
+// Write a line of the form <key>:<value> to the socket
+void LyXDataSocket::writeln(string const & line)
+{
+       string linen(line + '\n');
+       int size = linen.size();
+       int written = ::write(fd_, linen.c_str(), size);
+       if (written < size) { // Allways mean end of connection.
+               if ((written == -1) && (errno == EPIPE)) {
+                       // The program will also receive a SIGPIPE
+                       // that must be catched
+                       cerr << "lyxclient: connection closed while writing."
+                            << endl;
+               } else {
+                       // Anything else, including errno == EAGAIN, must be
+                       // considered IO error. EAGAIN should never happen
+                       // when line is small
+                       cerr << "lyxclient: IO error: " << strerror(errno);
+               }
+               connected_ = false;
+       }
+}
+// ~Class LyXDataSocket -------------------------------------------------------
+
+
+// Class CmdLineParser -------------------------------------------------------
+class CmdLineParser {
+public:
+       typedef int (*optfunc)(vector<docstring> const & args);
+       std::map<string, optfunc> helper;
+       std::map<string, bool> isset;
+       bool parse(int, char * []);
+       vector<char *> nonopt;
+};
+
+
+bool CmdLineParser::parse(int argc, char * argv[])
+{
+       int opt = 1;
+       while (opt < argc) {
+               vector<docstring> args;
+               if (helper[argv[opt]]) {
+                       isset[argv[opt]] = true;
+                       int arg = opt + 1;
+                       while ((arg < argc) && (!helper[argv[arg]])) {
+                               args.push_back(from_local8bit(argv[arg]));
+                               ++arg;
+                       }
+                       int taken = helper[argv[opt]](args);
+                       if (taken == -1)
+                               return false;
+                       opt += 1 + taken;
+               } else {
+                       if (argv[opt][0] == '-') {
+                               if ((argv[opt][1] == '-')
+                                  && (argv[opt][2]== '\0')) {
+                                       ++opt;
+                                       while (opt < argc) {
+                                               nonopt.push_back(argv[opt]);
+                                               ++opt;
+                                       }
+                                       return true;
+                               } else {
+                                       cerr << "lyxclient: unknown option "
+                                            << argv[opt] << endl;
+                                       return false;
+                               }
+                       }
+                       nonopt.push_back(argv[opt]);
+                       ++opt;
+               }
+       }
+       return true;
+}
+// ~Class CmdLineParser -------------------------------------------------------
+
+
+
+namespace cmdline {
+
+void usage()
+{
+       cerr << "Usage: lyxclient [options]" << endl
+            << "Options are:" << endl
+            << "  -a address    set address of the lyx socket" << endl
+            << "  -t directory  set system temporary directory" << endl
+            << "  -p pid        select a running lyx by pid" << endl
+            << "  -c command    send a single command and quit" << endl
+            << "  -g file row   send a command to go to file and row" << endl
+            << "  -n name       set client name" << endl
+            << "  -h name       display this help end exit" << endl
+            << "If -a is not used, lyxclient will use the arguments of -t and -p to look for" << endl
+            << "a running lyx. If -t is not set, 'directory' defaults to /tmp. If -p is set," << endl
+            << "lyxclient will connect only to a lyx with the specified pid. Options -c and -g" << endl
+            << "cannot be set simultaneoulsly. If no -c or -g options are given, lyxclient" << endl
+            << "will read commands from standard input and disconnect when command read is BYE:"
+            << endl;
+}
+
+
+int h(vector<docstring> const &)
+{
+       usage();
+       exit(0);
+}
+
+
+docstring clientName(from_ascii(support::itoa(::getppid()) + ">" + support::itoa(::getpid())));
+
+int n(vector<docstring> const & arg)
+{
+       if (arg.size() < 1) {
+               cerr << "lyxclient: The option -n requires 1 argument."
+                    << endl;
+               return -1;
+       }
+       clientName = arg[0];
+       return 1;
+}
+
+
+docstring singleCommand;
+
+
+int c(vector<docstring> const & arg)
+{
+       if (arg.size() < 1) {
+               cerr << "lyxclient: The option -c requires 1 argument."
+                    << endl;
+               return -1;
+       }
+       singleCommand = arg[0];
+       return 1;
+}
+
+
+int g(vector<docstring> const & arg)
+{
+       if (arg.size() < 2) {
+               cerr << "lyxclient: The option -g requires 2 arguments."
+                    << endl;
+               return -1;
+       }
+       singleCommand = "LYXCMD:server-goto-file-row "
+               + arg[0] + ' '
+               + arg[1];
+       return 2;
+}
+
+
+// empty if LYXSOCKET is not set in the environment
+docstring serverAddress;
+
+
+int a(vector<docstring> const & arg)
+{
+       if (arg.size() < 1) {
+               cerr << "lyxclient: The option -a requires 1 argument."
+                    << endl;
+               return -1;
+       }
+       // -a supercedes LYXSOCKET environment variable
+       serverAddress = arg[0];
+       return 1;
+}
+
+
+docstring mainTmp(from_ascii("/tmp"));
+
+
+int t(vector<docstring> const & arg)
+{
+       if (arg.size() < 1) {
+               cerr << "lyxclient: The option -t requires 1 argument."
+                    << endl;
+               return -1;
+       }
+       mainTmp = arg[0];
+       return 1;
+}
+
+
+string serverPid; // Init to empty string
+
+
+int p(vector<docstring> const & arg)
+{
+       if (arg.size() < 1) {
+               cerr << "lyxclient: The option -p requires 1 argument."
+                    << endl;
+               return -1;
+       }
+       serverPid = to_ascii(arg[0]);
+       return 1;
+}
+
+
+} // namespace cmdline
+
+} // namespace lyx
+
+
+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;
+       args.helper["-g"] = cmdline::g;
+       args.helper["-n"] = cmdline::n;
+       args.helper["-a"] = cmdline::a;
+       args.helper["-t"] = cmdline::t;
+       args.helper["-p"] = cmdline::p;
+
+       // Command line failure conditions:
+       if ((!args.parse(argc, argv))
+          || (args.isset["-c"] && args.isset["-g"])
+          || (args.isset["-a"] && args.isset["-p"])) {
+               cmdline::usage();
+               return 1;
+       }
+
+       scoped_ptr<LyXDataSocket> server;
+
+       if (!cmdline::serverAddress.empty()) {
+               server.reset(new LyXDataSocket(FileName(to_utf8(cmdline::serverAddress))));
+               if (!server->connected()) {
+                       cerr << "lyxclient: " << "Could not connect to "
+                            << 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(to_filesystem8bit(cmdline::mainTmp), cmdline::serverPid);
+               vector<fs::path>::const_iterator addr = addrs.begin();
+               vector<fs::path>::const_iterator end = addrs.end();
+               for (; addr != end; ++addr) {
+                       // Caution: addr->string() is in filesystem encoding
+                       server.reset(new LyXDataSocket(FileName(to_utf8(from_filesystem8bit(addr->string())))));
+                       if (server->connected())
+                               break;
+                       lyxerr << "lyxclient: " << "Could not connect to "
+                            << addr->string() << endl;
+               }
+               if (addr == end) {
+                       lyxerr << "lyxclient: No suitable server found."
+                              << endl;
+                       return EXIT_FAILURE;
+               }
+               cerr << "lyxclient: " << "Connected to " << addr->string() << endl;
+       }
+
+       int const serverfd = server->fd();
+
+       IOWatch iowatch;
+       iowatch.addfd(serverfd);
+
+       // Used to read from server
+       string answer;
+
+       // Send greeting
+       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)) {
+               if (prefixIs(answer, "BYE:")) {
+                       cerr << "lyxclient: Server disconnected." << endl;
+                       cout << answer << endl;
+                       return EXIT_FAILURE;
+               }
+       } else {
+               cerr << "lyxclient: No answer from server." << endl;
+               return EXIT_FAILURE;
+       }
+
+       if (args.isset["-g"] || args.isset["-c"]) {
+               server->writeln(to_utf8(cmdline::singleCommand));
+               iowatch.wait(2.0);
+               if (iowatch.isset(serverfd) && server->readln(answer)) {
+                       cout << answer;
+                       if (prefixIs(answer, "ERROR:"))
+                               return EXIT_FAILURE;
+                       return EXIT_SUCCESS;
+               } else {
+                       cerr << "lyxclient: No answer from server." << endl;
+                       return EXIT_FAILURE;
+               }
+       }
+
+       // Take commands from stdin
+       iowatch.addfd(0); // stdin
+       bool saidbye = false;
+       while ((!saidbye) && server->connected()) {
+               iowatch.wait();
+               if (iowatch.isset(0)) {
+                       string command;
+                       cin >> command;
+                       if (command == "BYE:") {
+                               server->writeln("BYE:");
+                               saidbye = true;
+                       } else {
+                               server->writeln("LYXCMD:" + command);
+                       }
+               }
+               if (iowatch.isset(serverfd)) {
+                       while(server->readln(answer))
+                               cout << answer << endl;
+               }
+       }
+
+       return EXIT_SUCCESS;
+}
+
+
+namespace boost {
+
+void assertion_failed(char const* a, char const* b, char const* c, long d)
+{
+       lyx::lyxerr << "Assertion failed: " << a << ' ' << b << ' ' << c << ' '
+               << d << '\n';
+}
+
+} // namespace boost
+
diff --git a/src/client/debug.C b/src/client/debug.C
deleted file mode 100644 (file)
index fe99801..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * \file debug.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- * \author Jean-Marc Lasgouttes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "debug.h"
-#include "gettext.h"
-
-#include "support/convert.h"
-#include "support/lstrings.h"
-
-#include <iostream>
-#include <iomanip>
-
-
-namespace lyx {
-
-using support::ascii_lowercase;
-using support::bformat;
-using support::isStrInt;
-
-using std::setw;
-using std::string;
-using std::ostream;
-
-namespace {
-
-struct error_item {
-       Debug::type level;
-       char const * name;
-       char const * desc;
-};
-
-
-error_item errorTags[] = {
-       { Debug::NONE,      "none",      N_("No debugging message")},
-       { Debug::INFO,      "info",      N_("General information")},
-       { Debug::DEBUG,     "debug",     N_("Developers' general debug messages")},
-       { Debug::ANY,       "any",       N_("All debugging messages")}
-};
-
-
-int const numErrorTags = sizeof(errorTags)/sizeof(error_item);
-
-} // namespace anon
-
-
-lyx_debug_trait::type lyx_debug_trait::value(string const & val)
-{
-       type l = Debug::NONE;
-       string v(val);
-       while (!v.empty()) {
-               string::size_type const st = v.find(',');
-               string const tmp(ascii_lowercase(v.substr(0, st)));
-               if (tmp.empty())
-                       break;
-               // Is it a number?
-               if (isStrInt(tmp))
-                       l |= static_cast<type>(convert<int>(tmp));
-               else
-               // Search for an explicit name
-               for (int i = 0 ; i < numErrorTags ; ++i)
-                       if (tmp == errorTags[i].name) {
-                               l |= errorTags[i].level;
-                               break;
-                       }
-               if (st == string::npos) break;
-               v.erase(0, st + 1);
-       }
-       return l;
-}
-
-
-void lyx_debug_trait::showLevel(ostream & os, lyx_debug_trait::type level)
-{
-       // Show what features are traced
-       for (int i = 0; i < numErrorTags ; ++i) {
-               if (errorTags[i].level != Debug::ANY
-                   && errorTags[i].level != Debug::NONE
-                   && errorTags[i].level & level) {
-                       // avoid to_utf8(_(...)) re-entrance problem
-                       docstring const s = _(errorTags[i].desc);
-                       os << to_utf8(bformat(_("Debugging `%1$s' (%2$s)"),
-                                       from_utf8(errorTags[i].name), s))
-                          << '\n';
-               }
-       }
-       os.flush();
-}
-
-
-void lyx_debug_trait::showTags(ostream & os)
-{
-       for (int i = 0; i < numErrorTags ; ++i)
-               os << setw(10) << static_cast<unsigned int>(errorTags[i].level)
-                  << setw(13) << errorTags[i].name
-                  << "  " << to_utf8(_(errorTags[i].desc)) << '\n';
-       os.flush();
-}
-
-
-LyXErr lyxerr;
-
-
-} // namespace lyx
diff --git a/src/client/debug.cpp b/src/client/debug.cpp
new file mode 100644 (file)
index 0000000..fe99801
--- /dev/null
@@ -0,0 +1,113 @@
+/**
+ * \file debug.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ * \author Jean-Marc Lasgouttes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "debug.h"
+#include "gettext.h"
+
+#include "support/convert.h"
+#include "support/lstrings.h"
+
+#include <iostream>
+#include <iomanip>
+
+
+namespace lyx {
+
+using support::ascii_lowercase;
+using support::bformat;
+using support::isStrInt;
+
+using std::setw;
+using std::string;
+using std::ostream;
+
+namespace {
+
+struct error_item {
+       Debug::type level;
+       char const * name;
+       char const * desc;
+};
+
+
+error_item errorTags[] = {
+       { Debug::NONE,      "none",      N_("No debugging message")},
+       { Debug::INFO,      "info",      N_("General information")},
+       { Debug::DEBUG,     "debug",     N_("Developers' general debug messages")},
+       { Debug::ANY,       "any",       N_("All debugging messages")}
+};
+
+
+int const numErrorTags = sizeof(errorTags)/sizeof(error_item);
+
+} // namespace anon
+
+
+lyx_debug_trait::type lyx_debug_trait::value(string const & val)
+{
+       type l = Debug::NONE;
+       string v(val);
+       while (!v.empty()) {
+               string::size_type const st = v.find(',');
+               string const tmp(ascii_lowercase(v.substr(0, st)));
+               if (tmp.empty())
+                       break;
+               // Is it a number?
+               if (isStrInt(tmp))
+                       l |= static_cast<type>(convert<int>(tmp));
+               else
+               // Search for an explicit name
+               for (int i = 0 ; i < numErrorTags ; ++i)
+                       if (tmp == errorTags[i].name) {
+                               l |= errorTags[i].level;
+                               break;
+                       }
+               if (st == string::npos) break;
+               v.erase(0, st + 1);
+       }
+       return l;
+}
+
+
+void lyx_debug_trait::showLevel(ostream & os, lyx_debug_trait::type level)
+{
+       // Show what features are traced
+       for (int i = 0; i < numErrorTags ; ++i) {
+               if (errorTags[i].level != Debug::ANY
+                   && errorTags[i].level != Debug::NONE
+                   && errorTags[i].level & level) {
+                       // avoid to_utf8(_(...)) re-entrance problem
+                       docstring const s = _(errorTags[i].desc);
+                       os << to_utf8(bformat(_("Debugging `%1$s' (%2$s)"),
+                                       from_utf8(errorTags[i].name), s))
+                          << '\n';
+               }
+       }
+       os.flush();
+}
+
+
+void lyx_debug_trait::showTags(ostream & os)
+{
+       for (int i = 0; i < numErrorTags ; ++i)
+               os << setw(10) << static_cast<unsigned int>(errorTags[i].level)
+                  << setw(13) << errorTags[i].name
+                  << "  " << to_utf8(_(errorTags[i].desc)) << '\n';
+       os.flush();
+}
+
+
+LyXErr lyxerr;
+
+
+} // namespace lyx
diff --git a/src/client/gettext.C b/src/client/gettext.C
deleted file mode 100644 (file)
index 7eb0be0..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * \file src/gettext.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- * \author Jean-Marc Lasgouttes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "gettext.h"
-#include "Messages.h"
-
-
-namespace lyx {
-
-
-#ifdef HAVE_LOCALE_H
-#  include <locale.h>
-#endif
-
-using std::string;
-
-
-namespace {
-
-Messages & getLyXMessages()
-{
-       static Messages lyx_messages;
-
-       return lyx_messages;
-}
-
-} // anon namespace
-
-
-docstring const _(string const & str)
-{
-       return getLyXMessages().get(str);
-}
-
-
-#ifdef ENABLE_NLS
-
-void locale_init()
-{
-#  ifdef HAVE_LC_MESSAGES
-       setlocale(LC_MESSAGES, "");
-#  endif
-       setlocale(LC_CTYPE, "");
-       setlocale(LC_NUMERIC, "C");
-}
-
-#else // ENABLE_NLS
-
-void locale_init()
-{
-       setlocale(LC_NUMERIC, "C");
-}
-
-#endif
-
-
-} // namespace lyx
diff --git a/src/client/gettext.cpp b/src/client/gettext.cpp
new file mode 100644 (file)
index 0000000..7eb0be0
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * \file src/gettext.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ * \author Jean-Marc Lasgouttes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "gettext.h"
+#include "Messages.h"
+
+
+namespace lyx {
+
+
+#ifdef HAVE_LOCALE_H
+#  include <locale.h>
+#endif
+
+using std::string;
+
+
+namespace {
+
+Messages & getLyXMessages()
+{
+       static Messages lyx_messages;
+
+       return lyx_messages;
+}
+
+} // anon namespace
+
+
+docstring const _(string const & str)
+{
+       return getLyXMessages().get(str);
+}
+
+
+#ifdef ENABLE_NLS
+
+void locale_init()
+{
+#  ifdef HAVE_LC_MESSAGES
+       setlocale(LC_MESSAGES, "");
+#  endif
+       setlocale(LC_CTYPE, "");
+       setlocale(LC_NUMERIC, "C");
+}
+
+#else // ENABLE_NLS
+
+void locale_init()
+{
+       setlocale(LC_NUMERIC, "C");
+}
+
+#endif
+
+
+} // namespace lyx
diff --git a/src/client/messages.C b/src/client/messages.C
deleted file mode 100644 (file)
index 04f1d49..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/* \file Messages.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "Messages.h"
-#include "debug.h"
-#include "support/filetools.h"
-#include "support/package.h"
-#include "support/unicode.h"
-
-#include <boost/current_function.hpp>
-
-#include <cerrno>
-
-
-namespace lyx {
-
-using lyx::support::package;
-using std::endl;
-using std::string;
-
-
-#ifdef ENABLE_NLS
-
-
-#if 0
-
--#include <locale>
-
-// This version of the Pimpl utilizes the message capability of
-// libstdc++ that is distributed with GNU G++.
-class Messages::Pimpl {
-public:
-       typedef std::messages<char>::catalog catalog;
-
-       Pimpl(string const & l)
-               : lang_(l),
-                 loc_gl(lang_.c_str()),
-                 mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
-       {
-               //lyxerr << "Messages: language(" << l
-               //       << ") in dir(" << dir << ")" << std::endl;
-
-               string const locale_dir = package().locale_dir().toFilesystemEncoding();
-               cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
-
-       }
-
-       ~Pimpl()
-       {
-               mssg_gl.close(cat_gl);
-       }
-
-       string const get(string const & msg) const
-       {
-               return mssg_gl.get(cat_gl, 0, 0, msg);
-       }
-private:
-       ///
-       string lang_;
-       ///
-       std::locale loc_gl;
-       ///
-       std::messages<char> const & mssg_gl;
-       ///
-       catalog cat_gl;
-};
-#else
-
-#ifdef HAVE_LOCALE_H
-#  include <locale.h>
-#endif
-
-#  if HAVE_GETTEXT
-#    include <libintl.h>      // use the header already in the system *EK*
-#  else
-#    include "../intl/libintl.h"
-#  endif
-
-// This is a more traditional variant.
-class Messages::Pimpl {
-public:
-       Pimpl(string const & l)
-               : lang_(l)
-       {
-               //lyxerr << "Messages: language(" << l
-               //       << ") in dir(" << dir << ")" << std::endl;
-
-       }
-
-       ~Pimpl() {}
-
-       docstring const get(string const & m) const
-       {
-               if (m.empty())
-                       return from_ascii(m);
-
-               char * o = setlocale(LC_ALL, 0);
-               string old;
-               if (o)
-                       old = o;
-               char * n = setlocale(LC_ALL, lang_.c_str());
-               if (!n)
-                       // If we are unable to honour the request we just
-                       // return what we got in.
-                       return from_ascii(m);
-               errno = 0;
-               string const locale_dir = package().locale_dir().toFilesystemEncoding();
-               char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
-               int e = errno;
-               if (e) {
-                       LYXERR(Debug::DEBUG)
-                               << BOOST_CURRENT_FUNCTION << '\n'
-                               << "Error code: " << errno << '\n'
-                               << "Lang, mess: " << lang_ << " " << m << '\n'
-                               << "Directory : " << package().locale_dir().absFilename() << '\n'
-                               << "Rtn value : " << c << endl;
-               }
-
-               if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
-                       LYXERR(Debug::DEBUG)
-                               << BOOST_CURRENT_FUNCTION << '\n'
-                               << "Error code: " << errno << '\n'
-                               << "Codeset   : " << ucs4_codeset << '\n'
-                               << endl;
-               }
-
-               textdomain(PACKAGE);
-
-               char const * tmp = m.c_str();
-               char const * msg = gettext(tmp);
-               docstring translated;
-               if (!msg) {
-                       lyxerr << "Undefined result from gettext" << endl;
-                       translated = from_ascii(tmp);
-               } else if (msg == tmp) {
-                       //lyxerr << "Same as entered returned" << endl;
-                       translated = from_ascii(tmp);
-               } else {
-                       LYXERR(Debug::DEBUG) << "We got a translation" << endl;
-                       char_type const * ucs4 = reinterpret_cast<char_type const *>(msg);
-                       translated = ucs4;
-               }
-               setlocale(LC_ALL, old.c_str());
-               return translated;
-       }
-private:
-       ///
-       string lang_;
-};
-#endif
-
-#else // ENABLE_NLS
-// This is the dummy variant.
-class Messages::Pimpl {
-public:
-       Pimpl(string const &) {}
-
-       ~Pimpl() {}
-
-       docstring const get(string const & m) const
-       {
-               return from_ascii(m);
-       }
-};
-#endif
-
-
-Messages::Messages()
-       : pimpl_(new Pimpl(""))
-{}
-
-
-Messages::Messages(string const & l)
-       : pimpl_(new Pimpl(l))
-{}
-
-
-// We need this for the sake of scoped_ptr
-Messages::~Messages()
-{}
-
-
-docstring const Messages::get(string const & msg) const
-{
-       return pimpl_->get(msg);
-}
-
-
-} // namespace lyx
diff --git a/src/client/messages.h b/src/client/messages.h
deleted file mode 100644 (file)
index 5eb9447..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// -*- C++ -*-
-/* \file Messages.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef MESSAGES_H
-#define MESSAGES_H
-
-#include "support/docstring.h"
-
-#include <boost/scoped_ptr.hpp>
-
-
-namespace lyx {
-
-///
-class Messages {
-public:
-       ///
-       Messages();
-       ///
-       Messages(std::string const & l);
-       ///
-       ~Messages();
-       ///
-       docstring const get(std::string const & msg) const;
-private:
-       class Pimpl;
-       boost::scoped_ptr<Pimpl> pimpl_;
-};
-
-
-} // namespace lyx
-
-#endif