]> git.lyx.org Git - lyx.git/blobdiff - src/Server.cpp
Fix -Winconsistent-missing-override
[lyx.git] / src / Server.cpp
index 51007d85a3c0940bc3189dc2d0e449d902a5c9ab..522060e91b6a70682b7ad0163ae9449cafbb240e 100644 (file)
           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 <iostream>
 
 #ifdef _WIN32
-#include <QCoreApplication>
+# include <io.h>
+# include <QCoreApplication>
+#else
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+# endif
 #endif
+#include <QThread>
 
 #include <cerrno>
 #ifdef HAVE_SYS_STAT_H
@@ -93,43 +102,60 @@ private:
 
 namespace {
 
-char * errormsg()
+string errormsg(DWORD const error)
 {
        void * msgbuf;
-       DWORD error = GetLastError();
-       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                     FORMAT_MESSAGE_FROM_SYSTEM |
-                     FORMAT_MESSAGE_IGNORE_INSERTS,
-                     NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                     (LPTSTR) &msgbuf, 0, NULL);
-       return static_cast<char *>(msgbuf);
+       string message;
+       if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                         FORMAT_MESSAGE_FROM_SYSTEM |
+                         FORMAT_MESSAGE_IGNORE_INSERTS,
+                         NULL, error,
+                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                         (LPTSTR) &msgbuf, 0, NULL)) {
+               message = static_cast<char *>(msgbuf);
+               LocalFree(msgbuf);
+       } else
+               message = "Unknown error";
+
+       return message;
 }
 
+} // namespace
 
-extern "C" {
 
 DWORD WINAPI pipeServerWrapper(void * arg)
 {
        LyXComm * lyxcomm = reinterpret_cast<LyXComm *>(arg);
-       lyxcomm->pipeServer();
+       if (!lyxcomm->pipeServer()) {
+               // Error exit; perform cleanup.
+               lyxcomm->ready_ = false;
+               lyxcomm->closeHandles();
+               CloseHandle(lyxcomm->server_thread_);
+               CloseHandle(lyxcomm->stopserver_);
+               CloseHandle(lyxcomm->outbuf_mutex_);
+               lyxerr << "LyXComm: Closing connection" << endl;
+       }
        return 1;
 }
 
-}
-
-} // namespace anon
 
 LyXComm::LyXComm(string const & pip, Server * cli, ClientCallbackfct ccb)
-       : pipename_(pip), client_(cli), clientcb_(ccb), stopserver_(0)
+       : stopserver_(0),
+         ready_(false), pipename_(pip), client_(cli), clientcb_(ccb),
+         deferred_loading_(false)
 {
-       ready_ = false;
+       for (int i = 0; i < MAX_PIPES; ++i) {
+               event_[i] = 0;
+               pipe_[i].handle = INVALID_HANDLE_VALUE;
+       }
        openConnection();
 }
 
 
-void LyXComm::pipeServer()
+bool LyXComm::pipeServer()
 {
        DWORD i;
+       DWORD error;
 
        for (i = 0; i < MAX_PIPES; ++i) {
                bool const is_outpipe = i >= MAX_CLIENTS;
@@ -140,29 +166,30 @@ void LyXComm::pipeServer()
                // Manual-reset event, initial state = signaled
                event_[i] = CreateEvent(NULL, TRUE, TRUE, NULL);
                if (!event_[i]) {
+                       error = GetLastError();
                        lyxerr << "LyXComm: Could not create event for pipe "
-                              << pipename.c_str() << "\nLyXComm: "
-                              << errormsg() << endl;
-                       closeHandles(i);
-                       return;
+                              << pipename << "\nLyXComm: "
+                              << errormsg(error) << endl;
+                       return false;
                }
 
                pipe_[i].overlap.hEvent = event_[i];
                pipe_[i].iobuf.erase();
-               pipe_[i].handle = CreateNamedPipe(pipename.c_str(),
+               pipe_[i].handle = CreateNamedPipeA(pipename.c_str(),
                                open_mode | FILE_FLAG_OVERLAPPED, PIPE_WAIT,
                                MAX_CLIENTS, PIPE_BUFSIZE, PIPE_BUFSIZE,
                                PIPE_TIMEOUT, NULL);
 
                if (pipe_[i].handle == INVALID_HANDLE_VALUE) {
+                       error = GetLastError();
                        lyxerr << "LyXComm: Could not create pipe "
-                              << pipename.c_str() << "\nLyXComm: "
-                              << errormsg() << endl;
-                       closeHandles(i);
-                       return;
+                              << pipename << "\nLyXComm: "
+                              << errormsg(error) << endl;
+                       return false;
                }
 
-               startPipe(i);
+               if (!startPipe(i))
+                       return false;
                pipe_[i].state = pipe_[i].pending_io ?
                        CONNECTING_STATE : (is_outpipe ? WRITING_STATE
                                                       : READING_STATE);
@@ -175,8 +202,8 @@ void LyXComm::pipeServer()
        LYXERR(Debug::LYXSERVER, "LyXComm: Connection established");
        ready_ = true;
        outbuf_.erase();
-       DWORD status;
-       bool success;
+       DWORD status = 0;
+       bool success = false;
 
        while (!checkStopServer()) {
                // Indefinitely wait for the completion of an overlapped
@@ -186,7 +213,7 @@ void LyXComm::pipeServer()
 
                // Determine which pipe instance completed the operation.
                i = wait - WAIT_OBJECT_0;
-               LASSERT(i >= 0 && i <= MAX_PIPES, /**/);
+               LASSERT(i <= MAX_PIPES, /**/);
 
                // Check whether we were waked up for stopping the pipe server.
                if (i == MAX_PIPES)
@@ -203,9 +230,11 @@ void LyXComm::pipeServer()
                        case CONNECTING_STATE:
                                // Pending connect operation
                                if (!success) {
+                                       error = GetLastError();
                                        lyxerr << "LyXComm: "
-                                              << errormsg() << endl;
-                                       resetPipe(i, true);
+                                              << errormsg(error) << endl;
+                                       if (!resetPipe(i, true))
+                                               return false;
                                        continue;
                                }
                                pipe_[i].state = is_outpipe ? WRITING_STATE
@@ -216,7 +245,8 @@ void LyXComm::pipeServer()
                                // Pending read operation
                                LASSERT(!is_outpipe, /**/);
                                if (!success || status == 0) {
-                                       resetPipe(i);
+                                       if (!resetPipe(i, !success))
+                                               return false;
                                        continue;
                                }
                                pipe_[i].nbytes = status;
@@ -267,24 +297,28 @@ void LyXComm::pipeServer()
                                continue;
                        }
 
-                       if (!success && GetLastError() == ERROR_IO_PENDING) {
+                       error = GetLastError();
+
+                       if (!success && error == ERROR_IO_PENDING) {
                                // The read operation is still pending.
                                pipe_[i].pending_io = true;
                                continue;
                        }
 
+                       success = error == ERROR_BROKEN_PIPE;
+
                        // Client closed connection (ERROR_BROKEN_PIPE) or
                        // an error occurred; in either case, reset the pipe.
-                       if (GetLastError() != ERROR_BROKEN_PIPE) {
-                               lyxerr << "LyXComm: " << errormsg() << endl;
+                       if (!success) {
+                               lyxerr << "LyXComm: " << errormsg(error) << endl;
                                if (!pipe_[i].iobuf.empty()) {
                                        lyxerr << "LyXComm: truncated command: "
                                               << pipe_[i].iobuf << endl;
                                        pipe_[i].iobuf.erase();
                                }
-                               resetPipe(i, true);
-                       } else
-                               resetPipe(i);
+                       }
+                       if (!resetPipe(i, !success))
+                               return false;
                        break;
 
                case WRITING_STATE:
@@ -295,8 +329,8 @@ void LyXComm::pipeServer()
                                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;
@@ -318,47 +352,59 @@ void LyXComm::pipeServer()
                                // The write operation completed successfully.
                                pipe_[i].iobuf.erase();
                                pipe_[i].pending_io = false;
-                               resetPipe(i);
+                               if (!resetPipe(i))
+                                       return false;
                                continue;
                        }
 
-                       if (GetLastError() == ERROR_IO_PENDING) {
+                       error = GetLastError();
+
+                       if (success && (error == ERROR_IO_PENDING || error == NO_ERROR)) {
                                // The write operation is still pending.
                                // 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;
                        }
 
+                       success = error == ERROR_NO_DATA;
+
                        // Client closed connection (ERROR_NO_DATA) or
                        // an error occurred; in either case, reset the pipe.
-                       if (GetLastError() != ERROR_NO_DATA) {
+                       if (!success) {
                                lyxerr << "LyXComm: Error sending message: "
                                       << pipe_[i].iobuf << "\nLyXComm: "
-                                      << errormsg() << endl;
-                               resetPipe(i, true);
-                       } else
-                               resetPipe(i);
+                                      << errormsg(error) << endl;
+                       }
+                       if (!resetPipe(i, !success))
+                               return false;
+                       break;
+               case CONNECTING_STATE:
+                       LYXERR0("Wrong pipe state");
                        break;
                }
        }
 
        ready_ = false;
-       closeHandles(MAX_PIPES - 1);
+       closeHandles();
+       return true;
 }
 
 
-void LyXComm::closeHandles(DWORD index)
+void LyXComm::closeHandles()
 {
-       for (int i = 0; i <= index; ++i) {
+       for (int i = 0; i < MAX_PIPES; ++i) {
                if (event_[i]) {
                        ResetEvent(event_[i]);
                        CloseHandle(event_[i]);
+                       event_[i] = 0;
                }
-               if (pipe_[i].handle != INVALID_HANDLE_VALUE)
+               if (pipe_[i].handle != INVALID_HANDLE_VALUE) {
                        CloseHandle(pipe_[i].handle);
+                       pipe_[i].handle = INVALID_HANDLE_VALUE;
+               }
        }
 }
 
@@ -373,23 +419,25 @@ 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;
 }
 
 
-void LyXComm::startPipe(DWORD index)
+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)) {
-               // FIXME: What to do? Maybe the pipe server should be reset.
+               DWORD const error = GetLastError();
                lyxerr << "LyXComm: Could not connect pipe "
                       << external_path(pipeName(index))
-                      << "\nLyXComm: " << errormsg() << endl;
-               return;
+                      << "\nLyXComm: " << errormsg(error) << endl;
+               return false;
        }
 
        switch (GetLastError()) {
@@ -402,26 +450,31 @@ void LyXComm::startPipe(DWORD index)
                // Client is already connected, so signal an event.
                if (SetEvent(pipe_[index].overlap.hEvent))
                        break;
+               // fall through
        default:
                // Anything else is an error.
-               // FIXME: What to do? Maybe the pipe server should be reset.
+               DWORD const error = GetLastError();
                lyxerr << "LyXComm: An error occurred while connecting pipe "
                       << external_path(pipeName(index))
-                      << "\nLyXComm: " << errormsg() << endl;
+                      << "\nLyXComm: " << errormsg(error) << endl;
+               return false;
        }
+
+       return true;
 }
 
 
-void LyXComm::resetPipe(DWORD index, bool close_handle)
+bool LyXComm::resetPipe(DWORD index, bool close_handle)
 {
        // This method is called when an error occurs or when a client
        // closes the connection. We first disconnect the pipe instance,
        // then reconnect it, ready to wait for another client.
 
        if (!DisconnectNamedPipe(pipe_[index].handle)) {
+               DWORD const error = GetLastError();
                lyxerr << "LyXComm: Could not disconnect pipe "
                       << external_path(pipeName(index))
-                      << "\nLyXComm: " << errormsg() << endl;
+                      << "\nLyXComm: " << errormsg(error) << endl;
                // What to do now? Let's try whether re-creating the pipe helps.
                close_handle = true;
        }
@@ -436,22 +489,25 @@ void LyXComm::resetPipe(DWORD index, bool close_handle)
                CloseHandle(pipe_[index].handle);
 
                pipe_[index].iobuf.erase();
-               pipe_[index].handle = CreateNamedPipe(name.c_str(),
+               pipe_[index].handle = CreateNamedPipeA(name.c_str(),
                                open_mode | FILE_FLAG_OVERLAPPED, PIPE_WAIT,
                                MAX_CLIENTS, PIPE_BUFSIZE, PIPE_BUFSIZE,
                                PIPE_TIMEOUT, NULL);
 
                if (pipe_[index].handle == INVALID_HANDLE_VALUE) {
+                       DWORD const error = GetLastError();
                        lyxerr << "LyXComm: Could not reset pipe " << name
-                              << "\nLyXComm: " << errormsg() << endl;
-                       return;
+                              << "\nLyXComm: " << errormsg(error) << endl;
+                       return false;
                }
        }
 
-       startPipe(index);
+       if (!startPipe(index))
+               return false;
        pipe_[index].state = pipe_[index].pending_io ?
                        CONNECTING_STATE : (is_outpipe ? WRITING_STATE
                                                       : READING_STATE);
+       return true;
 }
 
 
@@ -464,16 +520,20 @@ void LyXComm::openConnection()
                LYXERR(Debug::LYXSERVER, "LyXComm: Already connected");
                return;
        }
-       // We assume that we don't make it
-       ready_ = false;
 
        if (pipename_.empty()) {
                LYXERR(Debug::LYXSERVER, "LyXComm: server is disabled, nothing to do");
                return;
        }
 
-       // Check whether the pipe name is being used by some other program.
-       if (!stopserver_ && WaitNamedPipe(inPipeName().c_str(), 0)) {
+       // Check whether the pipe name is being used by some other instance.
+       if (!stopserver_ && WaitNamedPipeA(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;
@@ -484,8 +544,9 @@ void LyXComm::openConnection()
        // Mutex with no initial owner for synchronized access to outbuf_
        outbuf_mutex_ = CreateMutex(NULL, FALSE, NULL);
        if (!outbuf_mutex_) {
+               DWORD const error = GetLastError();
                lyxerr << "LyXComm: Could not create output buffer mutex"
-                      << "\nLyXComm: " << errormsg() << endl;
+                      << "\nLyXComm: " << errormsg(error) << endl;
                pipename_.erase();
                return;
        }
@@ -493,8 +554,9 @@ void LyXComm::openConnection()
        // Manual-reset event, initial state = not signaled
        stopserver_ = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!stopserver_) {
+               DWORD const error = GetLastError();
                lyxerr << "LyXComm: Could not create stop server event"
-                      << "\nLyXComm: " << errormsg() << endl;
+                      << "\nLyXComm: " << errormsg(error) << endl;
                pipename_.erase();
                CloseHandle(outbuf_mutex_);
                return;
@@ -503,8 +565,9 @@ void LyXComm::openConnection()
        server_thread_ = CreateThread(NULL, 0, pipeServerWrapper,
                                     static_cast<void *>(this), 0, NULL);
        if (!server_thread_) {
+               DWORD const error = GetLastError();
                lyxerr << "LyXComm: Could not create pipe server thread"
-                      << "\nLyXComm: " << errormsg() << endl;
+                      << "\nLyXComm: " << errormsg(error) << endl;
                pipename_.erase();
                CloseHandle(stopserver_);
                CloseHandle(outbuf_mutex_);
@@ -544,8 +607,11 @@ void LyXComm::emergencyCleanup()
                SetEvent(stopserver_);
                // Forcibly terminate the pipe server thread if it does
                // not finish quickly.
-               if (WaitForSingleObject(server_thread_, 200) != WAIT_OBJECT_0)
+               if (WaitForSingleObject(server_thread_, 200) != WAIT_OBJECT_0) {
                        TerminateThread(server_thread_, 0);
+                       ready_ = false;
+                       closeHandles();
+               }
                CloseHandle(server_thread_);
                ResetEvent(stopserver_);
                CloseHandle(stopserver_);
@@ -613,13 +679,13 @@ void LyXComm::send(string const & msg)
                ReleaseMutex(outbuf_mutex_);
        } else {
                // Something is fishy, better resetting the connection.
+               DWORD const error = GetLastError();
                lyxerr << "LyXComm: Error sending message: " << msg
-                      << "\nLyXComm: " << errormsg()
-                      << "LyXComm: Resetting connection" << endl;
+                      << "\nLyXComm: " << errormsg(error)
+                      << "\nLyXComm: Resetting connection" << endl;
                ReleaseMutex(outbuf_mutex_);
                closeConnection();
-               if (!checkStopServer())
-                       openConnection();
+               openConnection();
        }
 }
 
@@ -636,6 +702,7 @@ string const LyXComm::pipeName(DWORD index) const
 LyXComm::LyXComm(string const &, Server *, ClientCallbackfct)
 {}
 
+
 void LyXComm::openConnection()
 {}
 
@@ -657,6 +724,7 @@ void LyXComm::endPipe(int & fd, string const & filename, bool write)
 void LyXComm::emergencyCleanup()
 {}
 
+
 void LyXComm::read_ready()
 {}
 
@@ -667,11 +735,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)
+       : infd_(-1), outfd_(-1),
+         ready_(false), pipename_(pip), client_(cli), clientcb_(ccb),
+         deferred_loading_(false)
 {
-       ready_ = false;
        openConnection();
 }
 
@@ -749,6 +817,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;
@@ -790,8 +864,12 @@ int LyXComm::startPipe(string const & file, bool write)
        }
 
        if (!write) {
-               theApp()->registerSocketCallback(fd,
-                       boost::bind(&LyXComm::read_ready, this));
+               // Make sure not to call read_ready after destruction.
+               weak_ptr<void> tracker = tracker_.p();
+               theApp()->registerSocketCallback(fd, [this, tracker](){
+                               if (!tracker.expired())
+                                       read_ready();
+                       });
        }
 
        return fd;
@@ -811,7 +889,7 @@ void LyXComm::endPipe(int & fd, string const & filename, bool write)
                       << '\n' << strerror(errno) << endl;
        }
 
-       if (FileName(filename).removeFile() < 0) {
+       if (!FileName(filename).removeFile()) {
                lyxerr << "LyXComm: Could not remove pipe " << filename
                       << '\n' << strerror(errno) << endl;
        }
@@ -849,7 +927,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");
@@ -900,7 +977,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);
@@ -915,6 +993,65 @@ 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
+
+
+bool LyXComm::loadFilesInOtherInstance() const
+{
+       int pipefd;
+       FileName const pipe(inPipeName());
+
+       if (theFilesToLoad().empty()) {
+               LYXERR0("LyX is already running in another instance\n"
+                       "and 'use single instance' is active.");
+               // Wait a while for the other instance to reset the connection
+               Sleep::millisec(200);
+               pipefd = ::open(pipe.toFilesystemEncoding().c_str(), O_WRONLY);
+               if (pipefd >= 0) {
+                       string const cmd = "LYXCMD:pipe:window-raise\n";
+                       if (::write(pipefd, cmd.c_str(), cmd.length()) < 0)
+                               LYXERR0("Cannot communicate with running instance!");
+                       ::close(pipefd);
+               }
+               return true;
+       }
+
+       int loaded_files = 0;
+       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
 {
@@ -939,8 +1076,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)
 {}
 
 
@@ -959,7 +1096,6 @@ Server::~Server()
 
 int compare(char const * a, char const * b, unsigned int len)
 {
-       using namespace std;
        return strncmp(a, b, len);
 }
 
@@ -1048,7 +1184,7 @@ void Server::callback(string const & msg)
                                                << client << " said goodbye");
                                } else {
                                        LYXERR(Debug::LYXSERVER,
-                                               "Server: ignoring bye messge from unregistered client" << client);
+                                               "Server: ignoring bye message from unregistered client" << client);
                                }
                        } else {
                                LYXERR0("Server: Undefined server command " << cmd << '.');
@@ -1061,17 +1197,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), from_utf8(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:";