tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / DecorInfo.cpp
blob883eb8f09a31521f02e511c40fcd344633ba1c32
1 /*
2 * Public domain source code.
4 * Author:
5 * Joseph "looncraz" Groover <looncraz@satx.rr.com>
6 */
9 #include <DecorInfo.h>
11 #include <new>
12 #include <stdio.h>
14 #include <Autolock.h>
15 #include <FindDirectory.h>
16 #include <Path.h>
17 #include <Resources.h>
18 #include <SystemCatalog.h>
20 #include <DecoratorPrivate.h>
23 #define B_TRANSLATION_CONTEXT "Default decorator about box"
26 namespace BPrivate {
29 DecorInfo::DecorInfo()
31 fVersion(0),
32 fModificationTime(0),
33 fInitStatus(B_NO_INIT)
38 DecorInfo::DecorInfo(const BString& path)
40 fPath(path),
41 fVersion(0),
42 fModificationTime(0),
43 fInitStatus(B_NO_INIT)
45 BEntry entry(path.String(), true);
46 entry.GetRef(&fRef);
48 _Init();
52 DecorInfo::DecorInfo(const entry_ref& ref)
54 fRef(ref),
55 fVersion(0),
56 fModificationTime(0),
57 fInitStatus(B_NO_INIT)
59 BPath path(&ref);
60 fPath = path.Path();
62 _Init();
66 DecorInfo::~DecorInfo()
71 status_t
72 DecorInfo::SetTo(const entry_ref& ref)
74 Unset();
76 BPath path(&ref);
77 fPath = path.Path();
78 fRef = ref;
79 _Init();
81 return InitCheck();
85 status_t
86 DecorInfo::SetTo(BString path)
88 BEntry entry(path.String(), true);
89 entry_ref ref;
90 entry.GetRef(&ref);
91 return SetTo(ref);
95 status_t
96 DecorInfo::InitCheck() const
98 return fInitStatus;
102 void
103 DecorInfo::Unset()
105 fRef = entry_ref();
106 fPath = "";
107 fName = "";
108 fAuthors = "";
109 fShortDescription = "";
110 fLicenseURL = "";
111 fLicenseName = "";
112 fSupportURL = "";
113 fVersion = 0;
114 fModificationTime = 0;
115 fInitStatus = B_NO_INIT;
119 bool
120 DecorInfo::IsDefault() const
122 return fInitStatus == B_OK && fPath == "Default";
126 BString
127 DecorInfo::Path() const
129 return fPath;
133 const entry_ref*
134 DecorInfo::Ref() const
136 if (InitCheck() != B_OK || IsDefault())
137 return NULL;
138 return &fRef;
142 BString
143 DecorInfo::Name() const
145 return fName;
149 BString
150 DecorInfo::ShortcutName() const
152 if (Ref())
153 return fRef.name;
154 return Name();
158 BString
159 DecorInfo::Authors() const
161 return fAuthors;
165 BString
166 DecorInfo::ShortDescription() const
168 return fShortDescription;
172 BString
173 DecorInfo::LongDescription() const
175 return fLongDescription;
179 BString
180 DecorInfo::LicenseURL() const
182 return fLicenseURL;
186 BString
187 DecorInfo::LicenseName() const
189 return fLicenseName;
193 BString
194 DecorInfo::SupportURL() const
196 return fSupportURL;
200 float
201 DecorInfo::Version() const
203 return fVersion;
207 time_t
208 DecorInfo::ModificationTime() const
210 return fModificationTime;
214 bool
215 DecorInfo::CheckForChanges(bool& deleted)
217 if (InitCheck() != B_OK)
218 return false;
220 BEntry entry(&fRef);
222 if (entry.InitCheck() != B_OK)
223 return false;
225 if (!entry.Exists()) {
226 deleted = true;
227 return true;
230 time_t modtime = 0;
231 if (entry.GetModificationTime(&modtime) != B_OK) {
232 fprintf(stderr, "DecorInfo::CheckForChanges()\tERROR: "
233 "BEntry:GetModificationTime() failed\n");
234 return false;
237 if (fModificationTime != modtime) {
238 _Init(true);
239 return true;
242 return false;
246 void
247 DecorInfo::_Init(bool isUpdate)
249 if (!isUpdate && InitCheck() != B_NO_INIT) {
250 // TODO: remove after validation
251 fprintf(stderr, "DecorInfo::_Init()\tImproper init state\n");
252 return;
255 BEntry entry;
257 if (fPath == "Default") {
258 if (isUpdate) {
259 // should never happen
260 fprintf(stderr, "DecorInfo::_Init(true)\tBUG BUG updating default"
261 "decorator!?!?!\n");
262 return;
265 fAuthors = "DarkWyrm, Stephan Aßmus, Clemens Zeidler, Ingo Weinhold";
266 fLongDescription = fShortDescription;
267 fLicenseURL = "http://";
268 fLicenseName = "MIT";
269 fSupportURL = "http://www.haiku-os.org/";
270 fVersion = 0.5;
271 fInitStatus = B_OK;
273 fName = gSystemCatalog.GetString(B_TRANSLATE_MARK("Default"),
274 B_TRANSLATION_CONTEXT);
275 fShortDescription = gSystemCatalog.GetString(B_TRANSLATE_MARK(
276 "Default Haiku window decorator."),
277 B_TRANSLATION_CONTEXT);
279 // The following is to get the modification time of the app_server
280 // and, thusly, the Default decorator...
281 // If you can make it more simple, please do!
282 BPath path;
283 find_directory(B_SYSTEM_SERVERS_DIRECTORY, &path);
284 path.Append("app_server");
285 entry.SetTo(path.Path(), true);
286 if (!entry.Exists()) {
287 fprintf(stderr, "Server MIA the world has become its slave! "
288 "Call the CIA!\n");
289 return;
292 entry.GetModificationTime(&fModificationTime);
293 return;
296 // Is a file system object...
298 entry.SetTo(&fRef, true); // follow link
299 if (entry.InitCheck() != B_OK) {
300 fInitStatus = entry.InitCheck();
301 return;
304 if (!entry.Exists()) {
305 if (isUpdate) {
306 fprintf(stderr, "DecorInfo::_Init()\tERROR: decorator deleted"
307 " after CheckForChanges() found it!\n");
308 fprintf(stderr, "DecorInfo::_Init()\tERROR: DecorInfo will "
309 "Unset\n");
310 Unset();
312 return;
315 // update fRef to match file system object
316 entry.GetRef(&fRef);
317 entry.GetModificationTime(&fModificationTime);
319 BResources resources(&fRef);
320 if (resources.InitCheck() != B_OK) {
321 fprintf(stderr, "DecorInfo::_Init()\t BResource InitCheck() failure\n");
322 return;
325 size_t infoSize = 0;
326 const void* infoData = resources.LoadResource(B_MESSAGE_TYPE,
327 "be:decor:info", &infoSize);
328 BMessage infoMessage;
330 if (infoData == NULL || infoSize == 0
331 || infoMessage.Unflatten((const char*)infoData) != B_OK) {
332 fprintf(stderr, "DecorInfo::_init()\tNo extended information found for"
333 " \"%s\"\n", fRef.name);
334 } else {
335 infoMessage.FindString("name", &fName);
336 infoMessage.FindString("authors", &fAuthors);
337 infoMessage.FindString("short_descr", &fShortDescription);
338 infoMessage.FindString("long_descr", &fLongDescription);
339 infoMessage.FindString("lic_url", &fLicenseURL);
340 infoMessage.FindString("lic_name", &fLicenseName);
341 infoMessage.FindString("support_url", &fSupportURL);
342 infoMessage.FindFloat ("version", &fVersion);
345 fInitStatus = B_OK;
346 fName = fRef.name;
350 // #pragma mark - DecorInfoUtility
353 DecorInfoUtility::DecorInfoUtility(bool scanNow)
355 fHasScanned(false)
357 // get default decorator from app_server
358 DecorInfo* info = new(std::nothrow) DecorInfo("Default");
359 if (info == NULL || info->InitCheck() != B_OK) {
360 delete info;
361 fprintf(stderr, "DecorInfoUtility::constructor\tdefault decorator's "
362 "DecorInfo failed InitCheck()\n");
363 return;
366 fList.AddItem(info);
368 if (scanNow)
369 ScanDecorators();
373 DecorInfoUtility::~DecorInfoUtility()
375 BAutolock _(fLock);
376 for (int i = fList.CountItems() - 1; i >= 0; --i)
377 delete fList.ItemAt(i);
381 status_t
382 DecorInfoUtility::ScanDecorators()
384 status_t result;
386 BPath systemPath;
387 result = find_directory(B_SYSTEM_ADDONS_DIRECTORY, &systemPath);
388 if (result == B_OK)
389 result = systemPath.Append("decorators");
391 if (result == B_OK) {
392 BDirectory systemDirectory(systemPath.Path());
393 result = systemDirectory.InitCheck();
394 if (result == B_OK) {
395 result = _ScanDecorators(systemDirectory);
396 if (result != B_OK) {
397 fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
398 strerror(result));
399 return result;
404 BPath systemNonPackagedPath;
405 result = find_directory(B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
406 &systemNonPackagedPath);
407 if (result == B_OK)
408 result = systemNonPackagedPath.Append("decorators");
410 if (result == B_OK) {
411 BDirectory systemNonPackagedDirectory(systemNonPackagedPath.Path());
412 result = systemNonPackagedDirectory.InitCheck();
413 if (result == B_OK) {
414 result = _ScanDecorators(systemNonPackagedDirectory);
415 if (result != B_OK) {
416 fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
417 strerror(result));
418 return result;
423 BPath userPath;
424 result = find_directory(B_USER_ADDONS_DIRECTORY, &userPath);
425 if (result == B_OK)
426 result = userPath.Append("decorators");
428 if (result == B_OK) {
429 BDirectory userDirectory(userPath.Path());
430 result = userDirectory.InitCheck();
431 if (result == B_OK) {
432 result = _ScanDecorators(userDirectory);
433 if (result != B_OK) {
434 fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
435 strerror(result));
436 return result;
441 BPath userNonPackagedPath;
442 result = find_directory(B_USER_NONPACKAGED_ADDONS_DIRECTORY,
443 &userNonPackagedPath);
444 if (result == B_OK)
445 result = userNonPackagedPath.Append("decorators");
447 if (result == B_OK) {
448 BDirectory userNonPackagedDirectory(userNonPackagedPath.Path());
449 result = userNonPackagedDirectory.InitCheck();
450 if (result == B_OK) {
451 result = _ScanDecorators(userNonPackagedDirectory);
452 if (result != B_OK) {
453 fprintf(stderr, "DecorInfoUtility::ScanDecorators()\tERROR: %s\n",
454 strerror(result));
455 return result;
460 fHasScanned = true;
462 return B_OK;
466 int32
467 DecorInfoUtility::CountDecorators()
469 BAutolock _(fLock);
470 if (!fHasScanned)
471 ScanDecorators();
473 return fList.CountItems();
477 DecorInfo*
478 DecorInfoUtility::DecoratorAt(int32 index)
480 BAutolock _(fLock);
481 return fList.ItemAt(index);
485 DecorInfo*
486 DecorInfoUtility::FindDecorator(const BString& string)
488 if (string.Length() == 0)
489 return CurrentDecorator();
491 if (string.ICompare("default") == 0)
492 return DefaultDecorator();
494 BAutolock _(fLock);
495 if (!fHasScanned)
496 ScanDecorators();
498 // search by path
499 DecorInfo* decor = _FindDecor(string);
500 if (decor != NULL)
501 return decor;
503 // search by name or short cut name
504 for (int i = 1; i < fList.CountItems(); ++i) {
505 decor = fList.ItemAt(i);
506 if (string.ICompare(decor->ShortcutName()) == 0
507 || string.ICompare(decor->Name()) == 0) {
508 return decor;
512 return NULL;
516 DecorInfo*
517 DecorInfoUtility::CurrentDecorator()
519 BAutolock _(fLock);
520 if (!fHasScanned)
521 ScanDecorators();
523 BString name;
524 get_decorator(name);
525 return FindDecorator(name);
529 DecorInfo*
530 DecorInfoUtility::DefaultDecorator()
532 BAutolock _(fLock);
533 return fList.ItemAt(0);
537 bool
538 DecorInfoUtility::IsCurrentDecorator(DecorInfo* decor)
540 BAutolock _(fLock);
541 if (decor == NULL)
542 return false;
543 return decor->Path() == CurrentDecorator()->Path();
547 status_t
548 DecorInfoUtility::SetDecorator(DecorInfo* decor)
550 if (decor == NULL)
551 return B_BAD_VALUE;
553 BAutolock _(fLock);
554 if (decor->IsDefault())
555 return set_decorator("Default");
557 return set_decorator(decor->Path());
561 status_t
562 DecorInfoUtility::SetDecorator(int32 index)
564 BAutolock _(fLock);
565 if (!fHasScanned)
566 return B_ERROR;
568 DecorInfo* decor = DecoratorAt(index);
569 if (decor == NULL)
570 return B_BAD_INDEX;
572 return SetDecorator(decor);
576 status_t
577 DecorInfoUtility::Preview(DecorInfo* decor, BWindow* window)
579 if (decor == NULL)
580 return B_BAD_VALUE;
582 return preview_decorator(decor->Path(), window);
586 // #pargma mark - private
589 DecorInfo*
590 DecorInfoUtility::_FindDecor(const BString& pathString)
592 // find decor by path and path alone!
593 if (!fLock.IsLocked()) {
594 fprintf(stderr, "DecorInfoUtility::_find_decor()\tfailure to lock! - "
595 "BUG BUG BUG\n");
596 return NULL;
599 if (pathString == "Default")
600 return fList.ItemAt(0);
602 for (int i = 1; i < fList.CountItems(); ++i) {
603 DecorInfo* decor = fList.ItemAt(i);
604 // Find the DecoratorInfo either by its true current location or by
605 // what we still think the location is (before we had a chance to
606 // update). NOTE: This will only catch the case when the user moved the
607 // folder in which the add-on file lives. It will not work when the user
608 // moves the add-on file itself or renames it.
609 BPath path(decor->Ref());
610 if (path.Path() == pathString || decor->Path() == pathString)
611 return decor;
614 return NULL;
618 status_t
619 DecorInfoUtility::_ScanDecorators(BDirectory decoratorDirectory)
621 BAutolock _(fLock);
623 // First, run through our list and DecorInfos CheckForChanges()
624 if (fHasScanned) {
625 for (int i = fList.CountItems() - 1; i > 0; --i) {
626 DecorInfo* decorInfo = fList.ItemAt(i);
628 bool deleted = false;
629 decorInfo->CheckForChanges(deleted);
631 if (deleted) {
632 fList.RemoveItem(decorInfo);
633 delete decorInfo;
638 entry_ref ref;
639 // Now, look at file system, skip the entries for which we already have
640 // a DecorInfo in the list.
641 while (decoratorDirectory.GetNextRef(&ref) == B_OK) {
642 BPath path(&decoratorDirectory);
643 status_t result = path.Append(ref.name);
644 if (result != B_OK) {
645 fprintf(stderr, "DecorInfoUtility::_ScanDecorators()\tFailed to"
646 "append decorator file to path, skipping: %s.\n", strerror(result));
647 continue;
649 if (_FindDecor(path.Path()) != NULL)
650 continue;
652 DecorInfo* decorInfo = new(std::nothrow) DecorInfo(ref);
653 if (decorInfo == NULL || decorInfo->InitCheck() != B_OK) {
654 fprintf(stderr, "DecorInfoUtility::_ScanDecorators()\tInitCheck() "
655 "failure on decorator, skipping.\n");
656 delete decorInfo;
657 continue;
660 fList.AddItem(decorInfo);
663 return B_OK;
667 } // namespace BPrivate