]> git.lyx.org Git - lyx.git/blobdiff - src/Server.cpp
User frontend for the new document-wide bibliography style feature.
[lyx.git] / src / Server.cpp
index 08867d837c354d781fe9cbe55f0b205414e0f052..fed89ace5b0ce4813f65745133dd79bb55449667 100644 (file)
           received LyX will inform the client that it's listening its
           messages, and 'bye' will inform that lyx is closing.
 
           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"
   Purpose: implement a client/server lib for LyX
 */
 
 #include <config.h>
 
 #include "Server.h"
+
+#include "DispatchResult.h"
 #include "FuncRequest.h"
 #include "FuncRequest.h"
+#include "LyX.h"
 #include "LyXAction.h"
 #include "LyXAction.h"
-#include "LyXFunc.h"
 
 #include "frontends/Application.h"
 
 #include "support/debug.h"
 #include "support/FileName.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 "support/lassert.h"
 #include "support/lstrings.h"
 #include "support/os.h"
 
-#include <boost/bind.hpp>
+#include "support/bind.h"
 
 #ifdef _WIN32
 
 #ifdef _WIN32
+#include <io.h>
 #include <QCoreApplication>
 #endif
 #include <QCoreApplication>
 #endif
+#include <QThread>
 
 #include <cerrno>
 #ifdef HAVE_SYS_STAT_H
 
 #include <cerrno>
 #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;
                pipe_[i].handle = INVALID_HANDLE_VALUE;
        }
        ready_ = false;
+       deferred_loading_ = false;
        openConnection();
 }
 
        openConnection();
 }
 
@@ -319,8 +325,8 @@ bool LyXComm::pipeServer()
                                QCoreApplication::postEvent(this,
                                                static_cast<QEvent *>(event));
                                // Wait for completion
                                QCoreApplication::postEvent(this,
                                                static_cast<QEvent *>(event));
                                // Wait for completion
-                               while (pipe_[i].nbytes && !checkStopServer())
-                                       Sleep(100);
+                               while (pipe_[i].nbytes && !checkStopServer(100))
+                                       ;
                                pipe_[i].pending_io = false;
                                pipe_[i].state = READING_STATE;
                                continue;
                                pipe_[i].pending_io = false;
                                pipe_[i].state = READING_STATE;
                                continue;
@@ -354,7 +360,7 @@ bool LyXComm::pipeServer()
                                // We get here when a reader is started
                                // well before a reply is ready, so delay
                                // a bit in order to not burden the cpu.
                                // We get here when a reader is started
                                // well before a reply is ready, so delay
                                // a bit in order to not burden the cpu.
-                               Sleep(100);
+                               checkStopServer(100);
                                pipe_[i].pending_io = true;
                                continue;
                        }
                                pipe_[i].pending_io = true;
                                continue;
                        }
@@ -406,15 +412,17 @@ bool LyXComm::event(QEvent * e)
 }
 
 
 }
 
 
-bool LyXComm::checkStopServer()
+bool LyXComm::checkStopServer(DWORD timeout)
 {
 {
-       return WaitForSingleObject(stopserver_, 0) == WAIT_OBJECT_0;
+       return WaitForSingleObject(stopserver_, timeout) == WAIT_OBJECT_0;
 }
 
 
 bool LyXComm::startPipe(DWORD index)
 {
        pipe_[index].pending_io = false;
 }
 
 
 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)) {
 
        // Overlapped ConnectNamedPipe should return zero.
        if (ConnectNamedPipe(pipe_[index].handle, &pipe_[index].overlap)) {
@@ -511,8 +519,14 @@ void LyXComm::openConnection()
                return;
        }
 
                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)) {
        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;
                lyxerr << "LyXComm: Pipe " << external_path(inPipeName())
                       << " already exists.\nMaybe another instance of LyX"
                          " is using it." << endl;
@@ -664,8 +678,7 @@ void LyXComm::send(string const & msg)
                       << "\nLyXComm: Resetting connection" << endl;
                ReleaseMutex(outbuf_mutex_);
                closeConnection();
                       << "\nLyXComm: Resetting connection" << endl;
                ReleaseMutex(outbuf_mutex_);
                closeConnection();
-               if (!checkStopServer())
-                       openConnection();
+               openConnection();
        }
 }
 
        }
 }
 
@@ -718,6 +731,7 @@ LyXComm::LyXComm(string const & pip, Server * cli, ClientCallbackfct ccb)
        : pipename_(pip), client_(cli), clientcb_(ccb)
 {
        ready_ = false;
        : pipename_(pip), client_(cli), clientcb_(ccb)
 {
        ready_ = false;
+       deferred_loading_ = false;
        openConnection();
 }
 
        openConnection();
 }
 
@@ -795,6 +809,12 @@ int LyXComm::startPipe(string const & file, bool write)
                        if (fd >= 0) {
                                // Another LyX instance is using it.
                                ::close(fd);
                        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;
                        } else if (errno == ENXIO) {
                                // No process is reading from the other end.
                                stalepipe = true;
@@ -837,7 +857,7 @@ int LyXComm::startPipe(string const & file, bool write)
 
        if (!write) {
                theApp()->registerSocketCallback(fd,
 
        if (!write) {
                theApp()->registerSocketCallback(fd,
-                       boost::bind(&LyXComm::read_ready, this));
+                       bind(&LyXComm::read_ready, this));
        }
 
        return fd;
        }
 
        return fd;
@@ -961,6 +981,49 @@ void LyXComm::send(string const & msg)
 
 #endif // defined (HAVE_MKFIFO)
 
 
 #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';
+               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
 {
 
 string const LyXComm::inPipeName() const
 {
@@ -985,8 +1048,8 @@ void ServerCallback(Server * server, string const & msg)
        server->callback(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)
 {}
 
 
 {}
 
 
@@ -1107,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
                        // 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)
 
                        // 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;
 
                        // 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:";
                                buf = "ERROR:";
                        else
                                buf = "INFO:";