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 <config.h>
#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 <boost/bind.hpp>
+#include "support/bind.h"
#ifdef _WIN32
+#include <io.h>
#include <QCoreApplication>
#endif
+#include <QThread>
#include <cerrno>
#ifdef HAVE_SYS_STAT_H
pipe_[i].handle = INVALID_HANDLE_VALUE;
}
ready_ = false;
+ deferred_loading_ = false;
openConnection();
}
bool LyXComm::startPipe(DWORD index)
{
pipe_[index].pending_io = false;
+ pipe_[index].overlap.Offset = 0;
+ pipe_[index].overlap.OffsetHigh = 0;
// Overlapped ConnectNamedPipe should return zero.
if (ConnectNamedPipe(pipe_[index].handle, &pipe_[index].overlap)) {
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;
<< "\nLyXComm: Resetting connection" << endl;
ReleaseMutex(outbuf_mutex_);
closeConnection();
- if (!checkStopServer())
- openConnection();
+ openConnection();
}
}
: pipename_(pip), client_(cli), clientcb_(ccb)
{
ready_ = false;
+ deferred_loading_ = false;
openConnection();
}
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;
if (!write) {
theApp()->registerSocketCallback(fd,
- boost::bind(&LyXComm::read_ready, this));
+ bind(&LyXComm::read_ready, this));
}
return fd;
#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<string>::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';
+ ::write(pipefd, cmd.c_str(), cmd.length());
+ ::close(pipefd);
+ ++loaded_files;
+ it = theFilesToLoad().erase(it);
+ }
+ return loaded_files > 0;
+}
+
string const LyXComm::inPipeName() const
{
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)
{}
// 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 const fr(lyxaction.lookupFunc(cmd), arg);
+ DispatchResult dr;
+ theApp()->dispatch(fr, dr);
+ theApp()->dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
+ 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:";