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