X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FServer.cpp;h=1de758a5f46bd1b9507c9e2ad9b213d9a015c550;hb=86994bf75320524ec656fd70950633c83d445a6c;hp=33c32ea19ceac317ebd26010e91b85c78fecd087;hpb=68809af49bc9c77c4d54a55b5c020a7ca3a6bcb3;p=lyx.git diff --git a/src/Server.cpp b/src/Server.cpp index 33c32ea19c..1de758a5f4 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -34,30 +34,35 @@ received LyX will inform the client that it's listening its messages, and 'bye' will inform that lyx is closing. - See development/server_monitor.c for an example client. + See development/lyxserver/server_monitor.cpp for an example client. Purpose: implement a client/server lib for LyX */ #include #include "Server.h" + +#include "DispatchResult.h" #include "FuncRequest.h" +#include "LyX.h" #include "LyXAction.h" -#include "LyXFunc.h" #include "frontends/Application.h" #include "support/debug.h" #include "support/FileName.h" +#include "support/filetools.h" #include "support/lassert.h" #include "support/lstrings.h" #include "support/os.h" -#include +#include "support/bind.h" #ifdef _WIN32 +#include #include #endif +#include #include #ifdef HAVE_SYS_STAT_H @@ -138,6 +143,7 @@ LyXComm::LyXComm(string const & pip, Server * cli, ClientCallbackfct ccb) pipe_[i].handle = INVALID_HANDLE_VALUE; } ready_ = false; + deferred_loading_ = false; openConnection(); } @@ -513,8 +519,14 @@ void LyXComm::openConnection() return; } - // Check whether the pipe name is being used by some other program. + // Check whether the pipe name is being used by some other instance. if (!stopserver_ && WaitNamedPipe(inPipeName().c_str(), 0)) { + // Tell the running instance to load the files + if (run_mode == USE_REMOTE && loadFilesInOtherInstance()) { + deferred_loading_ = true; + pipename_.erase(); + return; + } lyxerr << "LyXComm: Pipe " << external_path(inPipeName()) << " already exists.\nMaybe another instance of LyX" " is using it." << endl; @@ -683,6 +695,7 @@ string const LyXComm::pipeName(DWORD index) const LyXComm::LyXComm(string const &, Server *, ClientCallbackfct) {} + void LyXComm::openConnection() {} @@ -704,6 +717,7 @@ void LyXComm::endPipe(int & fd, string const & filename, bool write) void LyXComm::emergencyCleanup() {} + void LyXComm::read_ready() {} @@ -714,11 +728,11 @@ void LyXComm::send(string const & msg) #else // defined (HAVE_MKFIFO) - LyXComm::LyXComm(string const & pip, Server * cli, ClientCallbackfct ccb) : pipename_(pip), client_(cli), clientcb_(ccb) { ready_ = false; + deferred_loading_ = false; openConnection(); } @@ -796,6 +810,12 @@ int LyXComm::startPipe(string const & file, bool write) if (fd >= 0) { // Another LyX instance is using it. ::close(fd); + // Tell the running instance to load the files + if (run_mode == USE_REMOTE && loadFilesInOtherInstance()) { + deferred_loading_ = true; + pipename_.erase(); + return -1; + } } else if (errno == ENXIO) { // No process is reading from the other end. stalepipe = true; @@ -838,7 +858,7 @@ int LyXComm::startPipe(string const & file, bool write) if (!write) { theApp()->registerSocketCallback(fd, - boost::bind(&LyXComm::read_ready, this)); + bind(&LyXComm::read_ready, this)); } return fd; @@ -896,7 +916,6 @@ void LyXComm::read_ready() int status; // the single = is intended here. while ((status = ::read(infd_, charbuf, charbuf_size - 1))) { - if (status > 0) { charbuf[status] = '\0'; // turn it into a c string read_buffer_ += rtrim(charbuf, "\r"); @@ -947,7 +966,8 @@ void LyXComm::send(string const & msg) LYXERR(Debug::LYXSERVER, "LyXComm: Sending '" << msg << '\''); - if (pipename_.empty()) return; + if (pipename_.empty()) + return; if (!ready_) { LYXERR0("LyXComm: Pipes are closed. Could not send " << msg); @@ -962,6 +982,49 @@ void LyXComm::send(string const & msg) #endif // defined (HAVE_MKFIFO) +namespace { + +struct Sleep : QThread +{ + static void millisec(unsigned long ms) + { + QThread::usleep(ms * 1000); + } +}; + +} // namespace anon + + +bool LyXComm::loadFilesInOtherInstance() +{ + int pipefd; + int loaded_files = 0; + FileName const pipe(inPipeName()); + vector::iterator it = theFilesToLoad().begin(); + while (it != theFilesToLoad().end()) { + FileName fname = fileSearch(string(), os::internal_path(*it), + "lyx", may_not_exist); + if (fname.empty()) { + ++it; + continue; + } + // Wait a while to allow time for the other + // instance to reset the connection + Sleep::millisec(200); + pipefd = ::open(pipe.toFilesystemEncoding().c_str(), O_WRONLY); + if (pipefd < 0) + break; + string const cmd = "LYXCMD:pipe:file-open:" + + fname.absFileName() + '\n'; + if (::write(pipefd, cmd.c_str(), cmd.length()) < 0) + LYXERR0("Cannot write to pipe!"); + ::close(pipefd); + ++loaded_files; + it = theFilesToLoad().erase(it); + } + return loaded_files > 0; +} + string const LyXComm::inPipeName() const { @@ -986,8 +1049,8 @@ void ServerCallback(Server * server, string const & msg) server->callback(msg); } -Server::Server(LyXFunc * f, string const & pipes) - : numclients_(0), func_(f), pipes_(pipes, this, &ServerCallback) +Server::Server(string const & pipes) + : numclients_(0), pipes_(pipes, this, &ServerCallback) {} @@ -1006,7 +1069,6 @@ Server::~Server() int compare(char const * a, char const * b, unsigned int len) { - using namespace std; return strncmp(a, b, len); } @@ -1108,17 +1170,20 @@ void Server::callback(string const & msg) // The correct solution would be to have a // specialized (non-gui) BufferView. But how do // we do it now? Probably we should just let it - // connect to the lyxfunc in the single LyXView we + // connect to the lyxfunc in the single GuiView we // support currently. (Lgb) - func_->dispatch(FuncRequest(lyxaction.lookupFunc(cmd), arg)); - string const rval = to_utf8(func_->getMessage()); + FuncRequest fr(lyxaction.lookupFunc(cmd), arg); + fr.setOrigin(FuncRequest::LYXSERVER); + DispatchResult dr; + theApp()->dispatch(fr, dr); + string const rval = to_utf8(dr.message()); // all commands produce an INFO or ERROR message // in the output pipe, even if they do not return // anything. See chapter 4 of Customization doc. string buf; - if (func_->errorStat()) + if (dr.error()) buf = "ERROR:"; else buf = "INFO:";