+ return true;
+}
+
+// set an arbitrary command:
+// could adjust the code to ask confirmation if it already exists and
+// overwriteprompt is true, but this is currently ignored as *Associate* has
+// no overwrite prompt
+bool
+wxFileTypeImpl::SetCommand(const wxString& cmd,
+ const wxString& verb,
+ bool WXUNUSED(overwriteprompt))
+{
+ wxArrayString strExtensions;
+ wxString strDesc, strIcon;
+
+ wxArrayString strTypes;
+ GetMimeTypes(strTypes);
+ if ( strTypes.IsEmpty() )
+ return false;
+
+ wxMimeTypeCommands *entry = new wxMimeTypeCommands();
+ entry->Add(verb + wxT("=") + cmd + wxT(" %s "));
+
+ bool ok = false;
+ size_t nCount = strTypes.GetCount();
+ for ( size_t i = 0; i < nCount; i++ )
+ {
+ if ( m_manager->DoAssociation
+ (
+ strTypes[i],
+ strIcon,
+ entry,
+ strExtensions,
+ strDesc
+ ) )
+ {
+ // DoAssociation() took ownership of entry, don't delete it below
+ ok = true;
+ }
+ }
+
+ if ( !ok )
+ delete entry;
+
+ return ok;
+}
+
+// ignore index on the grounds that we only have one icon in a Unix file
+bool wxFileTypeImpl::SetDefaultIcon(const wxString& strIcon, int WXUNUSED(index))
+{
+ if (strIcon.empty())
+ return false;
+
+ wxArrayString strExtensions;
+ wxString strDesc;
+
+ wxArrayString strTypes;
+ GetMimeTypes(strTypes);
+ if ( strTypes.IsEmpty() )
+ return false;
+
+ wxMimeTypeCommands *entry = new wxMimeTypeCommands();
+ bool ok = false;
+ size_t nCount = strTypes.GetCount();
+ for ( size_t i = 0; i < nCount; i++ )
+ {
+ if ( m_manager->DoAssociation
+ (
+ strTypes[i],
+ strIcon,
+ entry,
+ strExtensions,
+ strDesc
+ ) )
+ {
+ // we don't need to free entry now, DoAssociation() took ownership
+ // of it
+ ok = true;
+ }
+ }
+
+ if ( !ok )
+ delete entry;
+
+ return ok;
+}
+
+// ----------------------------------------------------------------------------
+// wxMimeTypesManagerImpl (Unix)
+// ----------------------------------------------------------------------------
+
+wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
+{
+ m_initialized = false;
+ m_mailcapStylesInited = 0;
+}
+
+void wxMimeTypesManagerImpl::InitIfNeeded()
+{
+ if ( !m_initialized )
+ {
+ // set the flag first to prevent recursion
+ m_initialized = true;
+
+ wxString wm = wxTheApp->GetTraits()->GetDesktopEnvironment();
+
+ if (wm == wxT("KDE"))
+ Initialize( wxMAILCAP_KDE );
+ else if (wm == wxT("GNOME"))
+ Initialize( wxMAILCAP_GNOME );
+ else
+ Initialize();
+ }
+}
+
+// read system and user mailcaps and other files
+void wxMimeTypesManagerImpl::Initialize(int mailcapStyles,
+ const wxString& sExtraDir)
+{
+ // read mimecap amd mime.types
+ if ( (mailcapStyles & wxMAILCAP_NETSCAPE) ||
+ (mailcapStyles & wxMAILCAP_STANDARD) )
+ GetMimeInfo(sExtraDir);
+
+ // read GNOME tables
+ if (mailcapStyles & wxMAILCAP_GNOME)
+ GetGnomeMimeInfo(sExtraDir);
+
+ // read KDE tables which are never installed on OpenVMS
+#ifndef __VMS
+ if (mailcapStyles & wxMAILCAP_KDE)
+ GetKDEMimeInfo(sExtraDir);
+#endif
+
+ m_mailcapStylesInited |= mailcapStyles;
+}
+
+// clear data so you can read another group of WM files
+void wxMimeTypesManagerImpl::ClearData()
+{
+ m_aTypes.Clear();
+ m_aIcons.Clear();
+ m_aExtensions.Clear();
+ m_aDescriptions.Clear();
+
+ WX_CLEAR_ARRAY(m_aEntries);
+ m_aEntries.Empty();
+
+ m_mailcapStylesInited = 0;
+}
+
+wxMimeTypesManagerImpl::~wxMimeTypesManagerImpl()
+{
+ ClearData();
+}
+
+void wxMimeTypesManagerImpl::GetMimeInfo(const wxString& sExtraDir)
+{
+ // read this for netscape or Metamail formats
+
+ // directories where we look for mailcap and mime.types by default
+ // used by netscape and pine and other mailers, using 2 different formats!
+
+ // (taken from metamail(1) sources)
+ //
+ // although RFC 1524 specifies the search path of
+ // /etc/:/usr/etc:/usr/local/etc only, it doesn't hurt to search in more
+ // places - OTOH, the RFC also says that this path can be changed with
+ // MAILCAPS environment variable (containing the colon separated full
+ // filenames to try) which is not done yet (TODO?)
+
+ wxString strHome = wxGetenv(wxT("HOME"));
+
+ wxArrayString dirs;
+ dirs.Add( strHome + wxT("/.") );
+ dirs.Add( wxT("/etc/") );
+ dirs.Add( wxT("/usr/etc/") );
+ dirs.Add( wxT("/usr/local/etc/") );
+ dirs.Add( wxT("/etc/mail/") );
+ dirs.Add( wxT("/usr/public/lib/") );
+ if (!sExtraDir.empty())
+ dirs.Add( sExtraDir + wxT("/") );
+
+ wxString file;
+ size_t nDirs = dirs.GetCount();
+ for ( size_t nDir = 0; nDir < nDirs; nDir++ )
+ {
+ file = dirs[nDir];
+ file += wxT("mailcap");
+ if ( wxFile::Exists(file) )
+ {
+ ReadMailcap(file);
+ }
+
+ file = dirs[nDir];
+ file += wxT("mime.types");
+ if ( wxFile::Exists(file) )
+ ReadMimeTypes(file);
+ }
+}
+
+bool wxMimeTypesManagerImpl::WriteToMimeTypes(int index, bool delete_index)
+{
+ // check we have the right manager
+ if (! ( m_mailcapStylesInited & wxMAILCAP_STANDARD) )
+ return false;
+
+ bool bTemp;
+ wxString strHome = wxGetenv(wxT("HOME"));
+
+ // and now the users mailcap
+ wxString strUserMailcap = strHome + wxT("/.mime.types");
+
+ wxMimeTextFile file;
+ if ( wxFile::Exists(strUserMailcap) )
+ {
+ bTemp = file.Open(strUserMailcap);
+ }
+ else
+ {
+ if (delete_index)
+ return false;
+
+ bTemp = file.Create(strUserMailcap);
+ }
+
+ if (bTemp)
+ {
+ int nIndex;
+ // test for netscape's header and return false if its found
+ nIndex = file.pIndexOf(wxT("#--Netscape"));
+ if (nIndex != wxNOT_FOUND)
+ {
+ wxFAIL_MSG(wxT("Error in .mime.types\nTrying to mix Netscape and Metamail formats\nFile not modified"));
+ return false;
+ }
+
+ // write it in alternative format
+ // get rid of unwanted entries
+ wxString strType = m_aTypes[index];
+ nIndex = file.pIndexOf(strType);
+
+ // get rid of all the unwanted entries...
+ if (nIndex != wxNOT_FOUND)
+ file.CommentLine(nIndex);
+
+ if (!delete_index)
+ {
+ // add the new entries in
+ wxString sTmp = strType.Append( wxT(' '), 40 - strType.Len() );
+ sTmp += m_aExtensions[index];
+ file.AddLine(sTmp);
+ }
+
+ bTemp = file.Write();
+ file.Close();
+ }
+
+ return bTemp;
+}
+
+bool wxMimeTypesManagerImpl::WriteToNSMimeTypes(int index, bool delete_index)
+{
+ //check we have the right managers
+ if (! ( m_mailcapStylesInited & wxMAILCAP_NETSCAPE) )
+ return false;
+
+ bool bTemp;
+ wxString strHome = wxGetenv(wxT("HOME"));
+
+ // and now the users mailcap
+ wxString strUserMailcap = strHome + wxT("/.mime.types");
+
+ wxMimeTextFile file;
+ if ( wxFile::Exists(strUserMailcap) )
+ {
+ bTemp = file.Open(strUserMailcap);
+ }
+ else
+ {
+ if (delete_index)
+ return false;
+
+ bTemp = file.Create(strUserMailcap);
+ }
+
+ if (bTemp)
+ {
+ // write it in the format that Netscape uses
+ int nIndex;
+ // test for netscape's header and insert if required...
+ // this is a comment so use true
+ nIndex = file.pIndexOf(wxT("#--Netscape"), true);
+ if (nIndex == wxNOT_FOUND)
+ {
+ // either empty file or metamail format
+ // at present we can't cope with mixed formats, so exit to preseve
+ // metamail entreies
+ if (file.GetLineCount() > 0)
+ {
+ wxFAIL_MSG(wxT(".mime.types File not in Netscape format\nNo entries written to\n.mime.types or to .mailcap"));
+ return false;
+ }
+
+ file.InsertLine(wxT( "#--Netscape Communications Corporation MIME Information" ), 0);
+ nIndex = 0;
+ }
+
+ wxString strType = wxT("type=") + m_aTypes[index];
+ nIndex = file.pIndexOf(strType);
+
+ // get rid of all the unwanted entries...
+ if (nIndex != wxNOT_FOUND)
+ {
+ wxString sOld = file[nIndex];
+ while ( (sOld.Contains(wxT("\\"))) && (nIndex < (int) file.GetLineCount()) )
+ {
+ file.CommentLine(nIndex);
+ sOld = file[nIndex];
+
+ wxLogTrace(TRACE_MIME, wxT("--- Deleting from mime.types line '%d %s' ---"), nIndex, sOld.c_str());
+
+ nIndex++;
+ }
+
+ if (nIndex < (int) file.GetLineCount())
+ file.CommentLine(nIndex);
+ }
+ else
+ nIndex = (int) file.GetLineCount();
+
+ wxString sTmp = strType + wxT(" \\");
+ if (!delete_index)
+ file.InsertLine(sTmp, nIndex);
+
+ if ( ! m_aDescriptions.Item(index).empty() )
+ {
+ sTmp = wxT("desc=\"") + m_aDescriptions[index]+ wxT("\" \\"); //.trim ??
+ if (!delete_index)
+ {
+ nIndex++;
+ file.InsertLine(sTmp, nIndex);
+ }
+ }
+
+ wxString sExts = m_aExtensions.Item(index);
+ sTmp = wxT("exts=\"") + sExts.Trim(false).Trim() + wxT("\"");
+ if (!delete_index)
+ {
+ nIndex++;
+ file.InsertLine(sTmp, nIndex);
+ }
+
+ bTemp = file.Write();
+ file.Close();
+ }
+
+ return bTemp;
+}
+
+bool wxMimeTypesManagerImpl::WriteToMailCap(int index, bool delete_index)
+{
+ //check we have the right managers
+ if ( !( ( m_mailcapStylesInited & wxMAILCAP_NETSCAPE) ||
+ ( m_mailcapStylesInited & wxMAILCAP_STANDARD) ) )
+ return false;
+
+ bool bTemp = false;
+ wxString strHome = wxGetenv(wxT("HOME"));
+
+ // and now the users mailcap
+ wxString strUserMailcap = strHome + wxT("/.mailcap");
+
+ wxMimeTextFile file;
+ if ( wxFile::Exists(strUserMailcap) )
+ {
+ bTemp = file.Open(strUserMailcap);
+ }
+ else
+ {
+ if (delete_index)
+ return false;
+
+ bTemp = file.Create(strUserMailcap);
+ }
+
+ if (bTemp)
+ {
+ // now got a file we can write to ....
+ wxMimeTypeCommands * entries = m_aEntries[index];
+ size_t iOpen;
+ wxString sCmd = entries->GetCommandForVerb(wxT("open"), &iOpen);
+ wxString sTmp;
+
+ sTmp = m_aTypes[index];
+ wxString sOld;
+ int nIndex = file.pIndexOf(sTmp);
+
+ // get rid of all the unwanted entries...
+ if (nIndex == wxNOT_FOUND)
+ {
+ nIndex = (int) file.GetLineCount();
+ }
+ else
+ {
+ sOld = file[nIndex];
+ wxLogTrace(TRACE_MIME, wxT("--- Deleting from mailcap line '%d' ---"), nIndex);
+
+ while ( (sOld.Contains(wxT("\\"))) && (nIndex < (int) file.GetLineCount()) )
+ {
+ file.CommentLine(nIndex);
+ if (nIndex < (int) file.GetLineCount())
+ sOld = sOld + file[nIndex];
+ }
+
+ if (nIndex < (int)
+ file.GetLineCount()) file.CommentLine(nIndex);
+ }
+
+ sTmp += wxT(";") + sCmd; //includes wxT(" %s ");
+
+ // write it in the format that Netscape uses (default)
+ if (! ( m_mailcapStylesInited & wxMAILCAP_STANDARD ) )
+ {
+ if (! delete_index)
+ file.InsertLine(sTmp, nIndex);
+ nIndex++;
+ }
+ else
+ {
+ // write extended format
+
+ // TODO - FIX this code:
+ // ii) lost entries
+ // sOld holds all the entries, but our data store only has some
+ // eg test= is not stored
+
+ // so far we have written the mimetype and command out
+ wxStringTokenizer sT(sOld, wxT(";\\"));
+ if (sT.CountTokens() > 2)
+ {
+ // first one mimetype; second one command, rest unknown...
+ wxString s;
+ s = sT.GetNextToken();
+ s = sT.GetNextToken();
+
+ // first unknown
+ s = sT.GetNextToken();
+ while ( ! s.empty() )
+ {
+ bool bKnownToken = false;
+ if (s.Contains(wxT("description=")))
+ bKnownToken = true;
+ if (s.Contains(wxT("x11-bitmap=")))
+ bKnownToken = true;
+
+ size_t i;
+ size_t nCount = entries->GetCount();
+ for (i=0; i < nCount; i++)
+ {
+ if (s.Contains(entries->GetVerb(i)))
+ bKnownToken = true;
+ }
+
+ if (!bKnownToken)
+ {
+ sTmp += wxT("; \\");
+ file.InsertLine(sTmp, nIndex);
+ sTmp = s;
+ }
+
+ s = sT.GetNextToken();
+ }
+ }
+
+ if (! m_aDescriptions[index].empty() )
+ {
+ sTmp += wxT("; \\");
+ file.InsertLine(sTmp, nIndex);
+ nIndex++;
+ sTmp = wxT(" description=\"") + m_aDescriptions[index] + wxT("\"");
+ }
+
+ if (! m_aIcons[index].empty() )
+ {
+ sTmp += wxT("; \\");
+ file.InsertLine(sTmp, nIndex);
+ nIndex++;
+ sTmp = wxT(" x11-bitmap=\"") + m_aIcons[index] + wxT("\"");
+ }
+
+ if ( entries->GetCount() > 1 )
+ {
+ size_t i;
+ for (i=0; i < entries->GetCount(); i++)
+ if ( i != iOpen )
+ {
+ sTmp += wxT("; \\");
+ file.InsertLine(sTmp, nIndex);
+ nIndex++;
+ sTmp = wxT(" ") + entries->GetVerbCmd(i);
+ }
+ }
+
+ file.InsertLine(sTmp, nIndex);
+ nIndex++;
+ }
+
+ bTemp = file.Write();
+ file.Close();
+ }
+
+ return bTemp;
+}
+
+wxFileType * wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& ftInfo)
+{
+ InitIfNeeded();
+
+ wxString strType = ftInfo.GetMimeType();
+ wxString strDesc = ftInfo.GetDescription();
+ wxString strIcon = ftInfo.GetIconFile();
+
+ wxMimeTypeCommands *entry = new wxMimeTypeCommands();
+
+ if ( ! ftInfo.GetOpenCommand().empty())
+ entry->Add(wxT("open=") + ftInfo.GetOpenCommand() + wxT(" %s "));
+ if ( ! ftInfo.GetPrintCommand().empty())
+ entry->Add(wxT("print=") + ftInfo.GetPrintCommand() + wxT(" %s "));
+
+ // now find where these extensions are in the data store and remove them
+ wxArrayString sA_Exts = ftInfo.GetExtensions();
+ wxString sExt, sExtStore;
+ size_t i, nIndex;
+ size_t nExtCount = sA_Exts.GetCount();
+ for (i=0; i < nExtCount; i++)
+ {
+ sExt = sA_Exts.Item(i);
+
+ // clean up to just a space before and after
+ sExt.Trim().Trim(false);
+ sExt = wxT(' ') + sExt + wxT(' ');
+ size_t nCount = m_aExtensions.GetCount();
+ for (nIndex = 0; nIndex < nCount; nIndex++)
+ {
+ sExtStore = m_aExtensions.Item(nIndex);
+ if (sExtStore.Replace(sExt, wxT(" ") ) > 0)
+ m_aExtensions.Item(nIndex) = sExtStore;
+ }
+ }
+
+ if ( !DoAssociation(strType, strIcon, entry, sA_Exts, strDesc) )
+ return NULL;
+
+ return GetFileTypeFromMimeType(strType);