- AddToMimeData (strMimeType, strIcon, entry, sExts, strDesc, (bool)TRUE);
-}
-
-void wxMimeTypesManagerImpl::AddMailcapInfo(const wxString& strType,
- const wxString& strOpenCmd,
- const wxString& strPrintCmd,
- const wxString& strTest,
- const wxString& strDesc)
-{
- InitIfNeeded();
-
- wxMimeArrayString *entry = new wxMimeArrayString;
- entry->Add(wxT("open=") + strOpenCmd);
- entry->Add(wxT("print=") + strPrintCmd);
- entry->Add(wxT("test=") + strTest);
-
- wxString strIcon;
- wxArrayString strExtensions;
-
- AddToMimeData (strType, strIcon, entry, strExtensions, strDesc, TRUE);
-
-}
-
-bool wxMimeTypesManagerImpl::ReadMimeTypes(const wxString& strFileName)
-{
- wxLogTrace(TRACE_MIME, wxT("--- Parsing mime.types file '%s' ---"),
- strFileName.c_str());
-
- wxTextFile file(strFileName);
- if ( !file.Open() )
- return FALSE;
-
- // the information we extract
- wxString strMimeType, strDesc, strExtensions;
-
- size_t nLineCount = file.GetLineCount();
- const wxChar *pc = NULL;
- for ( size_t nLine = 0; nLine < nLineCount; nLine++ ) {
- if ( pc == NULL ) {
- // now we're at the start of the line
- pc = file[nLine].c_str();
- }
- else {
- // we didn't finish with the previous line yet
- nLine--;
- }
-
- // skip whitespace
- while ( wxIsspace(*pc) )
- pc++;
-
- // comment or blank line?
- if ( *pc == wxT('#') || !*pc ) {
- // skip the whole line
- pc = NULL;
- continue;
- }
-
- // detect file format
- const wxChar *pEqualSign = wxStrchr(pc, wxT('='));
- if ( pEqualSign == NULL ) {
- // brief format
- // ------------
-
- // first field is mime type
- for ( strMimeType.Empty(); !wxIsspace(*pc) && *pc != wxT('\0'); pc++ ) {
- strMimeType += *pc;
- }
-
- // skip whitespace
- while ( wxIsspace(*pc) )
- pc++;
-
- // take all the rest of the string
- strExtensions = pc;
-
- // no description...
- strDesc.Empty();
- }
- else {
- // expanded format
- // ---------------
-
- // the string on the left of '=' is the field name
- wxString strLHS(pc, pEqualSign - pc);
-
- // eat whitespace
- for ( pc = pEqualSign + 1; wxIsspace(*pc); pc++ )
- ;
-
- const wxChar *pEnd;
- if ( *pc == wxT('"') ) {
- // the string is quoted and ends at the matching quote
- pEnd = wxStrchr(++pc, wxT('"'));
- if ( pEnd == NULL ) {
- wxLogWarning(_("Mime.types file %s, line %d: unterminated "
- "quoted string."),
- strFileName.c_str(), nLine + 1);
- }
- }
- else {
- // unquoted string ends at the first space or at the end of
- // line
- for ( pEnd = pc; *pEnd && !wxIsspace(*pEnd); pEnd++ )
- ;
- }
-
- // now we have the RHS (field value)
- wxString strRHS(pc, pEnd - pc);
-
- // check what follows this entry
- if ( *pEnd == wxT('"') ) {
- // skip this quote
- pEnd++;
- }
-
- for ( pc = pEnd; wxIsspace(*pc); pc++ )
- ;
-
- // if there is something left, it may be either a '\\' to continue
- // the line or the next field of the same entry
- bool entryEnded = *pc == wxT('\0'),
- nextFieldOnSameLine = FALSE;
- if ( !entryEnded ) {
- nextFieldOnSameLine = ((*pc != wxT('\\')) || (pc[1] != wxT('\0')));
- }
-
- // now see what we got
- if ( strLHS == wxT("type") ) {
- strMimeType = strRHS;
- }
- else if ( strLHS == wxT("desc") ) {
- strDesc = strRHS;
- }
- else if ( strLHS == wxT("exts") ) {
- strExtensions = strRHS;
- }
- else {
- // this one is simply ignored: it usually refers to Netscape
- // built in icons which are useless for us anyhow
- if ( strLHS != _T("icon") )
- {
- wxLogWarning(_("Unknown field in file %s, line %d: '%s'."),
- strFileName.c_str(), nLine + 1, strLHS.c_str());
- }
- }
-
- if ( !entryEnded ) {
- if ( !nextFieldOnSameLine )
- pc = NULL;
- //else: don't reset it
-
- // as we don't reset strMimeType, the next field in this entry
- // will be interpreted correctly.
-
- continue;
- }
- }
-
- // depending on the format (Mosaic or Netscape) either space or comma
- // is used to separate the extensions
- strExtensions.Replace(wxT(","), wxT(" "));
-
- // also deal with the leading dot
- if ( !strExtensions.IsEmpty() && strExtensions[0u] == wxT('.') )
- {
- strExtensions.erase(0, 1);
- }
-
- wxLogTrace(TRACE_MIME, wxT("--- Found Mimetype '%s' ---"),
- strMimeType.c_str());
-
- AddMimeTypeInfo(strMimeType, strExtensions, strDesc);
-
- // finished with this line
- pc = NULL;
- }
-
- return TRUE;
-}
-
-bool wxMimeTypesManagerImpl::ReadMailcap(const wxString& strFileName,
- bool fallback)
-{
-// wxLog::AddTraceMask (TRACE_MIME);
- wxLogTrace(TRACE_MIME, wxT("--- Parsing mailcap file '%s' ---"),
- strFileName.c_str());
-
- wxTextFile file(strFileName);
- if ( !file.Open() )
- return FALSE;
-
- // see the comments near the end of function for the reason we need these
- // variables (search for the next occurence of them)
- // indices of MIME types (in m_aTypes) we already found in this file
- wxArrayInt aEntryIndices;
- // aLastIndices[n] is the index of last element in
- // m_aEntries[aEntryIndices[n]] from this file
- // wxArrayInt aLastIndices;
-
- size_t nLineCount = file.GetLineCount();
- for ( size_t nLine = 0; nLine < nLineCount; nLine++ ) {
- // now we're at the start of the line
- const wxChar *pc = file[nLine].c_str();
-
- // skip whitespace
- while ( wxIsspace(*pc) )
- pc++;
-
- // comment or empty string?
- if ( *pc == wxT('#') || *pc == wxT('\0') )
- continue;
-
- // no, do parse
-
- // what field are we currently in? The first 2 are fixed and there may
- // be an arbitrary number of other fields -- currently, we are not
- // interested in any of them, but we should parse them as well...
- enum
- {
- Field_Type,
- Field_OpenCmd,
- Field_Other
- } currentToken = Field_Type;
-
- // the flags and field values on the current line
- bool needsterminal = FALSE,
- copiousoutput = FALSE;
- wxMimeArrayString *entry = NULL; // suppress compiler warning
-
- wxString strType,
- strOpenCmd,
- strIcon,
- strTest,
- strDesc,
- curField; // accumulator
- bool cont = TRUE;
- bool test_passed = TRUE;
- while ( cont ) {
- switch ( *pc ) {
- case wxT('\\'):
- // interpret the next character literally (notice that
- // backslash can be used for line continuation)
- if ( *++pc == wxT('\0') ) {
- // fetch the next line if there is one
- if ( nLine == nLineCount - 1 ) {
- // something is wrong, bail out
- cont = FALSE;
-
- wxLogDebug(wxT("Mailcap file %s, line %d: "
- "'\\' on the end of the last line "
- "ignored."),
- strFileName.c_str(),
- nLine + 1);
- }
- else {
- // pass to the beginning of the next line
- pc = file[++nLine].c_str();
-
- // skip pc++ at the end of the loop
- continue;
- }
- }
- else {
- // just a normal character
- curField += *pc;
- }
- break;
-
- case wxT('\0'):
- cont = FALSE; // end of line reached, exit the loop
-
- // fall through
-
- case wxT(';'):
- // store this field and start looking for the next one
-
- // trim whitespaces from both sides
- curField.Trim(TRUE).Trim(FALSE);
-
- switch ( currentToken ) {
- case Field_Type:
- strType = curField;
- if ( strType.empty() ) {
- // I don't think that this is a valid mailcap
- // entry, but try to interpret it somehow
- strType = _T('*');
- }
-
- if ( strType.Find(wxT('/')) == wxNOT_FOUND ) {
- // we interpret "type" as "type/*"
- strType += wxT("/*");
- }
-
- currentToken = Field_OpenCmd;
- break;
-
- case Field_OpenCmd:
- strOpenCmd = curField;
- entry = new wxMimeArrayString ();
- entry->Add(wxT("open=") + strOpenCmd);
-
- currentToken = Field_Other;
- break;
-
- case Field_Other:
- if ( !curField.empty() ) {
- // "good" mailcap entry?
- bool ok = TRUE;
-
- if ( IsKnownUnimportantField(curField) ) ok = FALSE;
-
- // is this something of the form foo=bar?
- const wxChar *pEq = wxStrchr(curField, wxT('='));
- if (ok)
- {
- if ( pEq != NULL )
- {
- wxString lhs = curField.BeforeFirst(wxT('=')),
- rhs = curField.AfterFirst(wxT('='));
-
- lhs.Trim(TRUE); // from right
- rhs.Trim(FALSE); // from left
-
- // it might be quoted
- if ( rhs[0u] == wxT('"') && rhs.Last() == wxT('"') )
- {
- wxString sTmp = wxString(rhs.c_str() + 1, rhs.Len() - 2);
- rhs = sTmp;
- }
- bool verbfound = TRUE;
- if ( lhs.Contains (wxT("test")))
- {
- if ( ! rhs.IsEmpty() )
- {
- if ( wxSystem(rhs) == 0 ) {
- // ok, test passed
- test_passed = TRUE;
- wxLogTrace(TRACE_MIME,
- wxT("Test '%s' for mime type '%s' succeeded."),
- rhs.c_str(), strType.c_str());
-
- }
- else {
- test_passed = FALSE;
- wxLogTrace(TRACE_MIME,
- wxT("Test '%s' for mime type '%s' failed."),
- rhs.c_str(), strType.c_str());
- }
- }
- verbfound = FALSE;
- }
- if ( lhs.Contains (wxT("desc")))
- {
- strDesc = rhs;
- verbfound = FALSE;
- }
- if ( lhs.Contains (wxT("x11-bitmap")))
- {
- strIcon = rhs;
- verbfound = FALSE;
- }
- if ( lhs.Contains (wxT("notes")))
- {
- // ignore
- verbfound = FALSE;
- }
- if (verbfound) entry->Add ( lhs + wxT('=') + rhs );
- ok = TRUE;
- }
- else
- {
- // no, it's a simple flag
- if ( curField == wxT("needsterminal") ) {
- needsterminal = TRUE;
- ok = TRUE;
- }
- if ( curField == wxT("copiousoutput")) {
- // copiousoutput impies that the
- // viewer is a console program
- needsterminal =
- copiousoutput =
- ok = TRUE;
-
- if ( !ok )
- {
- // don't flood the user with error
- // messages if we don't understand
- // something in his mailcap, but give
- // them in debug mode because this might
- // be useful for the programmer
- wxLogDebug
- (
- wxT("Mailcap file %s, line %d: "
- "unknown field '%s' for the "
- "MIME type '%s' ignored."),
- strFileName.c_str(),
- nLine + 1,
- curField.c_str(),
- strType.c_str()
- );
-
- }
-
- }
-
- }
-
- }
-
- }
-
-
- // it already has this value
- //currentToken = Field_Other;
- break;
-
- default:
- wxFAIL_MSG(wxT("unknown field type in mailcap"));
- }
-
- // next token starts immediately after ';'
- curField.Empty();
- break;
-
- default:
- curField += *pc;
- }
-
- // continue in the same line
- pc++;
- }
-
- // check that we really read something reasonable
- if ( currentToken == Field_Type || currentToken == Field_OpenCmd ) {
- wxLogWarning(_("Mailcap file %s, line %d: incomplete entry "
- "ignored."),
- strFileName.c_str(), nLine + 1);
- }
- else {
- // support for flags:
- // 1. create an xterm for 'needsterminal'
- // 2. append "| $PAGER" for 'copiousoutput'
- //
- // Note that the RFC says that having both needsterminal and
- // copiousoutput is probably a mistake, so it seems that running
- // programs with copiousoutput inside an xterm as it is done now
- // is a bad idea (FIXME)
- if ( copiousoutput )
- {
- const wxChar *p = wxGetenv(_T("PAGER"));
- strOpenCmd << _T(" | ") << (p ? p : _T("more"));
- wxLogTrace(TRACE_MIME, wxT("Replacing .(for pager)...") + entry->Item(0u) + wxT("with") + strOpenCmd );
-
- entry->ReplaceOrAddLineCmd (wxString(wxT("open")), strOpenCmd );
- }
-
- if ( needsterminal )
- {
- strOpenCmd.Printf(_T("xterm -e sh -c '%s'"), strOpenCmd.c_str());
- wxLogTrace(TRACE_MIME, wxT("Replacing .(for needs term)...") + entry->Item(0u) + wxT("with") + strOpenCmd );
-
- entry->ReplaceOrAddLineCmd (wxString(wxT("open")), strOpenCmd );
- }
-
- // NB: because of complications below (we must get entries priority
- // right), we can't use AddMailcapInfo() here, unfortunately.
- if ( test_passed )
- {
- strType.MakeLower();
- bool overwrite = TRUE;
- int entryIndex ;
- if (fallback)
- overwrite = FALSE;
- else
- {
- int nIndex = m_aTypes.Index(strType);
- entryIndex = aEntryIndices.Index(nIndex);
- if ( entryIndex == wxNOT_FOUND )
- {
- //check this fix
- // first time in this file, so replace the icons, entries
- // and description (no extensions to replace so ignore these
- overwrite = TRUE;
- aEntryIndices.Add(nIndex);
- //aLastIndices.Add(0);
- }
- else {
- // not the first time in _this_ file
- // so we don't want to overwrite
- // existing entries,but want to add to them
- // so we don't alter the mimetype
- // the indices were shifted by 1
- overwrite = FALSE;
- }
-
-
- }
- wxArrayString strExtensions;
- AddToMimeData (strType, strIcon, entry, strExtensions, strDesc, !overwrite );
- test_passed = TRUE;
- }
- }
-
- }
-
- return TRUE;