* The recent files list now also preserves the case of the MIME strings.

* STL allocations are guarded by a try/catch block.
* As in RecentApps, Get() did not properly populate an error condition.
* Cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19263 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-11-12 17:46:34 +00:00
parent 01b06fcc52
commit fd5c02b25c
2 changed files with 177 additions and 194 deletions
+1 -1
View File
@@ -82,7 +82,7 @@ RecentApps::Add(const char *appSig, int32 appFlags)
// of recent apps // of recent apps
if (!strcasecmp(appSig, kTrackerSignature) if (!strcasecmp(appSig, kTrackerSignature)
|| !strcasecmp(appSig, kDeskbarSignature) || !strcasecmp(appSig, kDeskbarSignature)
|| (appFlags & B_ARGV_ONLY) != 0 || (appFlags & B_BACKGROUND_APP) != 0) || (appFlags & (B_ARGV_ONLY | B_BACKGROUND_APP)) != 0)
return B_OK; return B_OK;
// Remove any previous instance // Remove any previous instance
+93 -110
View File
@@ -1,32 +1,15 @@
//------------------------------------------------------------------------------ /*
// Copyright (c) 2001-2005, Haiku * Copyright 2001-2006, Haiku Inc.
// * Distributed under the terms of the MIT License.
// Permission is hereby granted, free of charge, to any person obtaining a *
// copy of this software and associated documentation files (the "Software"), * Authors:
// to deal in the Software without restriction, including without limitation * Tyler Dauwalder
// the rights to use, copy, modify, merge, publish, distribute, sublicense, * Ingo Weinhold, [email protected]
// and/or sell copies of the Software, and to permit persons to whom the * Axel Dörfler, [email protected]e
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: RecentEntries.cpp
// Author: Tyler Dauwalder ([email protected])
// Description: Recently launched apps list
//------------------------------------------------------------------------------
/*! \file RecentEntries.cpp
\brief RecentEntries class implementation
*/ */
//! Recently launched apps list
#include "RecentEntries.h" #include "RecentEntries.h"
#include <AppFileInfo.h> #include <AppFileInfo.h>
@@ -48,9 +31,6 @@ using namespace std;
//#define DBG(x) //#define DBG(x)
#define OUT printf #define OUT printf
//------------------------------------------------------------------------------
// recent_entry
//------------------------------------------------------------------------------
/*! \struct recent_entry /*! \struct recent_entry
@@ -65,15 +45,16 @@ using namespace std;
*/ */
recent_entry::recent_entry(const entry_ref *ref, const char *appSig, recent_entry::recent_entry(const entry_ref *ref, const char *appSig,
uint32 index) uint32 index)
: ref(ref ? *ref : entry_ref()) :
, sig(appSig) ref(ref ? *ref : entry_ref()),
, index(index) sig(appSig),
index(index)
{ {
} }
//------------------------------------------------------------------------------
// RecentEntries // #pragma mark -
//------------------------------------------------------------------------------
/*! \class RecentEntries /*! \class RecentEntries
\brief Implements the common functionality used by the roster's recent \brief Implements the common functionality used by the roster's recent
@@ -88,7 +69,7 @@ recent_entry::recent_entry(const entry_ref *ref, const char *appSig,
signatures are case-independent. signatures are case-independent.
*/ */
// constructor
/*! \brief Creates a new list. /*! \brief Creates a new list.
The list is initially empty. The list is initially empty.
@@ -97,7 +78,7 @@ RecentEntries::RecentEntries()
{ {
} }
// destructor
/*! \brief Frees all resources associated with the object. /*! \brief Frees all resources associated with the object.
*/ */
RecentEntries::~RecentEntries() RecentEntries::~RecentEntries()
@@ -105,7 +86,7 @@ RecentEntries::~RecentEntries()
Clear(); Clear();
} }
// Add
/*! \brief Places the given entry Places the app with the given signature at the front of /*! \brief Places the given entry Places the app with the given signature at the front of
the recent apps list. the recent apps list.
@@ -124,16 +105,13 @@ RecentEntries::~RecentEntries()
status_t status_t
RecentEntries::Add(const entry_ref *ref, const char *appSig) RecentEntries::Add(const entry_ref *ref, const char *appSig)
{ {
std::string sig; if (ref == NULL || appSig == NULL)
status_t error = ref && appSig ? B_OK : B_BAD_VALUE; return B_BAD_VALUE;
if (!error) {
// Store all sigs as lowercase
sig = BPrivate::Storage::to_lower(appSig);
// Look for a previous instance of this entry // Look for a previous instance of this entry
std::list<recent_entry*>::iterator item; std::list<recent_entry*>::iterator item;
for (item = fEntryList.begin(); item != fEntryList.end(); item++) { for (item = fEntryList.begin(); item != fEntryList.end(); item++) {
if ((*item)->ref == *ref && (*item)->sig == sig) { if ((*item)->ref == *ref && !strcasecmp((*item)->sig.c_str(), appSig)) {
fEntryList.erase(item); fEntryList.erase(item);
break; break;
} }
@@ -141,14 +119,19 @@ RecentEntries::Add(const entry_ref *ref, const char *appSig)
// Add this entry to the front of the list // Add this entry to the front of the list
recent_entry *entry = new (nothrow) recent_entry(ref, appSig, 0); recent_entry *entry = new (nothrow) recent_entry(ref, appSig, 0);
error = entry ? B_OK : B_NO_MEMORY; if (entry == NULL)
if (!error) return B_NO_MEMORY;
try {
fEntryList.push_front(entry); fEntryList.push_front(entry);
} } catch (...) {
return error; return B_NO_MEMORY;
} }
// Get return B_OK;
}
/*! \brief Returns the first \a maxCount recent apps in the \c BMessage /*! \brief Returns the first \a maxCount recent apps in the \c BMessage
pointed to by \a list. pointed to by \a list.
@@ -171,82 +154,87 @@ RecentEntries::Add(const entry_ref *ref, const char *appSig)
expected to be all lowercase. expected to be all lowercase.
*/ */
status_t status_t
RecentEntries::Get(int32 maxCount, const char *fileTypes[], int32 fileTypesCount, RecentEntries::Get(int32 maxCount, const char *fileTypes[],
const char *appSig, BMessage *result) int32 fileTypesCount, const char *appSig, BMessage *result)
{ {
status_t error = result && (fileTypesCount == 0 || (fileTypesCount > 0 && fileTypes)) if (result == NULL
? B_OK : B_BAD_VALUE; || fileTypesCount < 0
if (!error) { || (fileTypesCount > 0 && fileTypes == NULL))
return B_BAD_VALUE;
result->MakeEmpty(); result->MakeEmpty();
std::list<recent_entry*> duplicateList; std::list<recent_entry*> duplicateList;
std::list<recent_entry*>::iterator item; std::list<recent_entry*>::iterator item;
status_t error = B_OK;
int count = 0; int count = 0;
for (item = fEntryList.begin(); for (item = fEntryList.begin();
count < maxCount && item != fEntryList.end(); error == B_OK && count < maxCount && item != fEntryList.end();
item++) item++) {
{
bool match = true;
// Filter if necessary
if (fileTypesCount > 0 || appSig) {
match = false;
// Filter by app sig // Filter by app sig
if (appSig) if (appSig != NULL && strcasecmp((*item)->sig.c_str(), appSig))
match = (*item)->sig == appSig; continue;
// Filter by file type // Filter by file type
if (!match && fileTypesCount > 0) { if (fileTypesCount > 0) {
char type[B_MIME_TYPE_LENGTH]; char type[B_MIME_TYPE_LENGTH];
if (GetTypeForRef(&(*item)->ref, type) == B_OK) { if (GetTypeForRef(&(*item)->ref, type) == B_OK) {
bool match = false;
for (int i = 0; i < fileTypesCount; i++) { for (int i = 0; i < fileTypesCount; i++) {
if (strcasecmp(type, fileTypes[i]) == 0) { if (!strcasecmp(type, fileTypes[i])) {
match = true; match = true;
break; break;
} }
} }
if (!match)
continue;
} }
} }
}
if (match) {
// Check for duplicates // Check for duplicates
for (std::list<recent_entry*>::iterator dupItem bool duplicate = false;
= duplicateList.begin(); for (std::list<recent_entry*>::iterator dupItem = duplicateList.begin();
dupItem != duplicateList.end(); dupItem != duplicateList.end(); dupItem++) {
dupItem++)
{
if ((*dupItem)->ref == (*item)->ref) { if ((*dupItem)->ref == (*item)->ref) {
match = false; duplicate = true;
break; break;
} }
} }
} if (duplicate)
if (match) { continue;
// Add the ref to the list used to check // Add the ref to the list used to check
// for duplicates, and then to the result // for duplicates, and then to the result
try {
duplicateList.push_back(*item); duplicateList.push_back(*item);
result->AddRef("refs", &(*item)->ref); } catch (...) {
error = B_NO_MEMORY;
}
if (error == B_OK)
error = result->AddRef("refs", &(*item)->ref);
if (error == B_OK)
count++; count++;
} }
}
}
return error; return error;
} }
// Clear
/*! \brief Clears the list of recently launched apps /*! \brief Clears the list of recently launched apps
*/ */
status_t status_t
RecentEntries::Clear() RecentEntries::Clear()
{ {
std::list<recent_entry*>::iterator i; std::list<recent_entry*>::iterator i;
for (i = fEntryList.begin(); i != fEntryList.end(); i++) for (i = fEntryList.begin(); i != fEntryList.end(); i++) {
delete *i; delete *i;
}
fEntryList.clear(); fEntryList.clear();
return B_OK; return B_OK;
} }
// Print
/*! \brief Dumps the the current list of entries to stdout. /*! \brief Dumps the the current list of entries to stdout.
*/ */
status_t status_t
@@ -254,10 +242,7 @@ RecentEntries::Print()
{ {
std::list<recent_entry*>::iterator item; std::list<recent_entry*>::iterator item;
int counter = 1; int counter = 1;
for (item = fEntryList.begin(); for (item = fEntryList.begin(); item != fEntryList.end(); item++) {
item != fEntryList.end();
item++)
{
printf("%d: device == '%ld', dir == '%lld', name == '%s', app == '%s', index == %ld\n", printf("%d: device == '%ld', dir == '%lld', name == '%s', app == '%s', index == %ld\n",
counter++, (*item)->ref.device, (*item)->ref.directory, (*item)->ref.name, counter++, (*item)->ref.device, (*item)->ref.directory, (*item)->ref.name,
(*item)->sig.c_str(), (*item)->index); (*item)->sig.c_str(), (*item)->index);
@@ -265,12 +250,13 @@ RecentEntries::Print()
return B_OK; return B_OK;
} }
// Save
status_t status_t
RecentEntries::Save(FILE* file, const char *description, const char *tag) RecentEntries::Save(FILE* file, const char *description, const char *tag)
{ {
status_t error = file ? B_OK : B_BAD_VALUE; if (file == NULL || description == NULL || tag == NULL)
if (!error) { return B_BAD_VALUE;
fprintf(file, "# %s\n", description); fprintf(file, "# %s\n", description);
/* In order to write our entries out in the format used by the /* In order to write our entries out in the format used by the
@@ -286,10 +272,9 @@ RecentEntries::Save(FILE* file, const char *description, const char *tag)
std::map<entry_ref, std::list<recent_entry*> > map; std::map<entry_ref, std::list<recent_entry*> > map;
uint32 count = fEntryList.size(); uint32 count = fEntryList.size();
try {
for (std::list<recent_entry*>::iterator item = fEntryList.begin(); for (std::list<recent_entry*>::iterator item = fEntryList.begin();
item != fEntryList.end(); item != fEntryList.end(); count--, item++) {
count--, item++)
{
recent_entry *entry = *item; recent_entry *entry = *item;
if (entry) { if (entry) {
entry->index = count; entry->index = count;
@@ -300,12 +285,12 @@ RecentEntries::Save(FILE* file, const char *description, const char *tag)
fEntryList.size() - count)); fEntryList.size() - count));
} }
} }
} catch (...) {
return B_NO_MEMORY;
}
for (std::map<entry_ref, std::list<recent_entry*> >::iterator mapItem for (std::map<entry_ref, std::list<recent_entry*> >::iterator mapItem = map.begin();
= map.begin(); mapItem != map.end(); mapItem++) {
mapItem != map.end();
mapItem++)
{
// We're going to need to properly escape the path name we // We're going to need to properly escape the path name we
// get, which will at absolute worst double the length of // get, which will at absolute worst double the length of
// the string. // the string.
@@ -318,9 +303,7 @@ RecentEntries::Save(FILE* file, const char *description, const char *tag)
std::list<recent_entry*> &list = mapItem->second; std::list<recent_entry*> &list = mapItem->second;
int32 i = 0; int32 i = 0;
for (std::list<recent_entry*>::iterator item = list.begin(); for (std::list<recent_entry*>::iterator item = list.begin();
item != list.end(); item != list.end(); i++, item++) {
i++, item++)
{
recent_entry *entry = *item; recent_entry *entry = *item;
if (entry) if (entry)
fprintf(file, " \"%s\" %ld", entry->sig.c_str(), entry->index); fprintf(file, " \"%s\" %ld", entry->sig.c_str(), entry->index);
@@ -340,9 +323,9 @@ RecentEntries::Save(FILE* file, const char *description, const char *tag)
mapItem->first.name, outputError)); mapItem->first.name, outputError));
} }
} }
fprintf(file, "\n"); fprintf(file, "\n");
} return B_OK;
return error;
} }
@@ -355,20 +338,20 @@ RecentEntries::Save(FILE* file, const char *description, const char *tag)
status_t status_t
RecentEntries::GetTypeForRef(const entry_ref *ref, char *result) RecentEntries::GetTypeForRef(const entry_ref *ref, char *result)
{ {
if (ref == NULL || result == NULL)
return B_BAD_VALUE;
// Read the type
BNode node; BNode node;
status_t error = ref && result ? B_OK : B_BAD_VALUE; status_t error = node.SetTo(ref);
// Read the type and force to lowercase if (error == B_OK) {
if (!error)
error = node.SetTo(ref);
if (!error) {
ssize_t bytes = node.ReadAttr("BEOS:TYPE", B_MIME_STRING_TYPE, ssize_t bytes = node.ReadAttr("BEOS:TYPE", B_MIME_STRING_TYPE,
0, result, B_MIME_TYPE_LENGTH - 1); 0, result, B_MIME_TYPE_LENGTH - 1);
if (bytes < 0) if (bytes < B_OK)
error = bytes; error = bytes;
else else
result[bytes] = '\0'; result[bytes] = '\0';
} }
if (!error)
BPrivate::Storage::to_lower(result);
return error; return error;
} }