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: remhelp.cpp 35650 2005-09-23 12:56:45Z MR $ 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 49rhhcClient::rhhcClient( bool *isconn_a ) 50{ 51 isconn_2 = isconn_a; 52} 53 54wxConnectionBase *rhhcClient::OnMakeConnection() 55{ 56 return new rhhcConnection( isconn_2 ); 57} 58 59rhhcConnection::rhhcConnection( bool *isconn_a ) 60: wxConnection() 61{ 62 isconn_3 = isconn_a; 63 *isconn_3 = true; 64} 65 66rhhcConnection::~rhhcConnection() 67{ 68 *isconn_3 = false; 69} 70 71bool rhhcConnection::OnAdvise(const wxString& topic, const wxString& item, char *data, int size, wxIPCFormat format) 72{ 73 return true; 74} 75 76bool rhhcConnection::OnDisconnect() 77{ 78 *isconn_3 = false; 79 80 return wxConnection::OnDisconnect(); 81} 82 83////////////////////////////////////////// 84///////////////////////////////////////// 85 86// wxRemoteHtmlHelpController class 87 88IMPLEMENT_CLASS(wxRemoteHtmlHelpController, wxHelpControllerBase) 89 90wxRemoteHtmlHelpController::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 126void wxRemoteHtmlHelpController::SetService(wxString& a_service) 127{ 128 m_service = a_service; 129} 130void wxRemoteHtmlHelpController::SetServer(wxString& a_appname) 131{ 132 m_appname = a_appname; 133} 134 135void wxRemoteHtmlHelpController::OnQuit() 136{ 137 //kill the Server here? 138 //this function is not called ? 139} 140 141wxRemoteHtmlHelpController::~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 162bool 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 230bool wxRemoteHtmlHelpController::LoadFile(const wxString& WXUNUSED(file)) 231{ 232 return true; 233} 234bool wxRemoteHtmlHelpController::DisplaySection(int sectionNo) 235{ 236 Display(sectionNo); 237 return true; 238} 239bool wxRemoteHtmlHelpController::DisplayBlock(long blockNo) 240{ 241 return DisplaySection((int)blockNo); 242} 243 244bool 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 319void 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 330void 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 344bool 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 359bool 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} 369void wxRemoteHtmlHelpController::DisplayIndex() 370{ 371 if( isconn_1 ) { 372 if (!m_connection->Poke( wxT("--DisplayIndex"), wxT("") ) ) 373 wxLogError(wxT("wxRemoteHtmlHelpController - DisplayIndex Failed")); 374 } 375} 376bool 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 387void 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 398void 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 406