Added wxExtHelpController: wxHelpController implementation for external
viewers. Made it the default viewer for wxGTK and set wxUSE_HELP=1. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@981 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
813
src/generic/helpext.cpp
Normal file
813
src/generic/helpext.cpp
Normal file
@@ -0,0 +1,813 @@
|
||||
/*-*- c++ -*-********************************************************
|
||||
* wxexthlp.cpp - an external help controller for wxWindows *
|
||||
* *
|
||||
* (C) 1998 by Karsten Ball<6C>der (Ballueder@usa.net) *
|
||||
* *
|
||||
* $Id$
|
||||
*******************************************************************/
|
||||
#ifdef __GNUG__
|
||||
# pragma implementation "wxexthlp.h"
|
||||
#endif
|
||||
|
||||
#include "wx/setup.h"
|
||||
#include "wx/helpbase.h"
|
||||
#include "wx/generic/helpext.h"
|
||||
#include "wx/string.h"
|
||||
#include "wx/utils.h"
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define WXEXTHELP_INCLUDE_KBLIST
|
||||
/**
|
||||
** This class uses kbList, a simple linked list. Until someone
|
||||
** rewrites it to use wxList instead, I include the relevant bits and
|
||||
** pieces of kbList here. It's a tiny class anyway, so it won't make
|
||||
** a big difference. The comments probably take up more space than
|
||||
** its code.
|
||||
**/
|
||||
|
||||
#ifdef WXEXTHELP_INCLUDE_KBLIST
|
||||
|
||||
/********************* kbList.h, verbose copy: ****************************/
|
||||
/**@name Double linked list implementation. */
|
||||
//@{
|
||||
|
||||
/** kbListNode is a class used by kbList. It represents a single
|
||||
element in the list. It is not intended for general use outside
|
||||
kbList functions.
|
||||
*/
|
||||
struct kbListNode
|
||||
{
|
||||
/// pointer to next node or NULL
|
||||
struct kbListNode *next;
|
||||
/// pointer to previous node or NULL
|
||||
struct kbListNode *prev;
|
||||
/// pointer to the actual data
|
||||
void *element;
|
||||
/** Constructor - it automatically links the node into the list, if
|
||||
the iprev, inext parameters are given.
|
||||
@param ielement pointer to the data for this node (i.e. the data itself)
|
||||
@param iprev if not NULL, use this as previous element in list
|
||||
@param inext if not NULL, use this as next element in list
|
||||
*/
|
||||
kbListNode( void *ielement,
|
||||
kbListNode *iprev = NULL,
|
||||
kbListNode *inext = NULL);
|
||||
/// Destructor.
|
||||
~kbListNode();
|
||||
};
|
||||
|
||||
/** The main list class, handling void pointers as data.
|
||||
*/
|
||||
|
||||
class kbList
|
||||
{
|
||||
public:
|
||||
/// An iterator class for kbList, just like for the STL classes.
|
||||
class iterator
|
||||
{
|
||||
protected:
|
||||
/// the node to which this iterator points
|
||||
kbListNode *node;
|
||||
friend class kbList;
|
||||
public:
|
||||
/** Constructor.
|
||||
@param n if not NULL, the node to which to point
|
||||
*/
|
||||
iterator(kbListNode *n = NULL);
|
||||
/** Dereference operator.
|
||||
@return the data pointer of the node belonging to this
|
||||
iterator
|
||||
*/
|
||||
void * operator*();
|
||||
|
||||
/** This operator allows us to write if(i). It is <em>not</em> a
|
||||
dereference operator and the result is always useless apart
|
||||
from its logical value!
|
||||
*/
|
||||
operator void*() const { return node == NULL ? (void*)0 : (void*)(-1); }
|
||||
|
||||
/** Increment operator - prefix, goes to next node in list.
|
||||
@return itself
|
||||
*/
|
||||
iterator & operator++();
|
||||
|
||||
/** Decrement operator - prefix, goes to previous node in list.
|
||||
@return itself
|
||||
*/
|
||||
iterator & operator--();
|
||||
|
||||
/** Increment operator - prefix, goes to next node in list.
|
||||
@return itself
|
||||
*/
|
||||
iterator & operator++(int); //postfix
|
||||
|
||||
/** Decrement operator - prefix, goes to previous node in list.
|
||||
@return itself
|
||||
*/
|
||||
iterator & operator--(int); //postfix
|
||||
|
||||
/** Comparison operator.
|
||||
@return true if not equal.
|
||||
*/
|
||||
bool operator !=(iterator const &) const;
|
||||
|
||||
/* Comparison operator.
|
||||
@return true if equal
|
||||
*/
|
||||
bool operator ==(iterator const &) const;
|
||||
|
||||
/** Returns a pointer to the node associated with this iterator.
|
||||
This function is not for general use and should be
|
||||
protected. However, if protected, it cannot be called from
|
||||
derived classes' iterators. (Is this a bug in gcc/egcs?)
|
||||
@return the node pointer
|
||||
*/
|
||||
inline kbListNode * Node(void) const
|
||||
{ return node; }
|
||||
};
|
||||
|
||||
/** Constructor.
|
||||
@param ownsEntriesFlag if true, the list owns the entries and
|
||||
will issue a delete on each of them when deleting them. If
|
||||
false, the entries themselves will not get deleted. Do not use
|
||||
this with array types!
|
||||
*/
|
||||
kbList(bool ownsEntriesFlag = true);
|
||||
|
||||
/** Destructor.
|
||||
If entries are owned, they will all get deleted from here.
|
||||
*/
|
||||
~kbList();
|
||||
|
||||
/** Tell list whether it owns objects. If owned, they can be
|
||||
deleted by list. See the constructor for more details.
|
||||
@param ownsflag if true, list will own entries
|
||||
*/
|
||||
void ownsObjects(bool ownsflag = true)
|
||||
{ ownsEntries = ownsflag; }
|
||||
|
||||
/** Query whether list owns entries.
|
||||
@return true if list owns entries
|
||||
*/
|
||||
bool ownsObjects(void)
|
||||
{ return ownsEntries; }
|
||||
|
||||
/** Add an entry at the end of the list.
|
||||
@param element pointer to data
|
||||
*/
|
||||
void push_back(void *element);
|
||||
|
||||
/** Add an entry at the head of the list.
|
||||
@param element pointer to data
|
||||
*/
|
||||
void push_front(void *element);
|
||||
|
||||
/** Get element from end of the list and delete it.
|
||||
NOTE: In this case the element's data will not get deleted by
|
||||
the list. It is the responsibility of the caller to free it.
|
||||
@return the element data
|
||||
*/
|
||||
void *pop_back(void);
|
||||
|
||||
/** Get element from head of the list and delete it.
|
||||
NOTE: In this case the element's data will not get deleted by
|
||||
the list. It is the responsibility of the caller to free it.
|
||||
@return the element data
|
||||
*/
|
||||
void *pop_front(void);
|
||||
|
||||
/** Insert an element into the list.
|
||||
@param i an iterator pointing to the element, before which the new one should be inserted
|
||||
@param element the element data
|
||||
*/
|
||||
void insert(iterator & i, void *element);
|
||||
|
||||
/** Remove an element from the list _without_ deleting the object.
|
||||
@param i iterator pointing to the element to be deleted
|
||||
@return the value of the element just removed
|
||||
*/
|
||||
void *remove(iterator& i) { void *p = *i; doErase(i); return p; }
|
||||
|
||||
/** Erase an element, move iterator to following element.
|
||||
@param i iterator pointing to the element to be deleted
|
||||
*/
|
||||
void erase(iterator & i) { deleteContent(i); doErase(i); }
|
||||
|
||||
/* Get head of list.
|
||||
@return iterator pointing to head of list
|
||||
*/
|
||||
iterator begin(void) const;
|
||||
|
||||
/* Get end of list.
|
||||
@return iterator pointing after the end of the list. This is an
|
||||
invalid iterator which cannot be dereferenced or decremented. It is
|
||||
only of use in comparisons. NOTE: this is different from STL!
|
||||
@see tail
|
||||
*/
|
||||
iterator end(void) const;
|
||||
|
||||
/* Get last element in list.
|
||||
@return iterator pointing to the last element in the list.
|
||||
@see end
|
||||
*/
|
||||
iterator tail(void) const;
|
||||
|
||||
/* Get the number of elements in the list.
|
||||
@return number of elements in the list
|
||||
*/
|
||||
unsigned size(void) const;
|
||||
|
||||
/* Query whether list is empty.
|
||||
@return true if list is empty
|
||||
*/
|
||||
inline bool empty(void) const
|
||||
{ return first == NULL ; }
|
||||
|
||||
protected:
|
||||
/// if true, list owns entries
|
||||
bool ownsEntries;
|
||||
/// pointer to first element in list
|
||||
kbListNode *first;
|
||||
/// pointer to last element in list
|
||||
kbListNode *last;
|
||||
protected:
|
||||
/** Erase an element, move iterator to following element.
|
||||
@param i iterator pointing to the element to be deleted
|
||||
*/
|
||||
void doErase(iterator & i);
|
||||
|
||||
/** Deletes the actual content if ownsflag is set.
|
||||
param iterator i
|
||||
*/
|
||||
inline void deleteContent(iterator i)
|
||||
{ if(ownsEntries) delete *i; }
|
||||
|
||||
|
||||
private:
|
||||
/// forbid copy construction
|
||||
kbList(kbList const &foo);
|
||||
/// forbid assignments
|
||||
kbList& operator=(const kbList& foo);
|
||||
};
|
||||
|
||||
/** Macro to define a kbList with a given name, having elements of
|
||||
pointer to the given type. I.e. KBLIST_DEFINE(Int,int) would
|
||||
create a kbListInt type holding int pointers.
|
||||
*/
|
||||
#define KBLIST_DEFINE(name,type) \
|
||||
class name : public kbList \
|
||||
{ \
|
||||
public: \
|
||||
class iterator : public kbList::iterator \
|
||||
{ \
|
||||
protected: \
|
||||
inline iterator(kbList::iterator const & i) \
|
||||
{ node = i.Node(); } \
|
||||
friend class name; \
|
||||
public: \
|
||||
inline iterator(kbListNode *n = NULL) \
|
||||
: kbList::iterator(n) {} \
|
||||
inline type * operator*() \
|
||||
/* the cast is needed for MS VC++ 5.0 */ \
|
||||
{ return (type *)((kbList::iterator *)this)->operator*() ; } \
|
||||
}; \
|
||||
inline name(bool ownsEntriesFlag = TRUE) \
|
||||
: kbList(ownsEntriesFlag) {} \
|
||||
\
|
||||
inline type *pop_back(void) \
|
||||
{ return (type *) kbList::pop_back(); } \
|
||||
\
|
||||
inline type *pop_front(void) \
|
||||
{ return (type *) kbList::pop_front(); } \
|
||||
\
|
||||
type *remove(iterator& i) \
|
||||
{ return (type *)kbList::remove(i); } \
|
||||
inline void erase(iterator & i) \
|
||||
{ deleteContent(i); kbList::erase(i); } \
|
||||
\
|
||||
inline iterator begin(void) const \
|
||||
{ return kbList::begin(); } \
|
||||
\
|
||||
inline iterator end(void) const \
|
||||
{ return kbList::end(); } \
|
||||
\
|
||||
inline iterator tail(void) const \
|
||||
{ return kbList::tail(); } \
|
||||
~name() \
|
||||
{ \
|
||||
kbListNode *next; \
|
||||
while ( first != NULL ) \
|
||||
{ \
|
||||
next = first->next; \
|
||||
if(ownsEntries) \
|
||||
delete (type *)first->element; \
|
||||
delete first; \
|
||||
first = next; \
|
||||
} \
|
||||
} \
|
||||
protected: \
|
||||
inline void deleteContent(iterator i) \
|
||||
{ if(ownsEntries) delete *i; } \
|
||||
}
|
||||
|
||||
|
||||
/************************* copy of kbList.cpp: ****************************/
|
||||
kbListNode::kbListNode( void *ielement,
|
||||
kbListNode *iprev,
|
||||
kbListNode *inext)
|
||||
{
|
||||
next = inext;
|
||||
prev = iprev;
|
||||
if(prev)
|
||||
prev->next = this;
|
||||
if(next)
|
||||
next->prev = this;
|
||||
element = ielement;
|
||||
}
|
||||
|
||||
kbListNode::~kbListNode()
|
||||
{
|
||||
if(prev)
|
||||
prev->next = next;
|
||||
if(next)
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
|
||||
kbList::iterator::iterator(kbListNode *n)
|
||||
{
|
||||
node = n;
|
||||
}
|
||||
|
||||
void *
|
||||
kbList::iterator::operator*()
|
||||
{
|
||||
return node->element;
|
||||
}
|
||||
|
||||
kbList::iterator &
|
||||
kbList::iterator::operator++()
|
||||
{
|
||||
node = node ? node->next : NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
kbList::iterator &
|
||||
kbList::iterator::operator--()
|
||||
{
|
||||
node = node ? node->prev : NULL;
|
||||
return *this;
|
||||
}
|
||||
kbList::iterator &
|
||||
kbList::iterator::operator++(int /* foo */)
|
||||
{
|
||||
return operator++();
|
||||
}
|
||||
|
||||
kbList::iterator &
|
||||
kbList::iterator::operator--(int /* bar */)
|
||||
{
|
||||
return operator--();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
kbList::iterator::operator !=(kbList::iterator const & i) const
|
||||
{
|
||||
return node != i.node;
|
||||
}
|
||||
|
||||
bool
|
||||
kbList::iterator::operator ==(kbList::iterator const & i) const
|
||||
{
|
||||
return node == i.node;
|
||||
}
|
||||
|
||||
kbList::kbList(bool ownsEntriesFlag)
|
||||
{
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
ownsEntries = ownsEntriesFlag;
|
||||
}
|
||||
|
||||
void
|
||||
kbList::push_back(void *element)
|
||||
{
|
||||
if(! first) // special case of empty list
|
||||
{
|
||||
first = new kbListNode(element);
|
||||
last = first;
|
||||
return;
|
||||
}
|
||||
else
|
||||
last = new kbListNode(element, last);
|
||||
}
|
||||
|
||||
void
|
||||
kbList::push_front(void *element)
|
||||
{
|
||||
if(! first) // special case of empty list
|
||||
{
|
||||
push_back(element);
|
||||
return;
|
||||
}
|
||||
else
|
||||
first = new kbListNode(element, NULL, first);
|
||||
}
|
||||
|
||||
void *
|
||||
kbList::pop_back(void)
|
||||
{
|
||||
iterator i;
|
||||
void *data;
|
||||
bool ownsFlagBak = ownsEntries;
|
||||
i = tail();
|
||||
data = *i;
|
||||
ownsEntries = false;
|
||||
erase(i);
|
||||
ownsEntries = ownsFlagBak;
|
||||
return data;
|
||||
}
|
||||
|
||||
void *
|
||||
kbList::pop_front(void)
|
||||
{
|
||||
iterator i;
|
||||
void *data;
|
||||
bool ownsFlagBak = ownsEntries;
|
||||
|
||||
i = begin();
|
||||
data = *i;
|
||||
ownsEntries = false;
|
||||
erase(i);
|
||||
ownsEntries = ownsFlagBak;
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
kbList::insert(kbList::iterator & i, void *element)
|
||||
{
|
||||
if(! i.Node())
|
||||
return;
|
||||
else if(i.Node() == first)
|
||||
{
|
||||
push_front(element);
|
||||
i = first;
|
||||
return;
|
||||
}
|
||||
i = kbList::iterator(new kbListNode(element, i.Node()->prev, i.Node()));
|
||||
}
|
||||
|
||||
void
|
||||
kbList::doErase(kbList::iterator & i)
|
||||
{
|
||||
kbListNode
|
||||
*node = i.Node(),
|
||||
*prev, *next;
|
||||
|
||||
if(! node) // illegal iterator
|
||||
return;
|
||||
|
||||
prev = node->prev;
|
||||
next = node->next;
|
||||
|
||||
// correct first/last:
|
||||
if(node == first)
|
||||
first = node->next;
|
||||
if(node == last) // don't put else here!
|
||||
last = node->prev;
|
||||
|
||||
// build new links:
|
||||
if(prev)
|
||||
prev->next = next;
|
||||
if(next)
|
||||
next->prev = prev;
|
||||
|
||||
// delete this node and contents:
|
||||
// now done separately
|
||||
//if(ownsEntries)
|
||||
//delete *i;
|
||||
delete i.Node();
|
||||
|
||||
// change the iterator to next element:
|
||||
i = kbList::iterator(next);
|
||||
}
|
||||
|
||||
kbList::~kbList()
|
||||
{
|
||||
kbListNode *next;
|
||||
|
||||
while ( first != NULL )
|
||||
{
|
||||
next = first->next;
|
||||
if(ownsEntries)
|
||||
delete first->element;
|
||||
delete first;
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
|
||||
kbList::iterator
|
||||
kbList::begin(void) const
|
||||
{
|
||||
return kbList::iterator(first);
|
||||
}
|
||||
|
||||
kbList::iterator
|
||||
kbList::tail(void) const
|
||||
{
|
||||
return kbList::iterator(last);
|
||||
}
|
||||
|
||||
kbList::iterator
|
||||
kbList::end(void) const
|
||||
{
|
||||
return kbList::iterator(NULL); // the one after the last
|
||||
}
|
||||
|
||||
unsigned
|
||||
kbList::size(void) const // inefficient
|
||||
{
|
||||
unsigned count = 0;
|
||||
kbList::iterator i;
|
||||
for(i = begin(); i != end(); i++, count++)
|
||||
;
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
||||
/************************* end of kbList code *****************************/
|
||||
|
||||
struct wxExtHelpMapEntry
|
||||
{
|
||||
int id;
|
||||
wxString url;
|
||||
wxString doc;
|
||||
wxExtHelpMapEntry(int iid, wxString const &iurl, wxString const &idoc)
|
||||
{ id = iid; url = iurl; doc = idoc; }
|
||||
};
|
||||
KBLIST_DEFINE(wxExtHelpMapList, wxExtHelpMapEntry);
|
||||
|
||||
|
||||
struct wxBusyCursor
|
||||
{
|
||||
wxBusyCursor() { wxBeginBusyCursor(); }
|
||||
~wxBusyCursor() { wxEndBusyCursor(); }
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(wxExtHelpController, wxHelpControllerBase)
|
||||
|
||||
/**
|
||||
This class implements help via an external browser.
|
||||
It requires the name of a directory containing the documentation
|
||||
and a file mapping numerical Section numbers to relative URLS.
|
||||
*/
|
||||
|
||||
wxExtHelpController::wxExtHelpController(void)
|
||||
{
|
||||
m_MapList = NULL;
|
||||
m_BrowserName = WXEXTHELP_DEFAULTBROWSER;
|
||||
m_BrowserIsNetscape = WXEXTHELP_DEFAULTBROWSER_IS_NETSCAPE;
|
||||
|
||||
char *browser = getenv(WXEXTHELP_ENVVAR_BROWSER);
|
||||
if(browser)
|
||||
{
|
||||
m_BrowserName = browser;
|
||||
browser = getenv(WXEXTHELP_ENVVAR_BROWSERISNETSCAPE);
|
||||
m_BrowserIsNetscape = browser && (atoi(browser) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
wxExtHelpController::~wxExtHelpController(void)
|
||||
{
|
||||
if(m_MapList) delete m_MapList;
|
||||
}
|
||||
|
||||
void
|
||||
wxExtHelpController::SetBrowser(wxString const & browsername, bool isNetscape)
|
||||
{
|
||||
m_BrowserName = browsername;
|
||||
m_BrowserIsNetscape = isNetscape;
|
||||
}
|
||||
|
||||
/** This must be called to tell the controller where to find the
|
||||
documentation.
|
||||
@param file - NOT a filename, but a directory name.
|
||||
@return true on success
|
||||
*/
|
||||
bool
|
||||
wxExtHelpController::Initialize(const wxString& file)
|
||||
{
|
||||
return LoadFile(file);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
wxExtHelpController::LoadFile(const wxString& ifile = "")
|
||||
{
|
||||
wxString mapFile, file, url, doc;
|
||||
int id,i,len;
|
||||
char buffer[WXEXTHELP_BUFLEN];
|
||||
|
||||
wxBusyCursor b; // display a busy cursor
|
||||
|
||||
if(! ifile.IsEmpty())
|
||||
{
|
||||
file = ifile;
|
||||
if(! wxIsAbsolutePath(file))
|
||||
{
|
||||
file = wxGetWorkingDirectory();
|
||||
file << WXEXTHELP_SEPARATOR << ifile;
|
||||
}
|
||||
else
|
||||
file = ifile;
|
||||
|
||||
if(! wxDirExists(file))
|
||||
return false;
|
||||
|
||||
mapFile << file << WXEXTHELP_SEPARATOR << WXEXTHELP_MAPFILE;
|
||||
}
|
||||
else // try to reload old file
|
||||
mapFile = m_MapFile;
|
||||
|
||||
if(! wxFileExists(mapFile))
|
||||
return false;
|
||||
|
||||
if(m_MapList) delete m_MapList;
|
||||
m_MapList = new wxExtHelpMapList;
|
||||
m_NumOfEntries = 0;
|
||||
|
||||
FILE *input = fopen(mapFile.c_str(),"rt");
|
||||
if(! input)
|
||||
return false;
|
||||
do
|
||||
{
|
||||
if(fgets(buffer,WXEXTHELP_BUFLEN,input) && *buffer != WXEXTHELP_COMMENTCHAR)
|
||||
{
|
||||
len = strlen(buffer);
|
||||
if(buffer[len-1] == '\n')
|
||||
buffer[len-1] = '\0'; // cut of trailing newline
|
||||
if(sscanf(buffer,"%d", &id) != 1)
|
||||
break; // error
|
||||
for(i=0; isdigit(buffer[i])||isspace(buffer[i]); i++)
|
||||
; // find begin of URL
|
||||
url = "";
|
||||
while(buffer[i] && ! isspace(buffer[i]) && buffer[i] !=
|
||||
WXEXTHELP_COMMENTCHAR)
|
||||
url << buffer[i++];
|
||||
while(buffer[i] && buffer[i] != WXEXTHELP_COMMENTCHAR)
|
||||
i++;
|
||||
doc = "";
|
||||
if(buffer[i])
|
||||
doc = (buffer + i + 1); // skip the comment character
|
||||
m_MapList->push_back(new wxExtHelpMapEntry(id,url,doc));
|
||||
m_NumOfEntries++;
|
||||
}
|
||||
else
|
||||
perror("");
|
||||
}while(! feof(input));
|
||||
fclose(input);
|
||||
|
||||
m_MapFile = file; // now it's valid
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
wxExtHelpController::CallBrowser(wxString const &relativeURL)
|
||||
{
|
||||
wxBusyCursor b; // display a busy cursor
|
||||
wxString command;
|
||||
|
||||
if(m_BrowserIsNetscape) // try re-loading first
|
||||
{
|
||||
wxString lockfile;
|
||||
wxGetHomeDir(&lockfile);
|
||||
lockfile << WXEXTHELP_SEPARATOR << ".netscape/lock";
|
||||
struct stat statbuf;
|
||||
if(lstat(lockfile.c_str(), &statbuf) == 0)
|
||||
// cannot use wxFileExists, because it's a link pointing to a
|
||||
// non-existing location if(wxFileExists(lockfile))
|
||||
{
|
||||
long success;
|
||||
command << m_BrowserName << " -remote openURL("
|
||||
<< "file://" << m_MapFile
|
||||
<< WXEXTHELP_SEPARATOR << relativeURL << ")";
|
||||
success = wxExecute(command);
|
||||
if(success != 0 ) // returns PID on success
|
||||
return true;
|
||||
}
|
||||
}
|
||||
command = m_BrowserName;
|
||||
command << " file://"
|
||||
<< m_MapFile << WXEXTHELP_SEPARATOR << relativeURL;
|
||||
return wxExecute(command) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
wxExtHelpController::DisplayContents(void)
|
||||
{
|
||||
if(! m_NumOfEntries)
|
||||
return false;
|
||||
wxBusyCursor b; // display a busy cursor
|
||||
return KeywordSearch("");
|
||||
}
|
||||
|
||||
bool
|
||||
wxExtHelpController::DisplaySection(int sectionNo)
|
||||
{
|
||||
if(! m_NumOfEntries)
|
||||
return false;
|
||||
|
||||
wxBusyCursor b; // display a busy cursor
|
||||
wxExtHelpMapList::iterator i = m_MapList->begin();
|
||||
while(i != m_MapList->end())
|
||||
{
|
||||
if((**i).id == sectionNo)
|
||||
return CallBrowser((**i).url);
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wxExtHelpController::DisplayBlock(long blockNo)
|
||||
{
|
||||
return DisplaySection((int)blockNo);
|
||||
}
|
||||
|
||||
bool
|
||||
wxExtHelpController::KeywordSearch(const wxString& k)
|
||||
{
|
||||
if(! m_NumOfEntries)
|
||||
return false;
|
||||
|
||||
wxBusyCursor b; // display a busy cursor
|
||||
wxString *choices = new wxString[m_NumOfEntries];
|
||||
wxString *urls = new wxString[m_NumOfEntries];
|
||||
wxString compA, compB;
|
||||
|
||||
int idx = 0, j;
|
||||
bool rc;
|
||||
bool showAll = k.IsEmpty();
|
||||
wxExtHelpMapList::iterator i = m_MapList->begin();
|
||||
|
||||
compA = k; compA.LowerCase(); // we compare case insensitive
|
||||
while(i != m_MapList->end())
|
||||
{
|
||||
compB = (**i).doc; compB.LowerCase();
|
||||
if((showAll || compB.Contains(k)) && ! compB.IsEmpty())
|
||||
{
|
||||
urls[idx] = (**i).url;
|
||||
// doesn't work:
|
||||
// choices[idx] = (**i).doc.Contains((**i).doc.Before(WXEXTHELP_COMMENTCHAR));
|
||||
//if(choices[idx].IsEmpty()) // didn't contain the ';'
|
||||
// choices[idx] = (**i).doc;
|
||||
choices[idx] = "";
|
||||
for(j=0;(**i).doc.c_str()[j]
|
||||
&& (**i).doc.c_str()[j] != WXEXTHELP_COMMENTCHAR; j++)
|
||||
choices[idx] << (**i).doc.c_str()[j];
|
||||
idx++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if(idx == 1)
|
||||
rc = CallBrowser(urls[0]);
|
||||
else if(idx == 0)
|
||||
{
|
||||
wxMessageBox(_("No entries found."));
|
||||
rc = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = wxGetSingleChoiceIndex(showAll ? _("Help Index") : _("Relevant entries:"),
|
||||
showAll ? _("Help Index") : _("Entries found"),
|
||||
idx,choices);
|
||||
if(idx != -1)
|
||||
rc = CallBrowser(urls[idx]);
|
||||
else
|
||||
rc = false;
|
||||
}
|
||||
delete[] urls;
|
||||
delete[] choices;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
wxExtHelpController::Quit(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
wxExtHelpController::OnQuit(void)
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user