1 /*-*- c++ -*-********************************************************
2 * wxexthlp.cpp - an external help controller for wxWindows *
4 * (C) 1998 by Karsten Ballüder (Ballueder@usa.net) *
7 *******************************************************************/
9 # pragma implementation "wxexthlp.h"
13 #include "wx/helpbase.h"
14 #include "wx/generic/helpext.h"
15 #include "wx/string.h"
25 class wxExtHelpMapEntry
: public wxObject
31 wxExtHelpMapEntry(int iid
, wxString
const &iurl
, wxString
const &idoc
)
32 { id
= iid
; url
= iurl
; doc
= idoc
; }
38 wxBusyCursor() { wxBeginBusyCursor(); }
39 ~wxBusyCursor() { wxEndBusyCursor(); }
42 IMPLEMENT_CLASS(wxExtHelpController
, wxHelpControllerBase
)
45 This class implements help via an external browser.
46 It requires the name of a directory containing the documentation
47 and a file mapping numerical Section numbers to relative URLS.
50 wxExtHelpController::wxExtHelpController(void)
53 m_BrowserName
= WXEXTHELP_DEFAULTBROWSER
;
54 m_BrowserIsNetscape
= WXEXTHELP_DEFAULTBROWSER_IS_NETSCAPE
;
57 char *browser
= getenv(WXEXTHELP_ENVVAR_BROWSER
);
60 m_BrowserName
= browser
;
61 browser
= getenv(WXEXTHELP_ENVVAR_BROWSERISNETSCAPE
);
62 m_BrowserIsNetscape
= browser
&& (atoi(browser
) != 0);
67 wxExtHelpController::DeleteList(void)
71 wxNode
*node
= m_MapList
->First();
74 delete (wxExtHelpMapEntry
*)node
->Data();
76 node
= m_MapList
->First();
83 wxExtHelpController::~wxExtHelpController(void)
89 wxExtHelpController::SetBrowser(wxString
const & browsername
, bool isNetscape
)
91 m_BrowserName
= browsername
;
92 m_BrowserIsNetscape
= isNetscape
;
95 /** This must be called to tell the controller where to find the
97 @param file - NOT a filename, but a directory name.
98 @return true on success
101 wxExtHelpController::Initialize(const wxString
& file
)
103 return LoadFile(file
);
108 wxExtHelpController::LoadFile(const wxString
& ifile
)
110 wxString mapFile
, file
, url
, doc
;
112 char buffer
[WXEXTHELP_BUFLEN
];
114 wxBusyCursor b
; // display a busy cursor
116 if(! ifile
.IsEmpty())
119 if(! wxIsAbsolutePath(file
))
121 char* f
= wxGetWorkingDirectory();
123 delete[] f
; // wxGetWorkingDirectory returns new memory
124 file
<< WXEXTHELP_SEPARATOR
<< ifile
;
129 if(! wxDirExists(file
))
132 mapFile
<< file
<< WXEXTHELP_SEPARATOR
<< WXEXTHELP_MAPFILE
;
134 else // try to reload old file
137 if(! wxFileExists(mapFile
))
141 m_MapList
= new wxList
;
144 FILE *input
= fopen(mapFile
.c_str(),"rt");
149 if(fgets(buffer
,WXEXTHELP_BUFLEN
,input
) && *buffer
!= WXEXTHELP_COMMENTCHAR
)
151 len
= strlen(buffer
);
152 if(buffer
[len
-1] == '\n')
153 buffer
[len
-1] = '\0'; // cut of trailing newline
154 if(sscanf(buffer
,"%d", &id
) != 1)
156 for(i
=0; isdigit(buffer
[i
])||isspace(buffer
[i
])||buffer
[i
]=='-'; i
++)
157 ; // find begin of URL
159 while(buffer
[i
] && ! isspace(buffer
[i
]) && buffer
[i
] !=
160 WXEXTHELP_COMMENTCHAR
)
162 while(buffer
[i
] && buffer
[i
] != WXEXTHELP_COMMENTCHAR
)
166 doc
= (buffer
+ i
+ 1); // skip the comment character
167 m_MapList
->Append(new wxExtHelpMapEntry(id
,url
,doc
));
170 }while(! feof(input
));
173 m_MapFile
= file
; // now it's valid
178 wxExtHelpController::CallBrowser(wxString
const &relativeURL
)
180 wxBusyCursor b
; // display a busy cursor
183 if(m_BrowserIsNetscape
) // try re-loading first
186 wxGetHomeDir(&lockfile
);
187 lockfile
<< WXEXTHELP_SEPARATOR
<< ".netscape/lock";
189 if(lstat(lockfile
.c_str(), &statbuf
) == 0)
190 // cannot use wxFileExists, because it's a link pointing to a
191 // non-existing location if(wxFileExists(lockfile))
194 command
<< m_BrowserName
<< " -remote openURL("
195 << "file://" << m_MapFile
196 << WXEXTHELP_SEPARATOR
<< relativeURL
<< ")";
197 success
= wxExecute(command
);
198 if(success
!= 0 ) // returns PID on success
202 command
= m_BrowserName
;
203 command
<< " file://"
204 << m_MapFile
<< WXEXTHELP_SEPARATOR
<< relativeURL
;
205 return wxExecute(command
) != 0;
209 wxExtHelpController::DisplayContents(void)
213 wxBusyCursor b
; // display a busy cursor
214 return KeywordSearch("");
218 wxExtHelpController::DisplaySection(int sectionNo
)
223 wxBusyCursor b
; // display a busy cursor
224 wxNode
*node
= m_MapList
->First();
225 wxExtHelpMapEntry
*entry
;
228 entry
= (wxExtHelpMapEntry
*)node
->Data();
229 if(entry
->id
== sectionNo
)
230 return CallBrowser(entry
->url
);
237 wxExtHelpController::DisplayBlock(long blockNo
)
239 return DisplaySection((int)blockNo
);
243 wxExtHelpController::KeywordSearch(const wxString
& k
)
248 wxBusyCursor b
; // display a busy cursor
249 wxString
*choices
= new wxString
[m_NumOfEntries
];
250 wxString
*urls
= new wxString
[m_NumOfEntries
];
251 wxString compA
, compB
;
255 bool showAll
= k
.IsEmpty();
256 wxNode
*node
= m_MapList
->First();
257 wxExtHelpMapEntry
*entry
;
259 compA
= k
; compA
.LowerCase(); // we compare case insensitive
262 entry
= (wxExtHelpMapEntry
*)node
->Data();
263 compB
= entry
->doc
; compB
.LowerCase();
264 if((showAll
|| compB
.Contains(k
)) && ! compB
.IsEmpty())
266 urls
[idx
] = entry
->url
;
268 // choices[idx] = (**i).doc.Contains((**i).doc.Before(WXEXTHELP_COMMENTCHAR));
269 //if(choices[idx].IsEmpty()) // didn't contain the ';'
270 // choices[idx] = (**i).doc;
272 for(j
=0;entry
->doc
.c_str()[j
]
273 && entry
->doc
.c_str()[j
] != WXEXTHELP_COMMENTCHAR
; j
++)
274 choices
[idx
] << entry
->doc
.c_str()[j
];
281 rc
= CallBrowser(urls
[0]);
284 wxMessageBox(_("No entries found."));
289 idx
= wxGetSingleChoiceIndex(showAll
? _("Help Index") : _("Relevant entries:"),
290 showAll
? _("Help Index") : _("Entries found"),
293 rc
= CallBrowser(urls
[idx
]);
305 wxExtHelpController::Quit(void)
311 wxExtHelpController::OnQuit(void)