* Public domain source code.
*
* Author:
* Joseph "looncraz" Groover <looncraz@satx.rr.com>
*/
#include <DecorInfo.h>
#include <new>
#include <stdio.h>
#include <Autolock.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Resources.h>
#include <SystemCatalog.h>
#include <DecoratorPrivate.h>
#define B_TRANSLATION_CONTEXT "Default decorator about box"
namespace BPrivate {
DecorInfo::DecorInfo()
:
fVersion(0),
fModificationTime(0),
fInitStatus(B_NO_INIT)
{
}
DecorInfo::DecorInfo(const BString& path)
:
fPath(path),
fVersion(0),
fModificationTime(0),
fInitStatus(B_NO_INIT)
{
BEntry entry(path.String(), true);
entry.GetRef(&fRef);
_Init();
}
DecorInfo::DecorInfo(const entry_ref& ref)
:
fRef(ref),
fVersion(0),
fModificationTime(0),
fInitStatus(B_NO_INIT)
{
BPath path(&ref);
fPath = path.Path();
_Init();
}
DecorInfo::~DecorInfo()
{
}
status_t
DecorInfo::SetTo(const entry_ref& ref)
{
Unset();
BPath path(&ref);
fPath = path.Path();
fRef = ref;
_Init();
return InitCheck();
}
status_t
DecorInfo::SetTo(BString path)
{
BEntry entry(path.String(), true);
entry_ref ref;
entry.GetRef(&ref);
return SetTo(ref);
}
status_t
DecorInfo::InitCheck() const
{
return fInitStatus;
}
void
DecorInfo::Unset()
{
fRef = entry_ref();
fPath = "";
fName = "";
fAuthors = "";
fShortDescription = "";
fLicenseURL = "";
fLicenseName = "";
fSupportURL = "";
fVersion = 0;
fModificationTime = 0;
fInitStatus = B_NO_INIT;
}
bool
DecorInfo::IsDefault() const
{
return fPath == "Default";
}
BString
DecorInfo::Path() const
{
return fPath;
}
const entry_ref*
DecorInfo::Ref() const
{
if (InitCheck() != B_OK || IsDefault())
return NULL;
return &fRef;
}
BString
DecorInfo::Name() const
{
return fName;
}
BString
DecorInfo::ShortcutName() const
{
if (IsDefault())
return "Default";
else if (Ref() != NULL)
return fRef.name;
return fName;
}
BString
DecorInfo::Authors() const
{
return fAuthors;
}
BString
DecorInfo::ShortDescription() const
{
return fShortDescription;
}
BString
DecorInfo::LongDescription() const
{
return fLongDescription;
}
BString
DecorInfo::LicenseURL() const
{
return fLicenseURL;
}
BString
DecorInfo::LicenseName() const
{
return fLicenseName;
}
BString
DecorInfo::SupportURL() const
{
return fSupportURL;
}
float
DecorInfo::Version() const
{
return fVersion;
}
time_t
DecorInfo::ModificationTime() const
{
return fModificationTime;
}
bool
DecorInfo::CheckForChanges(bool& deleted)
{
if (InitCheck() != B_OK)
return false;
BEntry entry(&fRef);
if (entry.InitCheck() != B_OK)
return false;
if (!entry.Exists()) {
deleted = true;
return true;
}
time_t modtime = 0;
if (entry.GetModificationTime(&modtime) != B_OK) {
fprintf(stderr, "DecorInfo::CheckForChanges()\tERROR: "
"BEntry:GetModificationTime() failed\n");
return false;
}
if (fModificationTime != modtime) {
_Init(true);
return true;
}
return false;
}
void
DecorInfo::_Init(bool isUpdate)
{
if (!isUpdate && InitCheck() != B_NO_INIT) {
fprintf(stderr, "DecorInfo::_Init()\tImproper init state\n");
return;
}
BEntry entry;
if (fPath == "Default") {
if (isUpdate) {
fprintf(stderr, "DecorInfo::_Init(true)\tBUG BUG updating default"
"decorator!?!?!\n");
return;
}
fAuthors = "DarkWyrm, Stephan Aßmus, Clemens Zeidler, Ingo Weinhold";
fLongDescription = "";
fLicenseURL = "http://";
fLicenseName = "MIT";
fSupportURL = "http://www.haiku-os.org/";
fVersion = 0.5;
fInitStatus = B_OK;
fName = gSystemCatalog.GetString(B_TRANSLATE_MARK("Default"),
B_TRANSLATION_CONTEXT);
fShortDescription = gSystemCatalog.GetString(B_TRANSLATE_MARK(
"Default Haiku window decorator."),
B_TRANSLATION_CONTEXT);
BPath path;
find_directory(B_SYSTEM_SERVERS_DIRECTORY, &path);
path.Append("app_server");
entry.SetTo(path.Path(), true);
if (!entry.Exists()) {
fprintf(stderr, "Server MIA the world has become its slave! "
"Call the CIA!\n");
return;
}
entry.GetModificationTime(&fModificationTime);
return;
}
entry.SetTo(&fRef, true);
if (entry.InitCheck() != B_OK) {
fInitStatus = entry.InitCheck();
return;
}
if (!entry.Exists()) {
if (isUpdate) {
fprintf(stderr, "DecorInfo::_Init()\tERROR: decorator deleted"
" after CheckForChanges() found it!\n");
fprintf(stderr, "DecorInfo::_Init()\tERROR: DecorInfo will "
"Unset\n");
Unset();
}
return;
}
entry.GetRef(&fRef);
entry.GetModificationTime(&fModificationTime);
BResources resources(&fRef);
if (resources.InitCheck() != B_OK) {
fprintf(stderr, "DecorInfo::_Init()\t BResource InitCheck() failure\n");
return;
}
size_t infoSize = 0;
const void* infoData = resources.LoadResource(B_MESSAGE_TYPE,
"be:decor:info", &infoSize);
BMessage infoMessage;
if (infoData == NULL || infoSize == 0
|| infoMessage.Unflatten((const char*)infoData) != B_OK) {
fprintf(stderr, "DecorInfo::_init()\tNo extended information found for"
" \"%s\"\n", fRef.name);
} else {
infoMessage.FindString("name", &fName);
infoMessage.FindString("authors", &fAuthors);
infoMessage.FindString("short_descr", &fShortDescription);
infoMessage.FindString("long_descr", &fLongDescription);
infoMessage.FindString("lic_url", &fLicenseURL);
infoMessage.FindString("lic_name", &fLicenseName);
infoMessage.FindString("support_url", &fSupportURL);
infoMessage.FindFloat ("version", &fVersion);
}
fInitStatus = B_OK;
fName = fRef.name;
}
DecorInfoUtility::DecorInfoUtility(bool scanNow)
:
fHasScanned(false)
{
DecorInfo* info = new(std::nothrow) DecorInfo("Default");
if (info == NULL || info->InitCheck() != B_OK) {
delete info;
fprintf(stderr, "DecorInfoUtility::constructor\tdefault decorator's "
"DecorInfo failed InitCheck()\n");
return;
}
fList.AddItem(info);
if (scanNow)
ScanDecorators();
}
DecorInfoUtility::~DecorInfoUtility()
{
BAutolock _(fLock);
for (int i = fList.CountItems() - 1; i >= 0; --i)
delete fList.ItemAt(i);
}
status_t
DecorInfoUtility::ScanDecorators()
{
status_t result;
BPath systemPath;
result = find_directory(B_SYSTEM_ADDONS_DIRECTORY, &systemPath);
if (result == B_OK)
result = systemPath.Append("decorators");
if (result == B_OK) {
BDirectory systemDirectory(systemPath.Path());
result = systemDirectory.InitCheck();
if (result == B_OK) {
result = _ScanDecorators(systemDirectory);
if (result != B_OK) {
fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
strerror(result));
return result;
}
}
}
BPath systemNonPackagedPath;
result = find_directory(B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
&systemNonPackagedPath);
if (result == B_OK)
result = systemNonPackagedPath.Append("decorators");
if (result == B_OK) {
BDirectory systemNonPackagedDirectory(systemNonPackagedPath.Path());
result = systemNonPackagedDirectory.InitCheck();
if (result == B_OK) {
result = _ScanDecorators(systemNonPackagedDirectory);
if (result != B_OK) {
fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
strerror(result));
return result;
}
}
}
BPath userPath;
result = find_directory(B_USER_ADDONS_DIRECTORY, &userPath);
if (result == B_OK)
result = userPath.Append("decorators");
if (result == B_OK) {
BDirectory userDirectory(userPath.Path());
result = userDirectory.InitCheck();
if (result == B_OK) {
result = _ScanDecorators(userDirectory);
if (result != B_OK) {
fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
strerror(result));
return result;
}
}
}
BPath userNonPackagedPath;
result = find_directory(B_USER_NONPACKAGED_ADDONS_DIRECTORY,
&userNonPackagedPath);
if (result == B_OK)
result = userNonPackagedPath.Append("decorators");
if (result == B_OK) {
BDirectory userNonPackagedDirectory(userNonPackagedPath.Path());
result = userNonPackagedDirectory.InitCheck();
if (result == B_OK) {
result = _ScanDecorators(userNonPackagedDirectory);
if (result != B_OK) {
fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
strerror(result));
return result;
}
}
}
fHasScanned = true;
return B_OK;
}
int32
DecorInfoUtility::CountDecorators()
{
BAutolock _(fLock);
if (!fHasScanned)
ScanDecorators();
return fList.CountItems();
}
DecorInfo*
DecorInfoUtility::DecoratorAt(int32 index)
{
BAutolock _(fLock);
return fList.ItemAt(index);
}
DecorInfo*
DecorInfoUtility::FindDecorator(const BString& string)
{
if (string.Length() == 0)
return CurrentDecorator();
if (string == "Default")
return DefaultDecorator();
BAutolock _(fLock);
if (!fHasScanned)
ScanDecorators();
DecorInfo* decor = _FindDecor(string);
if (decor != NULL)
return decor;
for (int i = 1; i < fList.CountItems(); ++i) {
decor = fList.ItemAt(i);
if (string.ICompare(decor->Name()) == 0)
return decor;
}
return NULL;
}
DecorInfo*
DecorInfoUtility::CurrentDecorator()
{
BAutolock _(fLock);
if (!fHasScanned)
ScanDecorators();
BString name;
get_decorator(name);
return FindDecorator(name);
}
DecorInfo*
DecorInfoUtility::DefaultDecorator()
{
BAutolock _(fLock);
return fList.ItemAt(0);
}
bool
DecorInfoUtility::IsCurrentDecorator(DecorInfo* decor)
{
BAutolock _(fLock);
if (decor == NULL)
return false;
return decor->Path() == CurrentDecorator()->Path();
}
status_t
DecorInfoUtility::SetDecorator(DecorInfo* decor)
{
if (decor == NULL)
return B_BAD_VALUE;
BAutolock _(fLock);
if (decor->IsDefault())
return set_decorator("Default");
return set_decorator(decor->Path());
}
status_t
DecorInfoUtility::SetDecorator(int32 index)
{
BAutolock _(fLock);
if (!fHasScanned)
return B_ERROR;
DecorInfo* decor = DecoratorAt(index);
if (decor == NULL)
return B_BAD_INDEX;
return SetDecorator(decor);
}
status_t
DecorInfoUtility::Preview(DecorInfo* decor, BWindow* window)
{
if (decor == NULL)
return B_BAD_VALUE;
return preview_decorator(decor->Path(), window);
}
DecorInfo*
DecorInfoUtility::_FindDecor(const BString& pathString)
{
if (!fLock.IsLocked()) {
fprintf(stderr, "DecorInfoUtility::_find_decor()\tfailure to lock! - "
"BUG BUG BUG\n");
return NULL;
}
if (pathString == "Default")
return fList.ItemAt(0);
for (int i = 1; i < fList.CountItems(); ++i) {
DecorInfo* decor = fList.ItemAt(i);
BPath path(decor->Ref());
if (path.Path() == pathString || decor->Path() == pathString)
return decor;
}
return NULL;
}
status_t
DecorInfoUtility::_ScanDecorators(BDirectory decoratorDirectory)
{
BAutolock _(fLock);
if (fHasScanned) {
for (int i = fList.CountItems() - 1; i > 0; --i) {
DecorInfo* decorInfo = fList.ItemAt(i);
bool deleted = false;
decorInfo->CheckForChanges(deleted);
if (deleted) {
fList.RemoveItem(decorInfo);
delete decorInfo;
}
}
}
entry_ref ref;
while (decoratorDirectory.GetNextRef(&ref) == B_OK) {
BPath path(&decoratorDirectory);
status_t result = path.Append(ref.name);
if (result != B_OK) {
fprintf(stderr, "DecorInfoUtility::_ScanDecorators()\tFailed to"
"append decorator file to path, skipping: %s.\n", strerror(result));
continue;
}
if (_FindDecor(path.Path()) != NULL)
continue;
DecorInfo* decorInfo = new(std::nothrow) DecorInfo(ref);
if (decorInfo == NULL || decorInfo->InitCheck() != B_OK) {
fprintf(stderr, "DecorInfoUtility::_ScanDecorators()\tInitCheck() "
"failure on decorator, skipping.\n");
delete decorInfo;
continue;
}
fList.AddItem(decorInfo);
}
return B_OK;
}
}