The rounded corners look really dumb at this size.
[wxWidgets.git] / utils / helpview / src / remhelp.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: remhelp.cpp
3 // Purpose: Remote help controller class
4 // Author: Eric Dowty
5 // Modified by:
6 // Created: 2002-11-18
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21
22 #include <math.h>
23
24 #include "wx/process.h"
25 #include "wx/confbase.h"
26
27 // Settings common to both executables: determines whether
28 // we're using TCP/IP or real DDE.
29
30 //#include "ddesetup.h"
31 //#define wxUSE_DDE_FOR_IPC 0
32
33 #ifndef wxHAS_IMAGES_IN_RESOURCES
34 #include "mondrian.xpm"
35 #endif
36
37 #include "remhelp.h"
38 #include "client.h"
39
40 #if !defined(USE_REMOTE)
41 #include <wx/html/helpctrl.h>
42 #endif
43
44 //////////////////
45 //////////////////
46 // helper classes
47
48 rhhcClient::rhhcClient( bool *isconn_a )
49 {
50 isconn_2 = isconn_a;
51 }
52
53 wxConnectionBase *rhhcClient::OnMakeConnection()
54 {
55 return new rhhcConnection( isconn_2 );
56 }
57
58 rhhcConnection::rhhcConnection( bool *isconn_a )
59 : wxConnection()
60 {
61 isconn_3 = isconn_a;
62 *isconn_3 = true;
63 }
64
65 rhhcConnection::~rhhcConnection()
66 {
67 *isconn_3 = false;
68 }
69
70 bool rhhcConnection::OnAdvise(const wxString& topic, const wxString& item, char *data, int size, wxIPCFormat format)
71 {
72 return true;
73 }
74
75 bool rhhcConnection::OnDisconnect()
76 {
77 *isconn_3 = false;
78
79 return wxConnection::OnDisconnect();
80 }
81
82 //////////////////////////////////////////
83 /////////////////////////////////////////
84
85 // wxRemoteHtmlHelpController class
86
87 IMPLEMENT_CLASS(wxRemoteHtmlHelpController, wxHelpControllerBase)
88
89 wxRemoteHtmlHelpController::wxRemoteHtmlHelpController(int style )
90 {
91 m_style = style;
92 m_connection = NULL;
93 m_client = NULL;
94 m_pid = 0;
95 isconn_1 = false;
96 m_process = NULL;
97
98 // defaults
99 //
100 // server app is assumed to be local
101 //
102 // for MSW (DDE classes), a_service is 'service name', apparently an arbitrary string
103 // for Unix, should be a valid file name (for a nonexistent file)
104 // for nonMSW, nonUnix, must be port number, for example "4242" (TCP/IP based classes)
105 // should be unique to the client app
106
107 wxString thename = wxGetApp().GetAppName();
108 #if defined(__WXMSW__)
109 m_appname = wxT("helpview.exe");
110 m_service = thename + wxString(wxT("_helpservice"));
111 #elif defined(__UNIX__)
112 m_appname = wxT("./helpview");
113 m_service = wxT("/tmp/") + thename + wxString(wxT("_helpservice"));
114 #else
115 m_appname = wxT("./helpview");
116 m_service = wxT("4242");
117 #endif
118
119 m_book = thename + wxT(".hhp"); // or .htb or .zip
120 m_windowname = thename + wxT(" Help: %s");
121 //underscores for spaces
122 m_windowname.Replace( wxT(" "), wxT("_") );
123 }
124
125 void wxRemoteHtmlHelpController::SetService(wxString& a_service)
126 {
127 m_service = a_service;
128 }
129 void wxRemoteHtmlHelpController::SetServer(wxString& a_appname)
130 {
131 m_appname = a_appname;
132 }
133
134 void wxRemoteHtmlHelpController::OnQuit()
135 {
136 //kill the Server here?
137 //this function is not called ?
138 }
139
140 wxRemoteHtmlHelpController::~wxRemoteHtmlHelpController()
141 {
142 if ( isconn_1 )
143 {
144 // if (!m_connection->Poke( wxT("--YouAreDead"), wxT("") ) )
145 // wxLogError(wxT("wxRemoteHtmlHelpController - YouAreDead Failed"));
146
147 // Kill the server. This could be an option.
148 Quit();
149
150 m_connection->Disconnect();
151 delete m_connection;
152
153 delete m_process;
154 m_process = NULL;
155 }
156 if( m_client )
157 delete m_client; //should be automatic?
158
159 }
160
161 bool wxRemoteHtmlHelpController::DoConnection()
162 {
163 wxString cmd, blank;
164 int nsleep;
165
166 blank = wxT(" ");
167
168 // ignored under DDE, host name in TCP/IP based classes
169 wxString hostName = wxT("localhost");
170
171 // Create a new client
172 if( !m_client ) m_client = new rhhcClient(&isconn_1);
173
174 nsleep = 0;
175
176 // suppress the log messages from MakeConnection()
177 {
178 wxLogNull nolog;
179
180 //first try to connect assuming server is running
181 if( !isconn_1 )
182 m_connection = (rhhcConnection *)m_client->MakeConnection(hostName, m_service, wxT("HELP") );
183
184 //if not, start server
185 if( !isconn_1 ) {
186
187 wxString stylestr;
188 stylestr.Printf( wxT("--Style%d"), m_style );
189
190 cmd = m_appname + blank + m_service + blank + m_windowname + blank + m_book + blank + stylestr;
191
192 m_process = new wxProcess(NULL);
193 m_pid = wxExecute( cmd, false, m_process );
194 // leaks - wxExecute itself (if not deleted) and in wxExecute at
195 // wxExecuteData *data = new wxExecuteData;
196 if( m_pid <= 0 ) {
197 wxLogError( wxT("wxRemoteHtmlHelpController - Failed to start Help server") );
198 return false;
199 }
200 }
201
202 while ( !isconn_1 )
203 {
204 //try every second for a while, then leave it to user
205 wxSleep(1);
206 if( nsleep > 4 ) {
207 if ( wxMessageBox( wxT("Failed to make connection to Help server.\nRetry?") ,
208 wxT("wxRemoteHtmlHelpController Error"),
209 wxICON_ERROR | wxYES_NO | wxCANCEL ) != wxYES )
210 {
211 // no server
212 return false;
213 }
214 }
215 nsleep++;
216
217 m_connection = (rhhcConnection *)m_client->MakeConnection(hostName, m_service, wxT("HELP") );
218 }
219 }
220
221 if (!m_connection->StartAdvise(wxT("Item"))) {
222 wxLogError(wxT("wxRemoteHtmlHelpController - StartAdvise failed") );
223 return false;
224 }
225
226 return true;
227 }
228
229 bool wxRemoteHtmlHelpController::LoadFile(const wxString& WXUNUSED(file))
230 {
231 return true;
232 }
233 bool wxRemoteHtmlHelpController::DisplaySection(int sectionNo)
234 {
235 Display(sectionNo);
236 return true;
237 }
238 bool wxRemoteHtmlHelpController::DisplayBlock(long blockNo)
239 {
240 return DisplaySection((int)blockNo);
241 }
242
243 bool wxRemoteHtmlHelpController::Quit()
244 {
245 //this code from exec sample - branches left in for testing
246 // sig = 3, 6, 9 or 12 all kill server with no apparent problem
247 // but give error message on MSW - timout?
248 int sig = 15; //3 = quit; 6 = abort; 9 = kill; 15 = terminate
249
250 /*
251 switch ( sig )
252 {
253 default:
254 wxFAIL_MSG( wxT("unexpected return value") );
255 // fall through
256
257 case -1:
258 // cancelled
259 return false;
260
261 case wxSIGNONE:
262 case wxSIGHUP:
263 case wxSIGINT:
264 case wxSIGQUIT:
265 case wxSIGILL:
266 case wxSIGTRAP:
267 case wxSIGABRT:
268 case wxSIGEMT:
269 case wxSIGFPE:
270 case wxSIGKILL:
271 case wxSIGBUS:
272 case wxSIGSEGV:
273 case wxSIGSYS:
274 case wxSIGPIPE:
275 case wxSIGALRM:
276 case wxSIGTERM:
277 break;
278 }
279 */
280
281 if ( sig == 0 )
282 {
283 if ( wxProcess::Exists(m_pid) )
284 {
285 wxLogStatus(wxT("Process %ld is running."), m_pid);
286 }
287 else
288 {
289 wxLogStatus(wxT("No process with pid = %ld."), m_pid);
290 }
291 }
292 else // not SIGNONE
293 {
294 wxKillError rc = wxProcess::Kill(m_pid, (wxSignal)sig);
295 if ( rc == wxKILL_OK )
296 {
297 wxLogStatus(wxT("Process %ld killed with signal %d."), m_pid, sig);
298 }
299 else
300 {
301 static const wxChar *errorText[] =
302 {
303 wxT(""), // no error
304 wxT("signal not supported"),
305 wxT("permission denied"),
306 wxT("no such process"),
307 wxT("unspecified error"),
308 };
309
310 // sig = 3, 6, 9 or 12 all kill server with no apparent problem
311 // but give error message on MSW - timout?
312 //
313 //wxLogError(wxT("Failed to kill process %ld with signal %d: %s"),
314 // m_pid, sig, errorText[rc]);
315 }
316 }
317
318
319 return true;
320 }
321
322 void wxRemoteHtmlHelpController::Display(const wxString& helpfile)
323 {
324 if( !isconn_1 ) {
325 if( !DoConnection() ) return;
326 }
327
328 if (!m_connection->Execute( helpfile, -1 ) )
329 wxLogError(wxT("wxRemoteHtmlHelpController - Display Failed"));
330
331 }
332
333 void wxRemoteHtmlHelpController::Display(const int id)
334 {
335 if( !isconn_1 ) {
336 if( !DoConnection() ) return;
337 }
338
339 wxString intstring;
340 intstring.Printf( "--intstring%d", id );
341
342 if (!m_connection->Execute( intstring, -1 ) )
343 wxLogError(wxT("wxRemoteHtmlHelpController - Display Failed"));
344
345 }
346
347 bool wxRemoteHtmlHelpController::AddBook(const wxString& book, bool show_wait_msg)
348 {
349 //ignore show_wait_msg - there shouldn't be a delay in this step
350 //show_wait_msg = true could be transmitted with ++AddBook
351 m_book = book;
352
353 if( isconn_1 ) {
354 if (!m_connection->Poke( wxT("--AddBook"), (char*)book.c_str() ) )
355 {
356 wxLogError(wxT("wxRemoteHtmlHelpController - AddBook Failed"));
357 }
358 return false;
359 }
360
361 return true;
362 }
363
364 bool wxRemoteHtmlHelpController::DisplayContents()
365 {
366 if( isconn_1 ) {
367 if (!m_connection->Poke( wxT("--DisplayContents"), wxT("") ) ) {
368 wxLogError(wxT("wxRemoteHtmlHelpController - DisplayContents Failed"));
369 return false;
370 }
371 }
372 return true;
373 }
374 void wxRemoteHtmlHelpController::DisplayIndex()
375 {
376 if( isconn_1 ) {
377 if (!m_connection->Poke( wxT("--DisplayIndex"), wxT("") ) )
378 {
379 wxLogError(wxT("wxRemoteHtmlHelpController - DisplayIndex Failed"));
380 }
381 }
382 }
383 bool wxRemoteHtmlHelpController::KeywordSearch(const wxString& keyword)
384 {
385 if( isconn_1 ) {
386 if (!m_connection->Poke( wxT("--KeywordSearch"), (char*)keyword.c_str() ) ) {
387 wxLogError(wxT("wxRemoteHtmlHelpController - KeywordSearch Failed"));
388 return false;
389 }
390 }
391 return true;
392 }
393
394 void wxRemoteHtmlHelpController::SetTitleFormat(const wxString& format)
395 {
396 m_windowname = format;
397 m_windowname.Replace( wxT(" "), wxT("_") );
398
399 if( isconn_1 ) {
400 if (!m_connection->Poke( wxT("--SetTitleFormat"), (char*)format.c_str() ) )
401 {
402 wxLogError(wxT("wxRemoteHtmlHelpController - SetTitleFormat Failed"));
403 }
404 }
405 }
406
407 void wxRemoteHtmlHelpController::SetTempDir(const wxString& path)
408 {
409 if( isconn_1 ) {
410 if (!m_connection->Poke( wxT("--SetTempDir"), (char*)path.c_str() ) )
411 {
412 wxLogError(wxT("wxRemoteHtmlHelpController - SetTempDir Failed"));
413 }
414 }
415 }
416