From 249b3fe3bb51b428327c3eb74b72869bb492ce1e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 27 Mar 2006 17:28:51 +0000 Subject: [PATCH] rewrote wxExtHelpController loading code to use wxFileName as it was broken under Mac and it also reduces the code size; also use wxTextFile to further simplify the code git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38390 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/helpext.h | 27 ++-- src/generic/helpext.cpp | 247 +++++++++++++++++++++-------------- 2 files changed, 161 insertions(+), 113 deletions(-) diff --git a/include/wx/generic/helpext.h b/include/wx/generic/helpext.h index aaad7d3ff3..9a721063c2 100644 --- a/include/wx/generic/helpext.h +++ b/include/wx/generic/helpext.h @@ -14,17 +14,6 @@ #include "wx/helpbase.h" -/// Path separator. -#ifdef __WXMSW__ -#define WXEXTHELP_SEPARATOR _T('\\') -#elif defined(__WXMAC__) -#define WXEXTHELP_SEPARATOR _T(':') -#else -#define WXEXTHELP_SEPARATOR _T('/') -#endif - -class WXDLLIMPEXP_ADV wxExtHelpMapList; - #ifndef WXEXTHELP_DEFAULTBROWSER /// Default browser name. # define WXEXTHELP_DEFAULTBROWSER _T("netscape") @@ -53,8 +42,7 @@ class WXDLLIMPEXP_ADV wxExtHelpMapList; class WXDLLIMPEXP_ADV wxExtHelpController : public wxHelpControllerBase { -DECLARE_CLASS(wxExtHelpController) - public: +public: wxExtHelpController(wxWindow* parentWindow = NULL); ~wxExtHelpController(); @@ -154,21 +142,30 @@ DECLARE_CLASS(wxExtHelpController) return (wxFrame*) NULL;// does nothing by default } - protected: +protected: /// Filename of currently active map file. wxString m_MapFile; /// How many entries do we have in the map file? int m_NumOfEntries; /// A list containing all id,url,documentation triples. wxList *m_MapList; + +private: + // parse a single line of the map file (called by LoadFile()) + // + // return true if the line was valid or false otherwise + bool ParseMapFileLine(const wxString& line); + /// Deletes the list and all objects. void DeleteList(void); - private: + /// How to call the html viewer. wxString m_BrowserName; /// Is the viewer a variant of netscape? bool m_BrowserIsNetscape; + + DECLARE_CLASS(wxExtHelpController) }; #endif // wxUSE_HELP diff --git a/src/generic/helpext.cpp b/src/generic/helpext.cpp index 1bf7d2b43d..dfd66791cf 100644 --- a/src/generic/helpext.cpp +++ b/src/generic/helpext.cpp @@ -27,7 +27,8 @@ #include "wx/log.h" #endif -#include "wx/helpbase.h" +#include "wx/filename.h" +#include "wx/textfile.h" #include "wx/generic/helpext.h" #include @@ -53,8 +54,7 @@ /// Name for map file. #define WXEXTHELP_MAPFILE _T("wxhelp.map") -/// Maximum line length in map file. -#define WXEXTHELP_BUFLEN 512 + /// Character introducing comments/documentation field in map file. #define WXEXTHELP_COMMENTCHAR ';' @@ -145,7 +145,7 @@ wxExtHelpController::DisplayHelp(const wxString &relativeURL) wxString command; command = m_BrowserName; command << wxT(" file://") - << m_MapFile << WXEXTHELP_SEPARATOR << relativeURL; + << m_MapFile << wxFILE_SEP_PATH << relativeURL; return wxExecute(command) != 0; #else // UNIX @@ -157,11 +157,11 @@ wxExtHelpController::DisplayHelp(const wxString &relativeURL) wxString lockfile; wxGetHomeDir(&lockfile); #ifdef __VMS__ - lockfile << WXEXTHELP_SEPARATOR << wxT(".netscape]lock."); + lockfile << wxFILE_SEP_PATH << wxT(".netscape]lock."); struct stat statbuf; if(stat(lockfile.fn_str(), &statbuf) == 0) #else - lockfile << WXEXTHELP_SEPARATOR << wxT(".netscape/lock"); + lockfile << wxFILE_SEP_PATH << wxT(".netscape/lock"); struct stat statbuf; if(lstat(lockfile.fn_str(), &statbuf) == 0) // cannot use wxFileExists, because it's a link pointing to a @@ -171,7 +171,7 @@ wxExtHelpController::DisplayHelp(const wxString &relativeURL) long success; command << m_BrowserName << wxT(" -remote openURL(") << wxT("file://") << m_MapFile - << WXEXTHELP_SEPARATOR << relativeURL << wxT(")"); + << wxFILE_SEP_PATH << relativeURL << wxT(")"); success = wxExecute(command); if(success != 0 ) // returns PID on success return true; @@ -180,7 +180,7 @@ wxExtHelpController::DisplayHelp(const wxString &relativeURL) #endif command = m_BrowserName; command << wxT(" file://") - << m_MapFile << WXEXTHELP_SEPARATOR << relativeURL; + << m_MapFile << wxFILE_SEP_PATH << relativeURL; return wxExecute(command) != 0; #endif } @@ -223,100 +223,151 @@ wxExtHelpController::Initialize(const wxString& file) } -// ifile is the name of the base help directory -bool wxExtHelpController::LoadFile(const wxString& ifile) +bool wxExtHelpController::ParseMapFileLine(const wxString& line) { - wxString mapFile, file, url, doc; - int id,i,len; - char buffer[WXEXTHELP_BUFLEN]; + const wxChar *p = line.c_str(); + + // skip whitespace + while ( isascii(*p) && isspace(*p) ) + p++; + + // skip empty lines and comments + if ( *p == _T('\0') || *p == WXEXTHELP_COMMENTCHAR ) + return true; + + // the line is of the form "num url" so we must have an integer now + wxChar *end; + const unsigned long id = wxStrtoul(p, &end, 0); + + if ( end == p ) + return false; + + p = end; + while ( isascii(*p) && isspace(*p) ) + p++; + + // next should be the URL + wxString url; + url.reserve(line.length()); + while ( isascii(*p) && !isspace(*p) ) + url += *p++; + + while ( isascii(*p) && isspace(*p) ) + p++; + + // and finally the optional description of the entry after comment + wxString doc; + if ( *p == WXEXTHELP_COMMENTCHAR ) + { + p++; + while ( isascii(*p) && isspace(*p) ) + p++; + doc = p; + } + + m_MapList->Append(new wxExtHelpMapEntry(id, url, doc)); + m_NumOfEntries++; + + return true; +} - wxBusyCursor b; // display a busy cursor +// file is a misnomer as it's the name of the base help directory +bool wxExtHelpController::LoadFile(const wxString& file) +{ + wxFileName helpDir(wxFileName::DirName(file)); + helpDir.MakeAbsolute(); - if(! ifile.empty()) - { - file = ifile; - if(! wxIsAbsolutePath(file)) - { - file = wxGetCwd(); -#ifdef __WXMAC__ - file << ifile; -#else - file << WXEXTHELP_SEPARATOR << ifile; -#endif - } - else - file = ifile; + bool dirExists = false; #if wxUSE_INTL - // If a locale is set, look in file/localename, i.e. - // If passed "/usr/local/myapp/help" and the current wxLocale is - // set to be "de", then look in "/usr/local/myapp/help/de/" - // first and fall back to "/usr/local/myapp/help" if that - // doesn't exist. - if(wxGetLocale() && !wxGetLocale()->GetName().empty()) - { - wxString newfile; - newfile << WXEXTHELP_SEPARATOR << wxGetLocale()->GetName(); - if(wxDirExists(newfile)) - file = newfile; - else - { - newfile = WXEXTHELP_SEPARATOR; - const wxChar *cptr = wxGetLocale()->GetName().c_str(); - while(*cptr && *cptr != wxT('_')) - newfile << *(cptr++); - if(wxDirExists(newfile)) - file = newfile; - } - } -#endif - - 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; - - DeleteList(); - m_MapList = new wxList; - m_NumOfEntries = 0; - - FILE *input = wxFopen(mapFile,wxT("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])||buffer[i]=='-'; i++) - ; // find begin of URL - url = wxEmptyString; - while(buffer[i] && ! isspace(buffer[i]) && buffer[i] != - WXEXTHELP_COMMENTCHAR) - url << (wxChar) buffer[i++]; - while(buffer[i] && buffer[i] != WXEXTHELP_COMMENTCHAR) - i++; - doc = wxEmptyString; - if(buffer[i]) - doc = wxString::FromAscii( (buffer + i + 1) ); // skip the comment character - m_MapList->Append(new wxExtHelpMapEntry(id,url,doc)); - m_NumOfEntries++; - } - }while(! feof(input)); - fclose(input); - - m_MapFile = file; // now it's valid - return true; + // If a locale is set, look in file/localename, i.e. If passed + // "/usr/local/myapp/help" and the current wxLocale is set to be "de", then + // look in "/usr/local/myapp/help/de/" first and fall back to + // "/usr/local/myapp/help" if that doesn't exist. + const wxLocale * const loc = wxGetLocale(); + if ( loc ) + { + wxString locName = loc->GetName(); + + // the locale is in general of the form xx_YY.zzzz, try the full firm + // first and then also more general ones + wxFileName helpDirLoc(helpDir); + helpDirLoc.AppendDir(locName); + dirExists = helpDirLoc.DirExists(); + + if ( !dirExists ) + { + // try without encoding + const wxString locNameWithoutEncoding = locName.BeforeLast(_T('.')); + if ( !locNameWithoutEncoding.empty() ) + { + helpDirLoc = helpDir; + helpDirLoc.AppendDir(locNameWithoutEncoding); + dirExists = helpDirLoc.DirExists(); + } + } + + if ( !dirExists ) + { + // try without country part + wxString locNameWithoutCountry = locName.BeforeLast(_T('_')); + if ( !locNameWithoutCountry.empty() ) + { + helpDirLoc = helpDir; + helpDirLoc.AppendDir(locNameWithoutCountry); + dirExists = helpDirLoc.DirExists(); + } + } + + if ( dirExists ) + helpDir = helpDirLoc; + } +#endif // wxUSE_INTL + + if ( !dirExists && !helpDir.DirExists() ) + { + wxLogError(_("Help directory \"%s\" not found."), + helpDir.GetFullPath().c_str()); + return false; + } + + const wxFileName mapFile(helpDir.GetFullPath(), WXEXTHELP_MAPFILE); + if ( !mapFile.FileExists() ) + { + wxLogError(_("Help file \"%s\" not found."), + mapFile.GetFullPath().c_str()); + return false; + } + + DeleteList(); + m_MapList = new wxList; + m_NumOfEntries = 0; + + wxTextFile input; + if ( !input.Open(mapFile.GetFullPath()) ) + return false; + + for ( wxString& line = input.GetFirstLine(); + !input.Eof(); + line = input.GetNextLine() ) + { + if ( !ParseMapFileLine(line) ) + { + wxLogWarning(_("Line %lu of map file \"%s\" has invalid syntax, skipped."), + (unsigned long)input.GetCurrentLine(), + mapFile.GetFullPath().c_str()); + } + } + + if ( !m_NumOfEntries ) + { + wxLogError(_("No valid mappings found in the file \"%s\"."), + mapFile.GetFullPath().c_str()); + return false; + } + + m_MapFile = helpDir.GetFullPath(); // now it's valid + return true; } @@ -342,7 +393,7 @@ wxExtHelpController::DisplayContents() bool rc = false; wxString file; - file << m_MapFile << WXEXTHELP_SEPARATOR << contents; + file << m_MapFile << wxFILE_SEP_PATH << contents; if(file.Contains(wxT('#'))) file = file.BeforeLast(wxT('#')); if(contents.length() && wxFileExists(file)) -- 2.45.2