home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / generic / helphtml.cpp < prev    next >
C/C++ Source or Header  |  2002-11-04  |  9KB  |  361 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        helphtml.cpp
  3. // Purpose:     base class for html help systems
  4. // Author:      Karsten Ballueder
  5. // Modified by:
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: helphtml.cpp,v 1.23.2.1 2002/10/29 21:47:53 RR Exp $
  8. // Copyright:   (c) Karsten Ballueder
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13. #   pragma implementation "helphtml.h"
  14. #endif
  15.  
  16. #include "wx/wxprec.h"
  17.  
  18. #ifdef __BORLANDC__
  19.     #pragma hdrstop
  20. #endif
  21.  
  22. #if wxUSE_HELP
  23.  
  24. #ifndef WX_PRECOMP
  25.     #include "wx/setup.h"
  26.     #include "wx/string.h"
  27.     #include "wx/utils.h"
  28.     #include "wx/list.h"
  29.     #include "wx/intl.h"
  30.     #include "wx/msgdlg.h"
  31.     #include "wx/choicdlg.h"
  32. #endif
  33.  
  34. #include "wx/helpbase.h"
  35. #include "wx/generic/helpext.h"
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #ifndef __MWERKS__
  40. #include <sys/stat.h>
  41. #endif
  42.  
  43. #if !defined(__WINDOWS__) && !defined(__OS2__)
  44.     #include   <unistd.h>
  45. #endif
  46.  
  47. // ----------------------------------------------------------------------------
  48. // constants
  49. // ----------------------------------------------------------------------------
  50.  
  51. /// Name for map file.
  52. #define WXEXTHELP_MAPFILE   _T("wxhelp.map")
  53. /// Maximum line length in map file.
  54. #define WXEXTHELP_BUFLEN 512
  55. /// Character introducing comments/documentation field in map file.
  56. #define WXEXTHELP_COMMENTCHAR   ';'
  57.  
  58. #define CONTENTS_ID   0
  59.  
  60. class wxExtHelpMapEntry : public wxObject
  61. {
  62. public:
  63.    int      id;
  64.    wxString url;
  65.    wxString doc;
  66.    wxExtHelpMapEntry(int iid, wxString const &iurl, wxString const &idoc)
  67.       { id = iid; url = iurl; doc = idoc; }
  68. };
  69.  
  70. IMPLEMENT_ABSTRACT_CLASS(wxHTMLHelpControllerBase, wxHelpControllerBase)
  71.  
  72. /**
  73.    This class implements help via an external browser.
  74.    It requires the name of a directory containing the documentation
  75.    and a file mapping numerical Section numbers to relative URLS.
  76. */
  77.  
  78. wxHTMLHelpControllerBase::wxHTMLHelpControllerBase()
  79. {
  80.    m_MapList = (wxList*) NULL;
  81.    m_NumOfEntries = 0;
  82. }
  83.  
  84. void
  85. wxHTMLHelpControllerBase::DeleteList()
  86. {
  87.    if(m_MapList)
  88.    {
  89.       wxNode *node = m_MapList->First();
  90.       while (node)
  91.       {
  92.          delete (wxExtHelpMapEntry *)node->Data();
  93.          delete node;
  94.          node = m_MapList->First();
  95.       }
  96.       delete m_MapList;
  97.       m_MapList = (wxList*) NULL;
  98.    }
  99. }
  100.  
  101. wxHTMLHelpControllerBase::~wxHTMLHelpControllerBase()
  102. {
  103.    DeleteList();
  104. }
  105.  
  106. /** This must be called to tell the controller where to find the
  107.     documentation.
  108.     @param file - NOT a filename, but a directory name.
  109.     @return true on success
  110. */
  111. bool
  112. wxHTMLHelpControllerBase::Initialize(const wxString& file)
  113. {
  114.    return LoadFile(file);
  115. }
  116.  
  117.  
  118. // ifile is the name of the base help directory
  119. bool
  120. wxHTMLHelpControllerBase::LoadFile(const wxString& ifile)
  121. {
  122.    wxString mapFile, file, url, doc;
  123.    int id,i,len;
  124.    char buffer[WXEXTHELP_BUFLEN];
  125.  
  126.    wxBusyCursor b; // display a busy cursor
  127.  
  128.    if(! ifile.IsEmpty())
  129.    {
  130.       file = ifile;
  131.       if(! wxIsAbsolutePath(file))
  132.       {
  133.          wxChar* f = wxGetWorkingDirectory();
  134.          file = f;
  135.          delete[] f; // wxGetWorkingDirectory returns new memory
  136. #ifdef __WXMAC__
  137.          file << ifile;
  138. #else
  139.          file << WXEXTHELP_SEPARATOR << ifile;
  140. #endif
  141.       }
  142.       else
  143.          file = ifile;
  144.  
  145. #if wxUSE_INTL
  146.       // If a locale is set, look in file/localename, i.e.
  147.       // If passed "/usr/local/myapp/help" and the current wxLocale is
  148.       // set to be "de", then look in "/usr/local/myapp/help/de/"
  149.       // first and fall back to "/usr/local/myapp/help" if that
  150.       // doesn't exist.
  151.       if(wxGetLocale() && !wxGetLocale()->GetName().IsEmpty())
  152.       {
  153.          wxString newfile;
  154.          newfile << WXEXTHELP_SEPARATOR << wxGetLocale()->GetName();
  155.          if(wxDirExists(newfile))
  156.             file = newfile;
  157.          else
  158.          {
  159.             newfile = WXEXTHELP_SEPARATOR;
  160.             const wxChar *cptr = wxGetLocale()->GetName().c_str();
  161.             while(*cptr && *cptr != wxT('_'))
  162.                newfile << *(cptr++);
  163.             if(wxDirExists(newfile))
  164.                file = newfile;
  165.          }
  166.       }
  167. #endif
  168.  
  169.       if(! wxDirExists(file))
  170.          return FALSE;
  171.  
  172.       mapFile << file << WXEXTHELP_SEPARATOR << WXEXTHELP_MAPFILE;
  173.    }
  174.    else // try to reload old file
  175.       mapFile = m_MapFile;
  176.  
  177.    if(! wxFileExists(mapFile))
  178.       return FALSE;
  179.  
  180.    DeleteList();
  181.    m_MapList = new wxList;
  182.    m_NumOfEntries = 0;
  183.  
  184.    FILE *input = wxFopen(mapFile,wxT("rt"));
  185.    if(! input)
  186.       return FALSE;
  187.    do
  188.    {
  189.       if(fgets(buffer,WXEXTHELP_BUFLEN,input) && *buffer != WXEXTHELP_COMMENTCHAR)
  190.       {
  191.          len = strlen(buffer);
  192.          if(buffer[len-1] == '\n')
  193.             buffer[len-1] = '\0'; // cut of trailing newline
  194.          if(sscanf(buffer,"%d", &id) != 1)
  195.             break; // error
  196.          for(i=0; isdigit(buffer[i])||isspace(buffer[i])||buffer[i]=='-'; i++)
  197.             ; // find begin of URL
  198.          url = wxT("");
  199.          while(buffer[i] && ! isspace(buffer[i]) && buffer[i] !=
  200.                WXEXTHELP_COMMENTCHAR)
  201.             url << (wxChar) buffer[i++];
  202.          while(buffer[i] && buffer[i] != WXEXTHELP_COMMENTCHAR)
  203.             i++;
  204.          doc = wxT("");
  205.          if(buffer[i])
  206.             doc = wxString::FromAscii( (buffer + i + 1) ); // skip the comment character
  207.          m_MapList->Append(new wxExtHelpMapEntry(id,url,doc));
  208.          m_NumOfEntries++;
  209.       }
  210.    }while(! feof(input));
  211.    fclose(input);
  212.  
  213.    m_MapFile = file; // now it's valid
  214.    return TRUE;
  215. }
  216.  
  217.  
  218. bool
  219. wxHTMLHelpControllerBase::DisplayContents()
  220. {
  221.    if(! m_NumOfEntries)
  222.       return FALSE;
  223.  
  224.    wxString contents;
  225.    wxNode *node = m_MapList->First();
  226.    wxExtHelpMapEntry *entry;
  227.    while(node)
  228.    {
  229.       entry = (wxExtHelpMapEntry *)node->Data();
  230.       if(entry->id == CONTENTS_ID)
  231.       {
  232.          contents = entry->url;
  233.          break;
  234.       }
  235.       node = node->Next();
  236.    }
  237.  
  238.    bool rc = FALSE;
  239.    wxString file;
  240.    file << m_MapFile << WXEXTHELP_SEPARATOR << contents;
  241.    if(file.Contains(wxT('#')))
  242.       file = file.BeforeLast(wxT('#'));
  243.    if(contents.Length() && wxFileExists(file))
  244.       rc = DisplaySection(CONTENTS_ID);
  245.  
  246.    // if not found, open homemade toc:
  247.    return rc ? TRUE : KeywordSearch(wxT(""));
  248. }
  249.  
  250. bool
  251. wxHTMLHelpControllerBase::DisplaySection(int sectionNo)
  252. {
  253.    if(! m_NumOfEntries)
  254.       return FALSE;
  255.  
  256.    wxBusyCursor b; // display a busy cursor
  257.    wxNode *node = m_MapList->First();
  258.    wxExtHelpMapEntry *entry;
  259.    while(node)
  260.    {
  261.       entry = (wxExtHelpMapEntry *)node->Data();
  262.       if(entry->id == sectionNo)
  263.          return DisplayHelp(entry->url);
  264.       node = node->Next();
  265.    }
  266.    return FALSE;
  267. }
  268.  
  269. bool wxHTMLHelpControllerBase::DisplaySection(const wxString& section)
  270. {
  271.     bool isFilename = (section.Find(wxT(".htm")) != -1);
  272.  
  273.     if (isFilename)
  274.         return DisplayHelp(section);
  275.     else
  276.         return KeywordSearch(section);
  277. }
  278.  
  279. bool
  280. wxHTMLHelpControllerBase::DisplayBlock(long blockNo)
  281. {
  282.    return DisplaySection((int)blockNo);
  283. }
  284.  
  285. bool
  286. wxHTMLHelpControllerBase::KeywordSearch(const wxString& k)
  287. {
  288.    if(! m_NumOfEntries)
  289.       return FALSE;
  290.  
  291.    wxString     *choices = new wxString[m_NumOfEntries];
  292.    wxString     *urls = new wxString[m_NumOfEntries];
  293.    wxString compA, compB;
  294.  
  295.    int          idx = 0, j;
  296.    bool         rc;
  297.    bool         showAll = k.IsEmpty();
  298.    wxNode       *node = m_MapList->First();
  299.    wxExtHelpMapEntry *entry;
  300.  
  301.    {
  302.       wxBusyCursor b; // display a busy cursor
  303.       compA = k; compA.LowerCase(); // we compare case insensitive
  304.       while(node)
  305.       {
  306.          entry = (wxExtHelpMapEntry *)node->Data();
  307.          compB = entry->doc; compB.LowerCase();
  308.          if((showAll || compB.Contains(k)) && ! compB.IsEmpty())
  309.          {
  310.             urls[idx] = entry->url;
  311.             // doesn't work:
  312.             // choices[idx] = (**i).doc.Contains((**i).doc.Before(WXEXTHELP_COMMENTCHAR));
  313.             //if(choices[idx].IsEmpty()) // didn't contain the ';'
  314.             //   choices[idx] = (**i).doc;
  315.             choices[idx] = wxT("");
  316.             for(j=0;entry->doc.c_str()[j]
  317.                    && entry->doc.c_str()[j] != WXEXTHELP_COMMENTCHAR; j++)
  318.                choices[idx] << entry->doc.c_str()[j];
  319.             idx++;
  320.          }
  321.          node = node->Next();
  322.       }
  323.    }
  324.  
  325.    if(idx == 1)
  326.       rc = DisplayHelp(urls[0]);
  327.    else if(idx == 0)
  328.    {
  329.       wxMessageBox(_("No entries found."));
  330.       rc = FALSE;
  331.    }
  332.    else
  333.    {
  334.       idx = wxGetSingleChoiceIndex(showAll ? _("Help Index") : _("Relevant entries:"),
  335.                                    showAll ? _("Help Index") : _("Entries found"),
  336.                                    idx,choices);
  337.       if(idx != -1)
  338.          rc = DisplayHelp(urls[idx]);
  339.       else
  340.          rc = FALSE;
  341.    }
  342.    delete[] urls;
  343.    delete[] choices;
  344.  
  345.    return rc;
  346. }
  347.  
  348.  
  349. bool
  350. wxHTMLHelpControllerBase::Quit()
  351. {
  352.    return TRUE;
  353. }
  354.  
  355. void
  356. wxHTMLHelpControllerBase::OnQuit()
  357. {
  358. }
  359.  
  360. #endif // wxUSE_HELP
  361.