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 "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();
}
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;
: 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
{
// 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)
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