From 1ed04c7ce321cd6d04cc7d154ec760e19240fb20 Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Tue, 20 Aug 2002 09:37:04 +0000 Subject: [PATCH] Added code for: + {Get,Set}IconForType() + Delete*() functions git-svn-id: file:///srv/svn/repos/haiku/trunk/current@834 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/storage/MimeType.h | 13 +- headers/private/storage/MimeDatabase.h | 34 +- src/kits/storage/MimeDatabase.cpp | 644 ++++++++++++++----------- src/kits/storage/MimeType.cpp | 231 +++++---- src/servers/registrar/MIMEManager.cpp | 115 ++++- src/servers/registrar/MIMEManager.h | 2 + 6 files changed, 631 insertions(+), 408 deletions(-) diff --git a/headers/os/storage/MimeType.h b/headers/os/storage/MimeType.h index 54e24061f9..3b06574e07 100644 --- a/headers/os/storage/MimeType.h +++ b/headers/os/storage/MimeType.h @@ -147,10 +147,21 @@ public: /* Deprecated Use SetTo instead. */ status_t SetType(const char *mimeType); + /* Brand new Delete() methods */ + status_t DeleteIcon(icon_size size); + status_t DeletePreferredApp(app_verb verb = B_OPEN); + status_t DeleteAttrInfo(); + status_t DeleteFileExtensions(); + status_t DeleteShortDescription(); + status_t DeleteLongDescription(); + status_t DeleteSnifferRule(); + status_t DeleteIconForType(const char *type, icon_size which); + status_t DeleteAppHint(); + private: BMimeType(const char *mimeType, const char *mimePath); // if mimePath is NULL, defaults to "/boot/home/config/settings/beos_mime/" - + friend class MimeTypeTest; // Uncomment, when needed... diff --git a/headers/private/storage/MimeDatabase.h b/headers/private/storage/MimeDatabase.h index 2e0ecb64f7..3114d06a00 100644 --- a/headers/private/storage/MimeDatabase.h +++ b/headers/private/storage/MimeDatabase.h @@ -25,15 +25,15 @@ public: status_t Delete(const char *type); bool IsInstalled(const char *type) const; status_t GetIcon(const char *type, BBitmap *icon, icon_size size) const; - status_t GetPreferredApp(const char *type, char *signature, app_verb verb = B_OPEN) const; + status_t GetPreferredApp(const char *type, char *signature, app_verb verb) const; // status_t GetAttrInfo(BMessage *info) const; // status_t GetFileExtensions(BMessage *extensions) const; status_t GetShortDescription(const char *type, char *description) const; status_t GetLongDescription(const char *type, char *description) const; // status_t GetSupportingApps(BMessage *signatures) const; - status_t SetIcon(const char *type, const BBitmap *icon, icon_size size); - status_t SetIcon(const char *type, icon_size size, const void *data, size_t dataSize); +// status_t SetIcon(const char *type, const BBitmap *icon, icon_size which); + status_t SetIcon(const char *type, const void *data, size_t dataSize, icon_size which); status_t SetPreferredApp(const char *type, const char *signature, app_verb verb = B_OPEN); // status_t SetAttrInfo(const BMessage *info); // status_t SetFileExtensions(const BMessage *extensions); @@ -51,10 +51,10 @@ public: status_t SetAppHint(const char *type, const entry_ref *ref); /* for application signatures only.*/ -// status_t GetIconForType(const char *type, BBitmap *icon, -// icon_size which) const; -// status_t SetIconForType(const char *type, const BBitmap *icon, -// icon_size which); + status_t GetIconForType(const char *type, const char *fileType, BBitmap *icon, + icon_size which) const; + status_t SetIconForType(const char *type, const char *fileType, const void *data, + size_t dataSize, icon_size which); /* sniffer rule manipulation */ // status_t GetSnifferRule(BString *result) const; @@ -73,10 +73,23 @@ public: static status_t GetIconData(const BBitmap *icon, icon_size size, void **data, int32 *dataSize); + status_t DeleteAttribute(const char *type, const char *attr); + + static std::string ToLower(const char *str); + static const char *kDefaultDatabaseDir; + + static const char *kMiniIconAttrPrefix; + static const char *kLargeIconAttrPrefix; + + static const char *kTypeAttr; + static const char *kPreferredAppAttr; + static const char *kAppHintAttr; + static const char *kMiniIconAttr; + static const char *kLargeIconAttr; + static const char *kShortDescriptionAttr; + static const char *kLongDescriptionAttr; private: - static const char *kMiniIconAttribute; - static const char *kLargeIconAttribute; ssize_t ReadMimeAttr(const char *type, const char *attr, void *data, size_t len, type_code datatype) const; @@ -92,6 +105,9 @@ private: status_t SendMonitorUpdate(int32 which, const char *type); status_t SendMonitorUpdate(BMessage &msg); + // General icon functions used by {Get,Set}Icon() and {Get,Set}IconForType() + status_t GetIcon(const char *type, const char *attr, BBitmap *icon, icon_size which) const; + status_t SetIcon(const char *type, const char *attr, const void *data, size_t dataSize, icon_size which); std::string fDatabaseDir; status_t fCStatus; diff --git a/src/kits/storage/MimeDatabase.cpp b/src/kits/storage/MimeDatabase.cpp index 68940359b1..a39554d18a 100644 --- a/src/kits/storage/MimeDatabase.cpp +++ b/src/kits/storage/MimeDatabase.cpp @@ -23,19 +23,6 @@ #define DBG(x) #define OUT printf -// attribute names -#define ATTR_PREFIX "META:" -namespace { - const char *kTypeAttr = ATTR_PREFIX "TYPE"; - const char *kPreferredAppAttr = ATTR_PREFIX "PREF_APP"; - const char *kAppHintAttr = ATTR_PREFIX "PPATH"; - const char *kMiniIconAttr = ATTR_PREFIX "M:STD_ICON"; - const char *kLargeIconAttr = ATTR_PREFIX "L:STD_ICON"; - const char *kShortDescriptionAttr = ATTR_PREFIX "S:DESC"; - const char *kLongDescriptionAttr = ATTR_PREFIX "L:DESC"; -} -#undef ATTR_PREFIX - // icon types enum { B_MINI_ICON_TYPE = 'MICN', @@ -47,9 +34,30 @@ namespace BPrivate { //const char* MimeDatabase::kDefaultDatabaseDir = "/boot/home/config/settings/beos_mime"; const char* MimeDatabase::kDefaultDatabaseDir = "/boot/home/config/settings/obos_mime"; +// attribute names +#define ATTR_PREFIX "META:" +#define MINI_ICON_ATTR_PREFIX ATTR_PREFIX "M:" +#define LARGE_ICON_ATTR_PREFIX ATTR_PREFIX "L:" + +const char *MimeDatabase::kMiniIconAttrPrefix = MINI_ICON_ATTR_PREFIX; +const char *MimeDatabase::kLargeIconAttrPrefix = LARGE_ICON_ATTR_PREFIX; + +const char *MimeDatabase::kTypeAttr = ATTR_PREFIX "TYPE"; +const char *MimeDatabase::kPreferredAppAttr = ATTR_PREFIX "PREF_APP"; +const char *MimeDatabase::kAppHintAttr = ATTR_PREFIX "PPATH"; +const char *MimeDatabase::kMiniIconAttr = MINI_ICON_ATTR_PREFIX "STD_ICON"; +const char *MimeDatabase::kLargeIconAttr = LARGE_ICON_ATTR_PREFIX "STD_ICON"; +const char *MimeDatabase::kShortDescriptionAttr = ATTR_PREFIX "S:DESC"; +const char *MimeDatabase::kLongDescriptionAttr = ATTR_PREFIX "L:DESC"; + +#undef ATTR_PREFIX +#undef MINI_ICON_ATTR_PREFIX +#undef LARGE_ICON_ATTR_PREFIX + //! Converts every character in \c str to lowercase and returns the result std::string -to_lower(const char *str) { +MimeDatabase::ToLower(const char *str) +{ if (str) { std::string result = ""; for (int i = 0; i < strlen(str); i++) @@ -169,78 +177,14 @@ MimeDatabase::IsInstalled(const char *type) const \param size The size icon you're interested in (\c B_LARGE_ICON or \c B_MINI_ICON) */ status_t -MimeDatabase::GetIcon(const char *type, BBitmap *icon, icon_size size) const +MimeDatabase::GetIcon(const char *type, BBitmap *icon, icon_size which) const { - attr_info info; - ssize_t err; - BNode node; - std::string attr; - uint32 attrType; - size_t attrSize; - BRect bounds; - char *buffer; - - err = type && icon ? B_OK : B_BAD_VALUE; - - // Figure out what kind of data we *should* find - if (!err) { - switch (size) { - case B_MINI_ICON: - attr = kMiniIconAttr; - bounds.Set(0, 0, 15, 15); - attrType = B_MINI_ICON_TYPE; - attrSize = 16 * 16; - break; - case B_LARGE_ICON: - attr = kLargeIconAttr; - bounds.Set(0, 0, 31, 31); - attrType = B_LARGE_ICON_TYPE; - attrSize = 32 * 32; - break; - default: - err = B_BAD_VALUE; - break; - } - } - // Check the icon and attribute to see if they match - if (!err) - err = (icon->InitCheck() == B_OK && icon->Bounds() == bounds) ? B_OK : B_BAD_VALUE; - if (!err) - err = OpenType(type, &node); - if (!err) - err = node.GetAttrInfo(attr.c_str(), &info); - if (!err) - err = (attrType == info.type && attrSize == info.size) ? B_OK : B_BAD_VALUE; - // read the attribute - if (!err) { - bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); - char *buffer = NULL; - ssize_t read; - if (otherColorSpace) { - // other color space than stored in attribute - buffer = new(nothrow) char[attrSize]; - if (!buffer) - err = B_NO_MEMORY; - if (!err) - err = node.ReadAttr(attr.c_str(), attrType, 0, buffer, attrSize); - } else { - // same color space, just read direct - err = node.ReadAttr(attr.c_str(), attrType, 0, icon->Bits(), attrSize); - } - if (err >= 0) - err = (err == attrSize) ? B_OK : B_FILE_ERROR; - if (otherColorSpace) { - if (!err) { - icon->SetBits(buffer, attrSize, 0, B_CMAP8); - err = icon->InitCheck(); - } - delete[] buffer; - } - } - - return err; + const char *attr = (which == B_MINI_ICON) ? kMiniIconAttr : kLargeIconAttr; + return GetIcon(type, attr, icon, which); } + + // GetPreferredApp //! Fetches signature of the MIME type's preferred application for the given action. /*! The string pointed to by \c signature must be long enough to @@ -316,110 +260,6 @@ MimeDatabase::GetLongDescription(const char *type, char *description) const { return err >= 0 ? B_OK : err ; } -// GetIconData -/*! \brief Returns properly formatted raw bitmap data, ready to be shipped off to the hacked - up 4-parameter version of MimeDatabase::SetIcon() - - This function exists as something of a hack until an OBOS::BBitmap implementation is - available. It takes the given bitmap, converts it to the B_CMAP8 color space if necessary - and able, and returns said bitmap data in a newly allocated array pointed to by the - pointer that's pointed to by \c data. The length of the array is stored in the integer - pointed to by \c dataSize. The array is allocated with \c new[], and it's your responsibility - to \c delete[] it when you're finished. - -*/ -status_t -MimeDatabase::GetIconData(const BBitmap *icon, icon_size size, void **data, int32 *dataSize) -{ - ssize_t err = (icon && data && size && icon->InitCheck() == B_OK) ? B_OK : B_BAD_VALUE; - - BRect bounds; - const char *attr = (size == B_MINI_ICON) ? kMiniIconAttr : kLargeIconAttr; - int32 attrType; - int32 attrSize; - - BBitmap *icon8 = NULL; - void *srcData = NULL; - bool otherColorSpace = false; - - // Figure out what kind of data we *should* have - if (!err) { - switch (size) { - case B_MINI_ICON: - bounds.Set(0, 0, 15, 15); - attrType = B_MINI_ICON_TYPE; - attrSize = 16 * 16; - break; - case B_LARGE_ICON: - bounds.Set(0, 0, 31, 31); - attrType = B_LARGE_ICON_TYPE; - attrSize = 32 * 32; - break; - default: - err = B_BAD_VALUE; - break; - } - } - // Check the icon - if (!err) - err = (icon->Bounds() == bounds) ? B_OK : B_BAD_VALUE; - // Convert to B_CMAP8 if necessary - if (!err) { - otherColorSpace = (icon->ColorSpace() != B_CMAP8); - if (otherColorSpace) { - icon8 = new BBitmap(bounds, B_CMAP8); - if (!icon8) - err = B_NO_MEMORY; - if (!err) { - switch (icon->ColorSpace()) { - case B_RGB32: - { - // Set each pixel individually, since SetBits() for B_RGB32 takes - // 24-bit rgb pixel data... - char *bgra = (char*)icon->Bits(); - for (uint32 i = 0; i*4+3 < icon->BitsLength(); bgra += 4, i++) { - char rgb[3]; - rgb[0] = bgra[2]; // red - rgb[1] = bgra[1]; // green - rgb[2] = bgra[0]; // blue - icon8->SetBits(rgb, 3, i, B_RGB32); - } - break; - } - case B_GRAY1: - { - icon8->SetBits(icon->Bits(), icon->BitsLength(), 0, B_GRAY1); - break; - } - default: - err = B_BAD_VALUE; - } - if (!err) - err = icon8->InitCheck(); // I don't think this is actually useful, even if SetBits() fails... - } - if (!err) { - srcData = icon8->Bits(); - *dataSize = icon8->BitsLength(); - } - } else { - srcData = icon->Bits(); - *dataSize = icon->BitsLength(); - } - } - // Alloc a new data buffer - if (!err) { - *data = new char[*dataSize]; - if (!*data) - err = B_NO_MEMORY; - } - // Copy the data into it. - if (!err) - memcpy(*data, srcData, *dataSize); - if (otherColorSpace) - delete icon8; - return err; -} - //! Sets the icon for the given mime type /*! This is the version I would have used if I could have gotten a BBitmap to the registrar somehow. Since R5::BBitmap::Instantiate is causing a @@ -431,115 +271,12 @@ MimeDatabase::GetIconData(const BBitmap *icon, icon_size size, void **data, int3 I'll add some real documentation. */ status_t -MimeDatabase::SetIcon(const char *type, const BBitmap *icon, icon_size size) +MimeDatabase::SetIcon(const char *type, const void *data, size_t dataSize, icon_size which) { - printf("REG_MIME\n"); - ssize_t err = (type && icon && icon->InitCheck() == B_OK) ? B_OK : B_BAD_VALUE; - - BRect bounds; - const char *attr = (size == B_MINI_ICON) ? kMiniIconAttr : kLargeIconAttr; - int32 attrType; - int32 attrSize; - - BBitmap *icon8 = NULL; - void *data = NULL; - bool otherColorSpace = false; - - // Figure out what kind of data we *should* have - if (!err) { - switch (size) { - case B_MINI_ICON: - bounds.Set(0, 0, 15, 15); - attrType = B_MINI_ICON_TYPE; - attrSize = 16 * 16; - break; - case B_LARGE_ICON: - bounds.Set(0, 0, 31, 31); - attrType = B_LARGE_ICON_TYPE; - attrSize = 32 * 32; - break; - default: - err = B_BAD_VALUE; - break; - } - } - // Check the icon - if (!err) - err = (icon->Bounds() == bounds) ? B_OK : B_BAD_VALUE; - // Convert to B_CMAP8 if necessary - if (!err) { - otherColorSpace = (icon->ColorSpace() != B_CMAP8); - if (otherColorSpace) { - icon8 = new BBitmap(bounds, B_CMAP8); - if (!icon8) - err = B_NO_MEMORY; - if (!err) { - icon8->SetBits(icon->Bits(), icon->BitsLength(), 0, icon->ColorSpace()); - err = icon8->InitCheck(); - } - if (!err) - data = icon8->Bits(); - } else - data = icon->Bits(); - } - // Write the icon data - BNode node; - if (!err) - err = OpenOrCreateType(type, &node); - if (!err) - err = node.WriteAttr(attr, attrType, 0, data, attrSize); - if (err >= 0) - err = (err == attrSize) ? B_OK : B_FILE_ERROR; - if (otherColorSpace) - delete icon8; - return err; + const char *attr = (which == B_MINI_ICON) ? kMiniIconAttr : kLargeIconAttr; + return SetIcon(type, attr, data, dataSize, which); } -//! Sets the icon for the given mime type -/*! This is a hacked up temporary version of this function that we'll use until - we have a sufficiently complete OBOS::BBitmap implementation. -*/ -status_t -MimeDatabase::SetIcon(const char *type, icon_size size, const void *data, size_t dataSize) -{ - ssize_t err = (type && data) ? B_OK : B_BAD_VALUE; - - const char *attr = (size == B_MINI_ICON) ? kMiniIconAttr : kLargeIconAttr; - int32 attrType; - int32 attrSize; - - // Figure out what kind of data we *should* have - if (!err) { - switch (size) { - case B_MINI_ICON: - attrType = B_MINI_ICON_TYPE; - attrSize = 16 * 16; - break; - case B_LARGE_ICON: - attrType = B_LARGE_ICON_TYPE; - attrSize = 32 * 32; - break; - default: - err = B_BAD_VALUE; - break; - } - } - - // Double check the data we've been given - if (!err) - err = (dataSize == attrSize) ? B_OK : B_BAD_VALUE; - - // Write the icon data - BNode node; - if (!err) - err = OpenOrCreateType(type, &node); - if (!err) - err = node.WriteAttr(attr, attrType, 0, data, attrSize); - if (err >= 0) - err = (err == attrSize) ? B_OK : B_FILE_ERROR; - return err; - -} // SetPreferredApp /*! \brief Sets the signature of the preferred application for the given app verb @@ -645,6 +382,74 @@ MimeDatabase::SetAppHint(const char *type, const entry_ref *ref) return err; } +// GetIconForType +/*! \brief Fetches the large or mini icon used by an application of this type for files of the + given type. + + The type of the \c BMimeType object is not required to actually be a subtype of + \c "application/"; that is the intended use however, and calling \c GetIconForType() + on a non-application type will likely return \c B_ENTRY_NOT_FOUND. + + The icon is copied into the \c BBitmap pointed to by \c icon. The bitmap must + be the proper size: \c 32x32 for the large icon, \c 16x16 for the mini icon. + + \param type The MIME type + \param type Pointer to a pre-allocated string containing the MIME type whose + custom icon you wish to fetch. If NULL, works just like GetIcon(). + \param icon Pointer to a pre-allocated \c BBitmap of proper size and colorspace into + which the icon is copied. + \param icon_size Value that specifies which icon to return. Currently \c B_LARGE_ICON + and \c B_MINI_ICON are supported. + \return + - \c B_OK: Success + - \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type + - "error code": Failure + +*/ +status_t +MimeDatabase::GetIconForType(const char *type, const char *fileType, BBitmap *icon, + icon_size which) const +{ + std::string attr = ((which == B_MINI_ICON) + ? kMiniIconAttrPrefix + : kLargeIconAttrPrefix) + + ToLower(fileType); + return GetIcon(type, attr.c_str(), icon, which); +} + +// SetIconForType +/*! \brief Sets the large or mini icon used by an application of this type for + files of the given type. + + The type of the \c BMimeType object is not required to actually be a subtype of + \c "application/"; that is the intended use however, and application-specific + icons are not expected to be present for non-application types. + + The bitmap data pointed to by \c data must be of the proper size (\c 32x32 + for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON) and the proper color + space (B_CMAP8). + + \param type The MIME type + \param fileType The MIME type whose custom icon you wish to set. + \param data Pointer to an array of bitmap data of proper dimensions and color depth + \param dataSize The length of the array pointed to by \c data + \param size The size icon you're expecting (\c B_LARGE_ICON or \c B_MINI_ICON) + \return + - \c B_OK: Success + - "error code": Failure + +*/ +status_t +MimeDatabase::SetIconForType(const char *type, const char *fileType, const void *data, + size_t dataSize, icon_size which) +{ + std::string attr = ((which == B_MINI_ICON) + ? kMiniIconAttrPrefix + : kLargeIconAttrPrefix) + + ToLower(fileType); + return SetIcon(type, attr.c_str(), data, dataSize, which); +} + // StartWatching //! Subscribes the given BMessenger to the MIME monitor service /*! Notification messages will be sent with a \c BMessage::what value @@ -748,6 +553,124 @@ MimeDatabase::StopWatching(BMessenger target) return err; } +// GetIconData +/*! \brief Returns properly formatted raw bitmap data, ready to be shipped off to the hacked + up 4-parameter version of MimeDatabase::SetIcon() + + This function exists as something of a hack until an OBOS::BBitmap implementation is + available. It takes the given bitmap, converts it to the B_CMAP8 color space if necessary + and able, and returns said bitmap data in a newly allocated array pointed to by the + pointer that's pointed to by \c data. The length of the array is stored in the integer + pointed to by \c dataSize. The array is allocated with \c new[], and it's your responsibility + to \c delete[] it when you're finished. + +*/ +status_t +MimeDatabase::GetIconData(const BBitmap *icon, icon_size which, void **data, int32 *dataSize) +{ + ssize_t err = (icon && data && dataSize && icon->InitCheck() == B_OK) ? B_OK : B_BAD_VALUE; + + BRect bounds; + BBitmap *icon8 = NULL; + void *srcData = NULL; + bool otherColorSpace = false; + + // Figure out what kind of data we *should* have + if (!err) { + switch (which) { + case B_MINI_ICON: + bounds.Set(0, 0, 15, 15); + break; + case B_LARGE_ICON: + bounds.Set(0, 0, 31, 31); + break; + default: + err = B_BAD_VALUE; + break; + } + } + // Check the icon + if (!err) + err = (icon->Bounds() == bounds) ? B_OK : B_BAD_VALUE; + // Convert to B_CMAP8 if necessary + if (!err) { + otherColorSpace = (icon->ColorSpace() != B_CMAP8); + if (otherColorSpace) { + icon8 = new BBitmap(bounds, B_CMAP8); + if (!icon8) + err = B_NO_MEMORY; + if (!err) { + switch (icon->ColorSpace()) { + case B_RGB32: + { + // Set each pixel individually, since SetBits() for B_RGB32 takes + // 24-bit rgb pixel data... + char *bgra = (char*)icon->Bits(); + for (uint32 i = 0; i*4+3 < icon->BitsLength(); bgra += 4, i++) { + char rgb[3]; + rgb[0] = bgra[2]; // red + rgb[1] = bgra[1]; // green + rgb[2] = bgra[0]; // blue + icon8->SetBits(rgb, 3, i, B_RGB32); + } + break; + } + case B_GRAY1: + { + icon8->SetBits(icon->Bits(), icon->BitsLength(), 0, B_GRAY1); + break; + } + default: + err = B_BAD_VALUE; + } + if (!err) + err = icon8->InitCheck(); // I don't think this is actually useful, even if SetBits() fails... + } + if (!err) { + srcData = icon8->Bits(); + *dataSize = icon8->BitsLength(); + } + } else { + srcData = icon->Bits(); + *dataSize = icon->BitsLength(); + } + } + // Alloc a new data buffer + if (!err) { + *data = new char[*dataSize]; + if (!*data) + err = B_NO_MEMORY; + } + // Copy the data into it. + if (!err) + memcpy(*data, srcData, *dataSize); + if (otherColorSpace) + delete icon8; + return err; +} + +// DeleteAttribute +//! Deletes the given attribute for the given type +/*! + \param type The mime type + \param attr The attribute name + \return + - B_OK: success + - B_ENTRY_NOT_FOUND: no such type or attribute + - "error code": failure +*/ +status_t +MimeDatabase::DeleteAttribute(const char *type, const char *attr) +{ + status_t err = type ? B_OK : B_BAD_VALUE; + BNode node; + if (!err) + err = OpenType(type, &node); + if (!err) + err = node.RemoveAttr(attr); + return err; +} + // ReadMimeAttr /*! \brief Reads up to \c len bytes of the given data from the given attribute for the given MIME type. @@ -836,7 +759,7 @@ status_t MimeDatabase::OpenOrCreateType(const char *type, BNode *result) { std::string filename; - std::string typeLower = to_lower(type); + std::string typeLower = ToLower(type); status_t err = (type && result ? B_OK : B_BAD_VALUE); if (!err) { filename = TypeToFilename(type); @@ -874,7 +797,7 @@ inline std::string MimeDatabase::TypeToFilename(const char *type) const { - return fDatabaseDir + "/" + to_lower(type); + return fDatabaseDir + "/" + ToLower(type); } // SendMonitorUpdate @@ -985,5 +908,136 @@ MimeDatabase::SendMonitorUpdate(BMessage &msg) { return B_OK; } +// GetIconForAttr +//! Fetches the icon stored in the given attribute +/*! The bitmap pointed to by \c icon must be of the proper size (\c 32x32 + for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON). + + \param type The mime type + \param attr The attribute in which the icon is stored + \param icon Pointer to a pre-allocated bitmap of proper dimensions and color depth + \param size The size icon you're expecting (\c B_LARGE_ICON or \c B_MINI_ICON) +*/ +status_t +MimeDatabase::GetIcon(const char *type, const char *attr, BBitmap *icon, icon_size which) const +{ + attr_info info; + ssize_t err; + BNode node; + uint32 attrType; + size_t attrSize; + BRect bounds; + char *buffer; + + err = type && icon ? B_OK : B_BAD_VALUE; + + // Figure out what kind of data we *should* find + if (!err) { + switch (which) { + case B_MINI_ICON: + bounds.Set(0, 0, 15, 15); + attrType = B_MINI_ICON_TYPE; + attrSize = 16 * 16; + break; + case B_LARGE_ICON: + bounds.Set(0, 0, 31, 31); + attrType = B_LARGE_ICON_TYPE; + attrSize = 32 * 32; + break; + default: + err = B_BAD_VALUE; + break; + } + } + // Check the icon and attribute to see if they match + if (!err) + err = (icon->InitCheck() == B_OK && icon->Bounds() == bounds) ? B_OK : B_BAD_VALUE; + if (!err) + err = OpenType(type, &node); + if (!err) + err = node.GetAttrInfo(attr, &info); + if (!err) + err = (attrType == info.type && attrSize == info.size) ? B_OK : B_BAD_VALUE; + // read the attribute + if (!err) { + bool otherColorSpace = (icon->ColorSpace() != B_CMAP8); + char *buffer = NULL; + ssize_t read; + if (otherColorSpace) { + // other color space than stored in attribute + buffer = new(nothrow) char[attrSize]; + if (!buffer) + err = B_NO_MEMORY; + if (!err) + err = node.ReadAttr(attr, attrType, 0, buffer, attrSize); + } else { + // same color space, just read direct + err = node.ReadAttr(attr, attrType, 0, icon->Bits(), attrSize); + } + if (err >= 0) + err = (err == attrSize) ? B_OK : B_FILE_ERROR; + if (otherColorSpace) { + if (!err) { + icon->SetBits(buffer, attrSize, 0, B_CMAP8); + err = icon->InitCheck(); + } + delete[] buffer; + } + } + + return err; +} + +//! Sets the icon stored in the given attribute +/*! The bitmap data pointed to by \c data must be of the proper size (\c 32x32 + for \c B_LARGE_ICON, \c 16x16 for \c B_MINI_ICON) and the proper color + space (B_CMAP8). + + \param type The mime type + \param attr The attribute in which the icon is stored + \param data Pointer to an array of bitmap data of proper dimensions and color depth + \param dataSize The length of the array pointed to by \c data + \param size The size icon you're expecting (\c B_LARGE_ICON or \c B_MINI_ICON) +*/ +status_t +MimeDatabase::SetIcon(const char *type, const char *attr, const void *data, size_t dataSize, icon_size which) +{ + ssize_t err = (type && data) ? B_OK : B_BAD_VALUE; + + int32 attrType; + int32 attrSize; + + // Figure out what kind of data we *should* have + if (!err) { + switch (which) { + case B_MINI_ICON: + attrType = B_MINI_ICON_TYPE; + attrSize = 16 * 16; + break; + case B_LARGE_ICON: + attrType = B_LARGE_ICON_TYPE; + attrSize = 32 * 32; + break; + default: + err = B_BAD_VALUE; + break; + } + } + + // Double check the data we've been given + if (!err) + err = (dataSize == attrSize) ? B_OK : B_BAD_VALUE; + + // Write the icon data + BNode node; + if (!err) + err = OpenOrCreateType(type, &node); + if (!err) + err = node.WriteAttr(attr, attrType, 0, data, attrSize); + if (err >= 0) + err = (err == attrSize) ? B_OK : B_FILE_ERROR; + return err; +} } // namespace BPrivate + diff --git a/src/kits/storage/MimeType.cpp b/src/kits/storage/MimeType.cpp index 01b168ae0d..b6c6d6a76d 100644 --- a/src/kits/storage/MimeType.cpp +++ b/src/kits/storage/MimeType.cpp @@ -623,79 +623,9 @@ BMimeType::GetSupportingApps(BMessage *signatures) const */ status_t -BMimeType::SetIcon(const BBitmap *icon, icon_size size) +BMimeType::SetIcon(const BBitmap *icon, icon_size which) { - status_t err = icon ? B_OK : B_BAD_VALUE; - if (!err) - err = InitCheck(); - - BMessage msg(B_REG_MIME_SET_PARAM); - BMessage reply; - status_t result; - - void *data = NULL; - int32 dataSize; - - if (!err) - err = BPrivate::MimeDatabase::GetIconData(icon, size, &data, &dataSize); - - // Build and send the message, read the reply - if (!err) - err = msg.AddString("type", Type()); - if (!err) - err = msg.AddInt32("which", B_REG_MIME_ICON); - if (!err) - err = msg.AddData("icon data", B_RAW_TYPE, data, dataSize); - if (!err) - err = msg.AddInt32("icon size", size); - if (!err) - err = _send_to_roster_(&msg, &reply, true); - if (!err) - err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE; - if (!err) - err = reply.FindInt32("result", &result); - if (!err) - err = result; - - delete [] data; - return err; - - -/* This is the code I was using before BBitmap::Instantiate - blew up on me - - status_t err = icon ? B_OK : B_BAD_VALUE; - if (!err) - err = InitCheck(); - - BMessage msg(B_REG_MIME_SET_PARAM); - BMessage reply; - status_t result; - - BMessage archive; - - // Build and send the message, read the reply - if (!err) - err = msg.AddString("type", Type()); - if (!err) - err = msg.AddInt32("which", B_REG_MIME_ICON); - if (!err) - err = icon->Archive(&archive); - archive.PrintToStream(); - if (!err) - err = msg.AddMessage("icon archive", &archive); - if (!err) - err = msg.AddInt32("size", size); - if (!err) - err = _send_to_roster_(&msg, &reply, true); - if (!err) - err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE; - if (!err) - err = reply.FindInt32("result", &result); - if (!err) - err = result; - return err; -*/ + return SetIconForType(NULL, icon, which); } // SetPreferredApp @@ -721,11 +651,9 @@ BMimeType::SetIcon(const BBitmap *icon, icon_size size) status_t BMimeType::SetPreferredApp(const char *signature, app_verb verb) { - status_t err = signature ? B_OK : B_BAD_VALUE; - if (!err) - err = InitCheck(); + status_t err = InitCheck(); - BMessage msg(B_REG_MIME_SET_PARAM); + BMessage msg(signature ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); BMessage reply; status_t result; @@ -734,7 +662,7 @@ BMimeType::SetPreferredApp(const char *signature, app_verb verb) err = msg.AddString("type", Type()); if (!err) err = msg.AddInt32("which", B_REG_MIME_PREFERRED_APP); - if (!err) + if (!err && signature) err = msg.AddString("signature", signature); if (!err) err = msg.AddInt32("app verb", verb); @@ -856,11 +784,9 @@ BMimeType::SetFileExtensions(const BMessage *extensions) status_t BMimeType::SetShortDescription(const char *description) { - status_t err = description ? B_OK : B_BAD_VALUE; - if (!err) - err = InitCheck(); + status_t err = InitCheck(); - BMessage msg(B_REG_MIME_SET_PARAM); + BMessage msg(description ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); BMessage reply; status_t result; @@ -869,12 +795,10 @@ BMimeType::SetShortDescription(const char *description) err = msg.AddString("type", Type()); if (!err) err = msg.AddInt32("which", B_REG_MIME_DESCRIPTION); - if (!err) + if (!err && description) err = msg.AddString("description", description); if (!err) err = msg.AddBool("long", false); - if (!err) - err = msg.AddString("type", Type()); if (!err) err = _send_to_roster_(&msg, &reply, true); if (!err) @@ -902,11 +826,9 @@ BMimeType::SetShortDescription(const char *description) status_t BMimeType::SetLongDescription(const char *description) { - status_t err = description ? B_OK : B_BAD_VALUE; - if (!err) - err = InitCheck(); + status_t err = InitCheck(); - BMessage msg(B_REG_MIME_SET_PARAM); + BMessage msg(description ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); BMessage reply; status_t result; @@ -915,7 +837,7 @@ BMimeType::SetLongDescription(const char *description) err = msg.AddString("type", Type()); if (!err) err = msg.AddInt32("which", B_REG_MIME_DESCRIPTION); - if (!err) + if (!err && description) err = msg.AddString("description", description); if (!err) err = msg.AddBool("long", true); @@ -1106,11 +1028,9 @@ BMimeType::GetAppHint(entry_ref *ref) const status_t BMimeType::SetAppHint(const entry_ref *ref) { - status_t err = ref ? B_OK : B_BAD_VALUE; - if (!err) - err = InitCheck(); + status_t err = InitCheck(); - BMessage msg(B_REG_MIME_SET_PARAM); + BMessage msg(ref ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); BMessage reply; status_t result; @@ -1119,7 +1039,7 @@ BMimeType::SetAppHint(const entry_ref *ref) err = msg.AddString("type", Type()); if (!err) err = msg.AddInt32("which", B_REG_MIME_APP_HINT); - if (!err) + if (!err && ref) err = msg.AddRef("app hint", ref); if (!err) err = _send_to_roster_(&msg, &reply, true); @@ -1164,7 +1084,16 @@ BMimeType::SetAppHint(const entry_ref *ref) status_t BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) const { - return NOT_IMPLEMENTED; + // If type is NULL, this function works just like GetIcon(), othewise, + // we need to make sure the give type is valid. + status_t err; + if (type) { + err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE; + if (!err) + err = fMimeDatabase->GetIconForType(Type(), type, icon, which); + } else + err = GetIcon(icon, which); + return err; } // SetIconForType @@ -1183,7 +1112,6 @@ BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) cons The icon is copied from the \c BBitmap pointed to by \c icon. The bitmap must be the proper size: \c 32x32 for the large icon, \c 16x16 for the mini icon. - Additionally, the bitmap must be in the \c B_CMAP8 color space (8-bit color). If you want to erase the current icon, pass \c NULL as the \c icon argument. @@ -1201,7 +1129,45 @@ BMimeType::GetIconForType(const char *type, BBitmap *icon, icon_size which) cons status_t BMimeType::SetIconForType(const char *type, const BBitmap *icon, icon_size which) { - return NOT_IMPLEMENTED; + status_t err = InitCheck(); + + BMessage msg(icon ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); + BMessage reply; + status_t result; + + void *data = NULL; + int32 dataSize; + + // Build and send the message, read the reply + if (!err) + err = msg.AddString("type", Type()); + if (!err) + err = msg.AddInt32("which", (type ? B_REG_MIME_ICON_FOR_TYPE : B_REG_MIME_ICON)); + if (icon) { + if (!err) + err = BPrivate::MimeDatabase::GetIconData(icon, which, &data, &dataSize); + if (!err) + err = msg.AddData("icon data", B_RAW_TYPE, data, dataSize); + } + if (!err) + err = msg.AddInt32("icon size", which); + if (type) { + if (!err) + err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE; + if (!err) + err = msg.AddString("file type", type); + } + if (!err) + err = _send_to_roster_(&msg, &reply, true); + if (!err) + err = reply.what == B_REG_RESULT ? B_OK : B_BAD_VALUE; + if (!err) + err = reply.FindInt32("result", &result); + if (!err) + err = result; + + delete [] data; + return err; } // GetSnifferRule @@ -1458,6 +1424,77 @@ BMimeType::SetType(const char *mimeType) SetTo(mimeType); } +// DeleteIcon +//! Deletes the mime type's icon of given size +status_t +BMimeType::DeleteIcon(icon_size which) +{ + return SetIcon(NULL, which); +} + +// DeletePreferredApp +//! Deletes the mime type's preferred app for the given verb +status_t +BMimeType::DeletePreferredApp(app_verb verb = B_OPEN) +{ + return SetPreferredApp(NULL, verb); +} + +// DeleteAttrInfo +//! Deletes the mime type's attribute info +status_t +BMimeType::DeleteAttrInfo() +{ + return SetAttrInfo(NULL); +} + +// DeleteFileExtensions +//! Deletes the mime type's associated file extensions +status_t +BMimeType::DeleteFileExtensions() +{ + return SetFileExtensions(NULL); +} + +// DeleteShortDescription +//! Deletes the mime type's short description +status_t +BMimeType::DeleteShortDescription() +{ + return SetShortDescription(NULL); +} + +// DeleteLongDescription +//! Deletes the mime type's long description +status_t +BMimeType::DeleteLongDescription() +{ + return SetLongDescription(NULL); +} + +// DeleteSnifferRule +//! Deletes the mime type's sniffer rule +status_t +BMimeType::DeleteSnifferRule() +{ + return SetSnifferRule(NULL); +} + +// DeleteIconForType +//! Deletes the mime type's custom icon of given size for the given file type +status_t +BMimeType::DeleteIconForType(const char *type, icon_size which) +{ + return SetIconForType(type, NULL, which); +} + +// DeleteAppHint +//! Deletes the mime type's application hint +status_t +BMimeType::DeleteAppHint() +{ + return SetAppHint(NULL); +} void BMimeType::_ReservedMimeType1() {} void BMimeType::_ReservedMimeType2() {} diff --git a/src/servers/registrar/MIMEManager.cpp b/src/servers/registrar/MIMEManager.cpp index f01f10b57d..fd6f38f8ed 100644 --- a/src/servers/registrar/MIMEManager.cpp +++ b/src/servers/registrar/MIMEManager.cpp @@ -48,7 +48,11 @@ MIMEManager::MessageReceived(BMessage *message) switch (message->what) { case B_REG_MIME_SET_PARAM: HandleSetParam(message); - break; + break; + + case B_REG_MIME_DELETE_PARAM: + HandleDeleteParam(message); + break; case B_REG_MIME_START_WATCHING: case B_REG_MIME_STOP_WATCHING: @@ -89,7 +93,7 @@ MIMEManager::MessageReceived(BMessage *message) } } -// HandleSetParam +// HandleSetParam //! Handles all B_REG_MIME_SET_PARAM messages void MIMEManager::HandleSetParam(BMessage *message) @@ -139,16 +143,26 @@ MIMEManager::HandleSetParam(BMessage *message) } case B_REG_MIME_ICON: + case B_REG_MIME_ICON_FOR_TYPE: { - // Begin temporary fix code const void *data; ssize_t dataSize; int32 size; err = message->FindData("icon data", B_RAW_TYPE, &data, &dataSize); if (!err) err = message->FindInt32("icon size", &size); - if (!err) - err = fMimeDatabase.SetIcon(type, (icon_size)size, data, dataSize); + if (which == B_REG_MIME_ICON_FOR_TYPE) { + const char *fileType; + if (!err) + err = message->FindString("file type", &fileType); + if (!err) + err = fMimeDatabase.SetIconForType(type, fileType, data, + dataSize, (icon_size)size); + } else { + if (!err) + err = fMimeDatabase.SetIcon(type, data, dataSize, + (icon_size)size); + } break; // End temporary fix code @@ -188,4 +202,93 @@ MIMEManager::HandleSetParam(BMessage *message) BMessage reply(B_REG_RESULT); reply.AddInt32("result", err); message->SendReply(&reply, this); -} \ No newline at end of file +} + +// HandleSetParam +//! Handles all B_REG_MIME_SET_PARAM messages +void +MIMEManager::HandleDeleteParam(BMessage *message) +{ +// using BPrivate::MimeDatabase; + + status_t err; + int32 which; + const char *type; + + err = message->FindString("type", &type); + if (!err) + err = message->FindInt32("which", &which); + if (!err) { + switch (which) { + case B_REG_MIME_APP_HINT: + err = fMimeDatabase.DeleteAttribute(type, BPrivate::MimeDatabase::kAppHintAttr); + break; + + case B_REG_MIME_DESCRIPTION: + { + bool isLong; + const char *description; + err = message->FindBool("long", &isLong); + if (!err) + err = fMimeDatabase.DeleteAttribute(type, + (isLong + ? BPrivate::MimeDatabase::kLongDescriptionAttr + : BPrivate::MimeDatabase::kShortDescriptionAttr)); + break; + } + + case B_REG_MIME_PREFERRED_APP: + { + int32 verb; + err = message->FindInt32("app verb", &verb); + if (!err) { + switch (verb) { + case B_OPEN: + err = fMimeDatabase.DeleteAttribute(type, BPrivate::MimeDatabase::kPreferredAppAttr); + break; + + default: + err = B_BAD_VALUE; + break; + } + } + break; + } + + case B_REG_MIME_ICON: + case B_REG_MIME_ICON_FOR_TYPE: + { + int32 size; + err = message->FindInt32("icon size", &size); + if (which == B_REG_MIME_ICON_FOR_TYPE) { + const char *fileType; + if (!err) + err = message->FindString("file type", &fileType); + if (!err) { + std::string attr = ((size == B_MINI_ICON) + ? BPrivate::MimeDatabase::kMiniIconAttrPrefix + : BPrivate::MimeDatabase::kLargeIconAttrPrefix) + + BPrivate::MimeDatabase::ToLower(fileType); + err = fMimeDatabase.DeleteAttribute(type, attr.c_str()); + } + } else { + if (!err) { + err = fMimeDatabase.DeleteAttribute(type, (size == B_MINI_ICON + ? BPrivate::MimeDatabase::kMiniIconAttr + : BPrivate::MimeDatabase::kLargeIconAttr)); + } + } + break; + } + + default: + err = B_BAD_VALUE; + break; + } + } + + BMessage reply(B_REG_RESULT); + reply.AddInt32("result", err); + message->SendReply(&reply, this); +} + diff --git a/src/servers/registrar/MIMEManager.h b/src/servers/registrar/MIMEManager.h index 2c389fe3b3..b99c1ac789 100644 --- a/src/servers/registrar/MIMEManager.h +++ b/src/servers/registrar/MIMEManager.h @@ -14,6 +14,8 @@ public: virtual void MessageReceived(BMessage *message); private: void HandleSetParam(BMessage *message); + void HandleDeleteParam(BMessage *message); + BPrivate::MimeDatabase fMimeDatabase; };