]> git.lyx.org Git - lyx.git/blob - src/Server.h
Fix #10778 (issue with CJK and language nesting)
[lyx.git] / src / Server.h
1 // -*- C++ -*-
2 /**
3  * \file Server.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Enrico Forestieri
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #ifndef SERVER_H
15 #define SERVER_H
16
17 #include <boost/signals/trackable.hpp>
18
19 #ifdef _WIN32
20 #include <windows.h>
21 #include <QObject>
22 #include <QEvent>
23 #endif
24
25
26 namespace lyx {
27
28 class Server;
29
30
31 /** This class managed the pipes used for communicating with clients.
32  Usage: Initialize with pipe-filename-base, client class to receive
33  messages, and callback-function that will be called with the messages.
34  When you want to send, use "send()".
35  This class encapsulates all the dirty communication and thus provides
36  a clean string interface.
37  */
38 #ifndef _WIN32
39 class LyXComm : public boost::signals::trackable {
40 #else
41 class LyXComm : public QObject {
42         Q_OBJECT
43
44         friend DWORD WINAPI pipeServerWrapper(void *);
45
46 public:
47         /// Max number of clients
48         enum { MAX_CLIENTS = 10 };
49
50 private:
51         /// Max number of pipe instances
52         enum { MAX_PIPES = 2 * MAX_CLIENTS };
53
54         /// I/O buffer size
55         enum { PIPE_BUFSIZE = 512 };
56
57         /// Pipe client time-out
58         enum { PIPE_TIMEOUT = 5000 };
59
60         /// Pipe states
61         enum PipeState {
62                 CONNECTING_STATE,
63                 READING_STATE,
64                 WRITING_STATE
65         };
66
67         /// Pipe instances
68         typedef struct {
69                 OVERLAPPED overlap;
70                 HANDLE handle;
71                 std::string iobuf;
72                 char readbuf[PIPE_BUFSIZE];
73                 DWORD nbytes;
74                 PipeState state;
75                 bool pending_io;
76         } PipeInst;
77 #endif
78 public:
79         /** When we receive a message, we send it to a client.
80           This is one of the small things that would have been a lot
81           cleaner with a Signal/Slot thing.
82          */
83         typedef void (*ClientCallbackfct)(Server *, std::string const &);
84
85         /// Construct with pipe-basename and callback to receive messages
86         LyXComm(std::string const & pip, Server * cli, ClientCallbackfct ccb = 0);
87
88         ///
89         ~LyXComm() { closeConnection(); }
90
91         /// clean up in emergency
92         void emergencyCleanup();
93
94         /// Send message
95         void send(std::string const &);
96
97         /// asynch ready-to-be-read notification
98 #ifndef _WIN32
99         void read_ready();
100 #else
101         void read_ready(DWORD);
102 #endif
103
104         /// Tell whether we asked another instance of LyX to open the files
105         bool deferredLoading() { return deferred_loading_; }
106
107 private:
108         /// the filename of the in pipe
109         std::string const inPipeName() const;
110
111         /// the filename of the out pipe
112         std::string const outPipeName() const;
113
114         /// Open pipes
115         void openConnection();
116
117         /// Close pipes
118         void closeConnection();
119
120         /// Load files in another running instance of LyX
121         bool loadFilesInOtherInstance();
122
123 #ifndef _WIN32
124         /// start a pipe
125         int startPipe(std::string const &, bool);
126
127         /// finish a pipe
128         void endPipe(int &, std::string const &, bool);
129
130         /// This is -1 if not open
131         int infd_;
132
133         /// This is -1 if not open
134         int outfd_;
135 #else
136         /// The pipe server returns false when exiting due to an error
137         bool pipeServer();
138
139         /// Start an overlapped connection
140         bool startPipe(DWORD);
141
142         /// Reset an overlapped connection
143         bool resetPipe(DWORD, bool close_handle = false);
144
145         /// Close event and pipe handles
146         void closeHandles();
147
148         /// Catch pipe ready-to-be-read notification
149         bool event(QEvent *);
150
151         /// Check whether the pipe server must be stopped
152         bool checkStopServer(DWORD timeout = 0);
153
154         /// The filename of a (in or out) pipe instance
155         std::string const pipeName(DWORD) const;
156
157         /// Pipe instances
158         PipeInst pipe_[MAX_PIPES];
159
160         /// Pipe server control events
161         HANDLE event_[MAX_PIPES + 1];
162
163         /// Reply buffer
164         std::string outbuf_;
165
166         /// Synchronize access to outbuf_
167         HANDLE outbuf_mutex_;
168
169         /// Windows event for stopping the pipe server
170         HANDLE stopserver_;
171
172         /// Pipe server thread handle
173         HANDLE server_thread_;
174 #endif
175
176         /// Are we up and running?
177         bool ready_;
178
179         /// Base of pipename including path
180         std::string pipename_;
181
182         /// The client
183         Server * client_;
184
185         /// The client callback function
186         ClientCallbackfct clientcb_;
187
188         /// Did we defer loading of files to another instance?
189         bool deferred_loading_;
190 };
191
192
193 ///
194 class Server {
195 public:
196         // FIXME IN 0.13
197         // Hack! This should be changed in 0.13
198
199         // IMO lyxserver is atypical, and for the moment the only one, non-gui
200         // bufferview. We just have to find a way to handle situations like if
201         // lyxserver is using a buffer that is being edited with a bufferview.
202         // With a common buffer list this is not a problem, maybe. (Alejandro)
203         ///
204         Server(std::string const & pip);
205         ///
206         ~Server();
207         ///
208         void notifyClient(std::string const &);
209         ///
210         bool deferredLoadingToOtherInstance() { return pipes_.deferredLoading(); }
211
212         /// whilst crashing etc.
213         void emergencyCleanup() { pipes_.emergencyCleanup(); }
214         ///
215         void callback(std::string const & msg);
216
217 private:
218         /// Names and number of current clients
219 #ifndef _WIN32
220         enum { MAX_CLIENTS = 10 };
221 #else
222         enum { MAX_CLIENTS = LyXComm::MAX_CLIENTS };
223 #endif
224         ///
225         std::string clients_[MAX_CLIENTS];
226         ///
227         int numclients_;
228         ///
229         LyXComm pipes_;
230 };
231
232 /// Implementation is in LyX.cpp
233 Server & theServer();
234
235 /// Implementation is in LyX.cpp
236 extern std::vector<std::string> & theFilesToLoad();
237
238
239 } // namespace lyx
240
241 #endif // SERVER_H