wxFileType *GetFileTypeFromMimeType(const wxString& mimeType);
// this are NOPs under Windows
- void ReadMailcap(const wxString& filename) { }
- void ReadMimeTypes(const wxString& filename) { }
+ bool ReadMailcap(const wxString& filename, bool fallback = TRUE)
+ { return TRUE; }
+ bool ReadMimeTypes(const wxString& filename)
+ { return TRUE; }
};
#else // Unix
// operations
// prepend this element to the list
void Prepend(MailCapEntry *next) { m_next = next; }
- // append to the list
+ // insert into the list at given position
+ void Insert(MailCapEntry *next, size_t pos)
+ {
+ // FIXME slooow...
+ MailCapEntry *cur;
+ size_t n = 0;
+ for ( cur = next; cur != NULL; cur = cur->m_next, n++ ) {
+ if ( n == pos )
+ break;
+ }
+
+ wxASSERT_MSG( n == pos, "invalid position in MailCapEntry::Insert" );
+
+ m_next = cur->m_next;
+ cur->m_next = this;
+ }
+ // append this element to the list
void Append(MailCapEntry *next)
{
+ wxCHECK_RET( next != NULL, "Append()ing to what?" );
+
// FIXME slooow...
MailCapEntry *cur;
for ( cur = next; cur->m_next != NULL; cur = cur->m_next )
cur->m_next = this;
- // we initialize it in the ctor and there is no reason to both Prepend()
- // and Append() one and the same entry
- wxASSERT( m_next == NULL );
+ wxASSERT_MSG( !m_next, "Append()ing element already in the list?" );
}
private:
public:
// ctor loads all info into memory for quicker access later on
- // @@ it would be nice to load them all, but parse on demand only...
+ // TODO it would be nice to load them all, but parse on demand only...
wxMimeTypesManagerImpl();
// implement containing class functions
wxFileType *GetFileTypeFromExtension(const wxString& ext);
wxFileType *GetFileTypeFromMimeType(const wxString& mimeType);
- void ReadMailcap(const wxString& filename);
- void ReadMimeTypes(const wxString& filename);
+ bool ReadMailcap(const wxString& filename, bool fallback = FALSE);
+ bool ReadMimeTypes(const wxString& filename);
// accessors
// get the string containing space separated extensions for the given
bool GetExtensions(wxArrayString& extensions);
bool GetMimeType(wxString *mimeType) const
{ *mimeType = m_manager->m_aTypes[m_index]; return TRUE; }
- bool GetIcon(wxIcon *icon) const
- { return FALSE; } // @@ maybe with Gnome/KDE integration...
+ bool GetIcon(wxIcon * WXUNUSED(icon)) const
+ { return FALSE; } // TODO maybe with Gnome/KDE integration...
bool GetDescription(wxString *desc) const
{ *desc = m_manager->m_aDescriptions[m_index]; return TRUE; }
return m_impl->GetFileTypeFromMimeType(mimeType);
}
+bool wxMimeTypesManager::ReadMailcap(const wxString& filename, bool fallback)
+{
+ return m_impl->ReadMailcap(filename, fallback);
+}
+
+bool wxMimeTypesManager::ReadMimeTypes(const wxString& filename)
+{
+ return m_impl->ReadMimeTypes(filename);
+}
+
// ============================================================================
// real (OS specific) implementation
// ============================================================================
// it's the default value of the key
if ( key.QueryValue("", *command) ) {
// transform it from '%1' to '%s' style format string
- // @@ we don't make any attempt to verify that the string is valid,
- // i.e. doesn't contain %2, or second %1 or .... But we do make
- // sure that we return a string with _exactly_ one '%s'!
+ // NB: we don't make any attempt to verify that the string is valid,
+ // i.e. doesn't contain %2, or second %1 or .... But we do make
+ // sure that we return a string with _exactly_ one '%s'!
size_t len = command->Len();
for ( size_t n = 0; n < len; n++ ) {
if ( command->GetChar(n) == '%' &&
}
// we didn't find any '%1'!
- // @@@ hack: append the filename at the end, hope that it will do
+ // HACK: append the filename at the end, hope that it will do
*command << " %s";
return TRUE;
return FALSE;
}
-// @@ this function is half implemented
+// TODO this function is half implemented
bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions)
{
if ( m_ext.IsEmpty() ) {
{
// suppress possible error messages
wxLogNull nolog;
- wxRegKey key(wxRegKey::HKCR, m_strFileType);
+ wxRegKey key(wxRegKey::HKCR, /*m_strFileType*/ "." + m_ext);
if ( key.Open() && key.QueryValue("Content Type", *mimeType) ) {
return TRUE;
}
wxFileType *
wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
{
- // @@@ I don't know of any official documentation which mentions this
- // location, but as a matter of fact IE uses it, so why not we?
+ // HACK I don't know of any official documentation which mentions this
+ // location, but as a matter of fact IE uses it, so why not we?
static const char *szMimeDbase = "MIME\\Database\\Content Type\\";
wxString strKey = szMimeDbase;
wxString command;
MailCapEntry *entry = m_manager->m_aEntries[m_index];
while ( entry != NULL ) {
- // notice that an empty command would always succeed (@@ is it ok?)
+ // notice that an empty command would always succeed (it's ok)
command = wxFileType::ExpandCommand(entry->GetTestCmd(), params);
if ( command.IsEmpty() || (system(command) == 0) ) {
}
}
-void wxMimeTypesManagerImpl::ReadMimeTypes(const wxString& strFileName)
+bool wxMimeTypesManagerImpl::ReadMimeTypes(const wxString& strFileName)
{
wxLogTrace("--- Parsing mime.types file '%s' ---", strFileName.c_str());
wxTextFile file(strFileName);
if ( !file.Open() )
- return;
+ return FALSE;
// the information we extract
wxString strMimeType, strDesc, strExtensions;
size_t nLineCount = file.GetLineCount();
+ const char *pc = NULL;
for ( size_t nLine = 0; nLine < nLineCount; nLine++ ) {
- // now we're at the start of the line
- const char *pc = file[nLine].c_str();
+ 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 ( isspace(*pc) )
pc++;
// comment?
- if ( *pc == '#' )
+ if ( *pc == '#' ) {
+ // skip the whole line
+ pc = NULL;
continue;
+ }
// detect file format
const char *pEqualSign = strchr(pc, '=');
}
}
else {
- // unquoted stringends at the first space
+ // unquoted string ends at the first space
for ( pEnd = pc; !isspace(*pEnd); pEnd++ )
;
}
// now we have the RHS (field value)
wxString strRHS(pc, pEnd - pc);
- // check that it's more or less what we're waiting for, i.e. that
- // only '\' is left on the line
+ // check what follows this entry
if ( *pEnd == '"' ) {
// skip this quote
pEnd++;
for ( pc = pEnd; isspace(*pc); pc++ )
;
- // only '\\' may be left on the line normally
- bool entryEnded = *pc == '\0';
- if ( !entryEnded && ((*pc != '\\') || (*++pc != '\0')) ) {
- wxLogWarning(_("Mime.types file %s, line %d: extra characters "
- "after the field value ignored."),
- strFileName.c_str(), nLine + 1);
+ // 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 == '\0',
+ nextFieldOnSameLine = FALSE;
+ if ( !entryEnded ) {
+ nextFieldOnSameLine = ((*pc != '\\') || (pc[1] != '\0'));
}
- // if there is a trailing backslash entryEnded = FALSE
// now see what we got
if ( strLHS == "type" ) {
}
if ( !entryEnded ) {
- // as we don't reset strMimeType, the next line in this entry
+ 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;
}
}
}
m_aExtensions[index] += strExtensions;
}
+
+ // finished with this line
+ pc = NULL;
}
// check our data integriry
wxASSERT( m_aTypes.Count() == m_aEntries.Count() &&
m_aTypes.Count() == m_aExtensions.Count() &&
m_aTypes.Count() == m_aDescriptions.Count() );
+
+ return TRUE;
}
-void wxMimeTypesManagerImpl::ReadMailcap(const wxString& strFileName)
+bool wxMimeTypesManagerImpl::ReadMailcap(const wxString& strFileName,
+ bool fallback)
{
wxLogTrace("--- Parsing mailcap file '%s' ---", strFileName.c_str());
wxTextFile file(strFileName);
if ( !file.Open() )
- return;
+ return FALSE;
- // see the comments near the end of function for the reason we need this
+ // 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++ ) {
m_aDescriptions.Add(strDesc);
}
else {
- // modify the existing entry: the entry in one and the same file
- // are read in top-to-bottom order, i.e. the entries read first
- // should be tried before the entries below. However, the files
- // read later should override the settings in the files read
- // before, thus we Append() the new entry to the list if it has
- // already occured in _this_ file, but Prepend() it if it
- // occured in some of the previous ones.
- if ( aEntryIndices.Index(nIndex) == wxNOT_FOUND ) {
- // first time in this file
- aEntryIndices.Add(nIndex);
- entry->Prepend(m_aEntries[nIndex]);
- m_aEntries[nIndex] = entry;
+ // modify the existing entry: the entries in one and the same
+ // file are read in top-to-bottom order, i.e. the entries read
+ // first should be tried before the entries below. However,
+ // the files read later should override the settings in the
+ // files read before (except if fallback is TRUE), thus we
+ // Insert() the new entry to the list if it has already
+ // occured in _this_ file, but Prepend() it if it occured in
+ // some of the previous ones and Append() to it in the
+ // fallback case
+
+ if ( fallback ) {
+ // 'fallback' parameter prevents the entries from this
+ // file from overriding the other ones - always append
+ MailCapEntry *entryOld = m_aEntries[nIndex];
+ if ( entryOld )
+ entry->Append(entryOld);
+ else
+ m_aEntries[nIndex] = entry;
}
else {
- // not the first time in _this_ file
- entry->Append(m_aEntries[nIndex]);
+ int entryIndex = aEntryIndices.Index(nIndex);
+ if ( entryIndex == wxNOT_FOUND ) {
+ // first time in this file
+ aEntryIndices.Add(nIndex);
+ aLastIndices.Add(0);
+
+ entry->Prepend(m_aEntries[nIndex]);
+ m_aEntries[nIndex] = entry;
+ }
+ else {
+ // not the first time in _this_ file
+ size_t nEntryIndex = (size_t)entryIndex;
+ MailCapEntry *entryOld = m_aEntries[nIndex];
+ if ( entryOld )
+ entry->Insert(entryOld, aLastIndices[nEntryIndex]);
+ else
+ m_aEntries[nIndex] = entry;
+
+ // the indices were shifted by 1
+ aLastIndices[nEntryIndex]++;
+ }
}
if ( !strDesc.IsEmpty() ) {
- // @@ replace the old one - what else can we do??
+ // replace the old one - what else can we do??
m_aDescriptions[nIndex] = strDesc;
}
}
m_aTypes.Count() == m_aExtensions.Count() &&
m_aTypes.Count() == m_aDescriptions.Count() );
}
+
+ return TRUE;
}
#endif // OS type