- // constructors
- wxMimeTextFile () : wxTextFile () {};
- wxMimeTextFile(const wxString& strFile) : wxTextFile(strFile) {};
-
- int pIndexOf(const wxString & sSearch, bool bIncludeComments = false, int iStart = 0)
- {
- size_t i = iStart;
- int nResult = wxNOT_FOUND;
- if (i >= GetLineCount())
- return wxNOT_FOUND;
-
- wxString sTest = sSearch;
- sTest.MakeLower();
- wxString sLine;
-
- if (bIncludeComments)
- {
- while ( i < GetLineCount() )
- {
- sLine = GetLine(i);
- sLine.MakeLower();
- if (sLine.Contains(sTest))
- nResult = (int) i;
-
- i++;
- }
- }
- else
- {
- while ( (i < GetLineCount()) )
- {
- sLine = GetLine(i);
- sLine.MakeLower();
- if ( ! sLine.StartsWith(wxT("#")))
- {
- if (sLine.Contains(sTest))
- nResult = (int) i;
- }
-
- i++;
- }
- }
-
- return nResult;
- }
-
- bool CommentLine(int nIndex)
- {
- if (nIndex < 0)
- return false;
- if (nIndex >= (int)GetLineCount() )
- return false;
-
- GetLine(nIndex) = GetLine(nIndex).Prepend(wxT("#"));
- return true;
- }
-
- bool CommentLine(const wxString & sTest)
- {
- int nIndex = pIndexOf(sTest);
- if (nIndex < 0)
- return false;
- if (nIndex >= (int)GetLineCount() )
- return false;
-
- GetLine(nIndex) = GetLine(nIndex).Prepend(wxT("#"));
- return true;
- }
-
- wxString GetVerb(size_t i)
- {
- if (i > GetLineCount() )
- return wxEmptyString;
-
- wxString sTmp = GetLine(i).BeforeFirst(wxT('='));
- return sTmp;
- }
-
- wxString GetCmd(size_t i)
- {
- if (i > GetLineCount() )
- return wxEmptyString;
-
- wxString sTmp = GetLine(i).AfterFirst(wxT('='));
- return sTmp;
- }
-};
-
-// in case we're compiling in non-GUI mode
-class WXDLLEXPORT wxIcon;
-
-// ----------------------------------------------------------------------------
-// constants
-// ----------------------------------------------------------------------------
-
-// MIME code tracing mask
-#define TRACE_MIME wxT("mime")
-
-// give trace messages about the results of mailcap tests
-#define TRACE_MIME_TEST wxT("mimetest")
-
-// ----------------------------------------------------------------------------
-// private functions
-// ----------------------------------------------------------------------------
-
-// there are some fields which we don't understand but for which we don't give
-// warnings as we know that they're not important - this function is used to
-// test for them
-static bool IsKnownUnimportantField(const wxString& field);
-
-// ----------------------------------------------------------------------------
-// private classes
-// ----------------------------------------------------------------------------
-
-
-// This class uses both mailcap and mime.types to gather information about file
-// types.
-//
-// The information about mailcap file was extracted from metamail(1) sources
-// and documentation and subsequently revised when I found the RFC 1524
-// describing it.
-//
-// Format of mailcap file: spaces are ignored, each line is either a comment
-// (starts with '#') or a line of the form <field1>;<field2>;...;<fieldN>.
-// A backslash can be used to quote semicolons and newlines (and, in fact,
-// anything else including itself).
-//
-// The first field is always the MIME type in the form of type/subtype (see RFC
-// 822) where subtype may be '*' meaning "any". Following metamail, we accept
-// "type" which means the same as "type/*", although I'm not sure whether this
-// is standard.
-//
-// The second field is always the command to run. It is subject to
-// parameter/filename expansion described below.
-//
-// All the following fields are optional and may not be present at all. If
-// they're present they may appear in any order, although each of them should
-// appear only once. The optional fields are the following:
-// * notes=xxx is an uninterpreted string which is silently ignored
-// * test=xxx is the command to be used to determine whether this mailcap line
-// applies to our data or not. The RHS of this field goes through the
-// parameter/filename expansion (as the 2nd field) and the resulting string
-// is executed. The line applies only if the command succeeds, i.e. returns 0
-// exit code.
-// * print=xxx is the command to be used to print (and not view) the data of
-// this type (parameter/filename expansion is done here too)
-// * edit=xxx is the command to open/edit the data of this type
-// * needsterminal means that a new interactive console must be created for
-// the viewer
-// * copiousoutput means that the viewer doesn't interact with the user but
-// produces (possibly) a lof of lines of output on stdout (i.e. "cat" is a
-// good example), thus it might be a good idea to use some kind of paging
-// mechanism.
-// * textualnewlines means not to perform CR/LF translation (not honored)
-// * compose and composetyped fields are used to determine the program to be
-// called to create a new message pert in the specified format (unused).
-//
-// Parameter/filename expansion:
-// * %s is replaced with the (full) file name
-// * %t is replaced with MIME type/subtype of the entry
-// * for multipart type only %n is replaced with the nnumber of parts and %F is
-// replaced by an array of (content-type, temporary file name) pairs for all
-// message parts (TODO)
-// * %{parameter} is replaced with the value of parameter taken from
-// Content-type header line of the message.
-//
-//
-// There are 2 possible formats for mime.types file, one entry per line (used
-// for global mime.types and called Mosaic format) and "expanded" format where
-// an entry takes multiple lines (used for users mime.types and called
-// Netscape format).
-//
-// For both formats spaces are ignored and lines starting with a '#' are
-// comments. Each record has one of two following forms:
-// a) for "brief" format:
-// <mime type> <space separated list of extensions>
-// b) for "expanded" format:
-// type=<mime type> BACKSLASH
-// desc="<description>" BACKSLASH
-// exts="<comma separated list of extensions>"
-//
-// (where BACKSLASH is a literal '\\' which we can't put here because cpp
-// misinterprets it)
-//
-// We try to autodetect the format of mime.types: if a non-comment line starts
-// with "type=" we assume the second format, otherwise the first one.
-
-// there may be more than one entry for one and the same mime type, to
-// choose the right one we have to run the command specified in the test
-// field on our data.
-
-// ----------------------------------------------------------------------------
-// wxGNOME
-// ----------------------------------------------------------------------------
-
-// GNOME stores the info we're interested in in several locations:
-// 1. xxx.keys files under /usr/share/mime-info
-// 2. xxx.keys files under ~/.gnome/mime-info
-//
-// Update (Chris Elliott): apparently there may be an optional "[lang]" prefix
-// just before the field name.
-
-
-void wxMimeTypesManagerImpl::LoadGnomeDataFromKeyFile(const wxString& filename,
- const wxArrayString& dirs)
-{
- wxTextFile textfile(filename);
-#if defined(__WXGTK20__) && wxUSE_UNICODE
- if ( !textfile.Open(wxConvUTF8) )
-#else
- if ( !textfile.Open() )
-#endif
- return;
-
- wxLogTrace(TRACE_MIME, wxT("--- Opened Gnome file %s ---"),
- filename.c_str());
-
- wxArrayString search_dirs( dirs );
-
- // values for the entry being parsed
- wxString curMimeType, curIconFile;
- wxMimeTypeCommands * entry = new wxMimeTypeCommands;
-
- wxArrayString strExtensions;
- wxString strDesc;
-
- const wxChar *pc;
- size_t nLineCount = textfile.GetLineCount();
- size_t nLine = 0;
- while ( nLine < nLineCount )
- {
- pc = textfile[nLine].c_str();
- if ( *pc != wxT('#') )
- {
-
- wxLogTrace(TRACE_MIME, wxT("--- Reading from Gnome file %s '%s' ---"),
- filename.c_str(), pc);
-
- // trim trailing space and tab
- while ((*pc == wxT(' ')) || (*pc == wxT('\t')))
- pc++;
-
- wxString sTmp(pc);
- int equal_pos = sTmp.Find( wxT('=') );
- if (equal_pos > 0)
- {
- wxString left_of_equal = sTmp.Left( equal_pos );
- const wxChar *right_of_equal = pc;
- right_of_equal += equal_pos+1;
-
- if (left_of_equal == wxT("icon_filename"))
- {
- // GNOME 2:
- curIconFile = right_of_equal;
-
- wxFileName newFile( curIconFile );
- if (newFile.IsRelative() || newFile.FileExists())
- {
- size_t nDirs = search_dirs.GetCount();
-
- for (size_t nDir = 0; nDir < nDirs; nDir++)
- {
- newFile.SetPath( search_dirs[nDir] );
- newFile.AppendDir( wxT("pixmaps") );
- newFile.AppendDir( wxT("document-icons") );
- newFile.SetExt( wxT("png") );
- if (newFile.FileExists())
- {
- curIconFile = newFile.GetFullPath();
- // reorder search_dirs for speedup (fewer
- // calls to FileExist() required)
- if (nDir != 0)
- {
- wxString tmp = search_dirs[nDir];
- search_dirs.RemoveAt( nDir );
- search_dirs.Insert( tmp, 0 );
- }
- break;
- }
- }
- }
- }
- else if (left_of_equal == wxT("open"))
- {
- sTmp = right_of_equal;
- sTmp.Replace( wxT("%f"), wxT("%s") );
- sTmp.Prepend( wxT("open=") );
- entry->Add(sTmp);
- }
- else if (left_of_equal == wxT("view"))
- {
- sTmp = right_of_equal;
- sTmp.Replace( wxT("%f"), wxT("%s") );
- sTmp.Prepend( wxT("view=") );
- entry->Add(sTmp);
- }
- else if (left_of_equal == wxT("print"))
- {
- sTmp = right_of_equal;
- sTmp.Replace( wxT("%f"), wxT("%s") );
- sTmp.Prepend( wxT("print=") );
- entry->Add(sTmp);
- }
- else if (left_of_equal == wxT("description"))
- {
- strDesc = right_of_equal;
- }
- else if (left_of_equal == wxT("short_list_application_ids_for_novice_user_level"))
- {
- sTmp = right_of_equal;
- if (sTmp.Contains( wxT(",") ))
- sTmp = sTmp.BeforeFirst( wxT(',') );
- sTmp.Prepend( wxT("open=") );
- sTmp.Append( wxT(" %s") );
- entry->Add(sTmp);
- }
-
- } // emd of has an equals sign
- else
- {
- // not a comment and not an equals sign
- if (sTmp.Contains(wxT('/')))
- {
- // this is the start of the new mimetype
- // overwrite any existing data
- if (! curMimeType.empty())
- {
- AddToMimeData( curMimeType, curIconFile, entry, strExtensions, strDesc );
-
- // now get ready for next bit
- entry = new wxMimeTypeCommands;
- }
-
- curMimeType = sTmp.BeforeFirst(wxT(':'));
- }
- }
- } // end of not a comment
-
- // ignore blank lines
- nLine++;
- } // end of while, save any data
-
- if ( curMimeType.empty() )
- delete entry;
- else
- AddToMimeData( curMimeType, curIconFile, entry, strExtensions, strDesc);
-}
-
-void wxMimeTypesManagerImpl::LoadGnomeMimeTypesFromMimeFile(const wxString& filename)
-{
- wxTextFile textfile(filename);
- if ( !textfile.Open() )
- return;
-
- wxLogTrace(TRACE_MIME,
- wxT("--- Opened Gnome file %s ---"),
- filename.c_str());
-
- // values for the entry being parsed
- wxString curMimeType, curExtList;
-
- const wxChar *pc;
- size_t nLineCount = textfile.GetLineCount();
- for ( size_t nLine = 0; /* nothing */; nLine++ )
- {
- if ( nLine < nLineCount )
- {
- pc = textfile[nLine].c_str();
- if ( *pc == wxT('#') )
- {
- // skip comments
- continue;
- }
- }
- else
- {
- // so that we will fall into the "if" below
- pc = NULL;
- }
-
- if ( !pc || !*pc )
- {
- // end of the entry
- if ( !curMimeType.empty() && !curExtList.empty() )
- {
- wxLogTrace(TRACE_MIME,
- wxT("--- At end of Gnome file finding mimetype %s ---"),
- curMimeType.c_str());
-
- AddMimeTypeInfo(curMimeType, curExtList, wxEmptyString);
- }
-
- if ( !pc )
- {
- // the end: this can only happen if nLine == nLineCount
- break;
- }
-
- curExtList.Empty();
-
- continue;
- }
-
- // what do we have here?
- if ( *pc == wxT('\t') )
- {
- // this is a field=value ling
- pc++; // skip leading TAB
-
- static const int lenField = 5; // strlen("ext: ")
- if ( wxStrncmp(pc, wxT("ext: "), lenField) == 0 )
- {
- // skip it and take everything left until the end of line
- curExtList = pc + lenField;
- }
- //else: some other field, we don't care
- }
- else
- {
- // this is the start of the new section
- wxLogTrace(TRACE_MIME,
- wxT("--- In Gnome file finding mimetype %s ---"),
- curMimeType.c_str());
-
- if (! curMimeType.empty())
- AddMimeTypeInfo(curMimeType, curExtList, wxEmptyString);
-
- curMimeType.Empty();
-
- while ( *pc != wxT(':') && *pc != wxT('\0') )
- {
- curMimeType += *pc++;
- }
- }
- }
-}
-
-
-void wxMimeTypesManagerImpl::LoadGnomeMimeFilesFromDir(
- const wxString& dirbase, const wxArrayString& dirs)
-{
- wxASSERT_MSG( !dirbase.empty() && !wxEndsWithPathSeparator(dirbase),
- wxT("base directory shouldn't end with a slash") );
-
- wxString dirname = dirbase;
- dirname << wxT("/mime-info");
-
- if ( !wxDir::Exists(dirname) )
- return;
-
- wxDir dir(dirname);
- if ( !dir.IsOpened() )
- return;
-
- // we will concatenate it with filename to get the full path below
- dirname += wxT('/');
-
- wxString filename;
- bool cont;
-
- cont = dir.GetFirst(&filename, wxT("*.mime"), wxDIR_FILES);
- while ( cont )
- {
- LoadGnomeMimeTypesFromMimeFile(dirname + filename);
-
- cont = dir.GetNext(&filename);
- }
-
- cont = dir.GetFirst(&filename, wxT("*.keys"), wxDIR_FILES);
- while ( cont )
- {
- LoadGnomeDataFromKeyFile(dirname + filename, dirs);
-
- cont = dir.GetNext(&filename);
- }
-
- // FIXME: Hack alert: We scan all icons and deduce the
- // mime-type from the file name.
- dirname = dirbase;
- dirname << wxT("/pixmaps/document-icons");
-
- // these are always empty in this file
- wxArrayString strExtensions;
- wxString strDesc;
-
- if ( !wxDir::Exists(dirname) )
- {
- // Just test for default GPE dir also
- dirname = wxT("/usr/share/gpe/pixmaps/default/filemanager/document-icons");
-
- if ( !wxDir::Exists(dirname) )
- return;
- }
-
- wxDir dir2( dirname );
-
- cont = dir2.GetFirst(&filename, wxT("gnome-*.png"), wxDIR_FILES);
- while ( cont )