1/* 2Open Tracker License 3 4Terms and Conditions 5 6Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a copy of 9this software and associated documentation files (the "Software"), to deal in 10the Software without restriction, including without limitation the rights to 11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12of the Software, and to permit persons to whom the Software is furnished to do 13so, subject to the following conditions: 14 15The above copyright notice and this permission notice applies to all licensees 16and shall be included in all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of Be Incorporated shall not be 26used in advertising or otherwise to promote the sale, use or other dealings in 27this Software without prior written authorization from Be Incorporated. 28 29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30of Be Incorporated in the United States and other countries. Other brand product 31names are registered trademarks or trademarks of their respective holders. 32All rights reserved. 33*/ 34#ifndef _UTILITIES_H 35#define _UTILITIES_H 36 37 38#include <ctype.h> 39#include <stdarg.h> 40#include <stdlib.h> 41 42#include <ByteOrder.h> 43#include <Bitmap.h> 44#include <DataIO.h> 45#include <Directory.h> 46#include <Entry.h> 47#include <Font.h> 48#include <GraphicsDefs.h> 49#include <Looper.h> 50#include <MenuItem.h> 51#include <MessageFilter.h> 52#include <Mime.h> 53#include <NaturalCompare.h> 54#include <ObjectList.h> 55#include <Point.h> 56#include <Path.h> 57#include <String.h> 58#include <StringView.h> 59 60 61class BMessage; 62class BVolume; 63class BBitmap; 64class BTextView; 65class BView; 66 67namespace BPrivate { 68 69class Benaphore; 70class BPose; 71class BPoseView; 72 73// global variables 74static const rgb_color kBlack = {0, 0, 0, 255}; 75static const rgb_color kWhite = {255, 255, 255 ,255}; 76 77const int64 kHalfKBSize = 512; 78const int64 kKBSize = 1024; 79const int64 kMBSize = 1048576; 80const int64 kGBSize = 1073741824; 81const int64 kTBSize = kGBSize * kKBSize; 82 83const int32 kMiniIconSeparator = 3; 84 85#ifdef __HAIKU__ 86const color_space kDefaultIconDepth = B_RGBA32; 87#else 88const color_space kDefaultIconDepth = B_CMAP8; 89#endif 90 91 92extern bool gLocalizedNamePreferred; 93 94 95// misc typedefs, constants and structs 96 97// Periodically updated poses (ones with a volume space bar) register 98// themselfs in this global list. This way they can be iterated over instead 99// of sending around update messages. 100 101class PeriodicUpdatePoses { 102 public: 103 PeriodicUpdatePoses(); 104 ~PeriodicUpdatePoses(); 105 106 typedef bool (*PeriodicUpdateCallback)(BPose* pose, void* cookie); 107 108 void AddPose(BPose* pose, BPoseView* poseView, 109 PeriodicUpdateCallback callback, void* cookie); 110 bool RemovePose(BPose* pose, void** cookie); 111 112 void DoPeriodicUpdate(bool forceRedraw); 113 114 private: 115 struct periodic_pose { 116 BPose* pose; 117 BPoseView* pose_view; 118 PeriodicUpdateCallback callback; 119 void* cookie; 120 }; 121 122 Benaphore* fLock; 123 BObjectList<periodic_pose> fPoseList; 124}; 125 126extern PeriodicUpdatePoses gPeriodicUpdatePoses; 127 128 129// PoseInfo is the structure that gets saved as attributes for every node on 130// disk, defining the node's position and visibility 131class PoseInfo { 132 public: 133 static void EndianSwap(void* castToThis); 134 void PrintToStream(); 135 136 bool fInvisible; 137 ino_t fInitedDirectory; 138 // For a location to be valid, fInitedDirectory has to contain 139 // the inode of the items parent directory. This makes it 140 // impossible to for instance zip up files and extract them in 141 // the same location. This should probably be reworked. 142 // Tracker could strip the file location attributes when dropping 143 // files into a closed folder. 144 BPoint fLocation; 145}; 146 147 148// extends PoseInfo adding workspace support; used for desktop 149// poses only 150class ExtendedPoseInfo { 151 public: 152 size_t Size() const; 153 static size_t Size(int32); 154 size_t SizeWithHeadroom() const; 155 static size_t SizeWithHeadroom(size_t); 156 bool HasLocationForFrame(BRect) const; 157 BPoint LocationForFrame(BRect) const; 158 bool SetLocationForFrame(BPoint, BRect); 159 160 static void EndianSwap(void* castToThis); 161 void PrintToStream(); 162 163 uint32 fWorkspaces; 164 bool fInvisible; 165 bool fShowFromBootOnly; 166 bool fReservedBool1; 167 bool fReservedBool2; 168 int32 fReservedInt1; 169 int32 fReservedInt2; 170 int32 fReservedInt3; 171 int32 fReservedInt4; 172 int32 fReservedInt5; 173 174 int32 fNumFrames; 175 struct FrameLocation { 176 BPoint fLocation; 177 BRect fFrame; 178 uint32 fWorkspaces; 179 }; 180 181 FrameLocation fLocations[0]; 182}; 183 184// misc functions 185void DisallowMetaKeys(BTextView*); 186void DisallowFilenameKeys(BTextView*); 187 188 189bool ValidateStream(BMallocIO*, uint32, int32 version); 190 191 192uint32 HashString(const char* string, uint32 seed); 193uint32 AttrHashString(const char* string, uint32 type); 194 195 196class OffscreenBitmap { 197 // a utility class for setting up offscreen bitmaps 198 public: 199 OffscreenBitmap(BRect bounds); 200 OffscreenBitmap(); 201 ~OffscreenBitmap(); 202 203 BView* BeginUsing(BRect bounds); 204 void DoneUsing(); 205 BBitmap* Bitmap() const; 206 // blit this to your view when you are done rendering 207 BView* View() const; 208 // use this to render your image 209 210 private: 211 void NewBitmap(BRect frame); 212 BBitmap* fBitmap; 213}; 214 215 216// bitmap functions 217extern void FadeRGBA32Horizontal(uint32* bits, int32 width, int32 height, 218 int32 from, int32 to); 219extern void FadeRGBA32Vertical(uint32* bits, int32 width, int32 height, 220 int32 from, int32 to); 221 222 223class FlickerFreeStringView : public BStringView { 224 // adds support for offscreen bitmap drawing for string views that update 225 // often this would be better implemented as an option of BStringView 226 public: 227 FlickerFreeStringView(BRect bounds, const char* name, 228 const char* text, uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP, 229 uint32 flags = B_WILL_DRAW); 230 FlickerFreeStringView(BRect bounds, const char* name, 231 const char* text, BBitmap* existingOffscreen, 232 uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP, 233 uint32 flags = B_WILL_DRAW); 234 virtual ~FlickerFreeStringView(); 235 virtual void Draw(BRect); 236 virtual void AttachedToWindow(); 237 virtual void SetViewColor(rgb_color); 238 virtual void SetLowColor(rgb_color); 239 240 private: 241 OffscreenBitmap* fBitmap; 242 rgb_color fViewColor; 243 rgb_color fLowColor; 244 BBitmap* fOrigBitmap; 245 246 typedef BStringView _inherited; 247}; 248 249 250class DraggableIcon : public BView { 251 // used to determine a save location for a file 252 public: 253 DraggableIcon(BRect, const char*, const char* mimeType, icon_size, 254 const BMessage*, BMessenger, 255 uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP, 256 uint32 flags = B_WILL_DRAW); 257 virtual ~DraggableIcon(); 258 259 static BRect PreferredRect(BPoint offset, icon_size); 260 void SetTarget(BMessenger); 261 262 protected: 263 virtual void AttachedToWindow(); 264 virtual void MouseDown(BPoint); 265 virtual void Draw(BRect); 266 267 virtual bool DragStarted(BMessage* dragMessage); 268 269 protected: 270 BBitmap* fBitmap; 271 BMessage fMessage; 272 BMessenger fTarget; 273}; 274 275 276class PositionPassingMenuItem : public BMenuItem { 277 public: 278 PositionPassingMenuItem(const char* title, BMessage*, 279 char shortcut = 0, uint32 modifiers = 0); 280 281 PositionPassingMenuItem(BMenu*, BMessage*); 282 283 protected: 284 virtual status_t Invoke(BMessage* = 0); 285 // appends the invoke location for NewFolder, etc. to use 286 287 private: 288 typedef BMenuItem _inherited; 289}; 290 291 292class Benaphore { 293 // aka benaphore 294 public: 295 Benaphore(const char* name = "Light Lock") 296 : fSemaphore(create_sem(0, name)), 297 fCount(1) 298 { 299 } 300 301 ~Benaphore() 302 { 303 delete_sem(fSemaphore); 304 } 305 306 bool Lock() 307 { 308 if (atomic_add(&fCount, -1) <= 0) 309 return acquire_sem(fSemaphore) == B_OK; 310 311 return true; 312 } 313 314 void Unlock() 315 { 316 if (atomic_add(&fCount, 1) < 0) 317 release_sem(fSemaphore); 318 } 319 320 bool IsLocked() const 321 { 322 return fCount <= 0; 323 } 324 325 private: 326 sem_id fSemaphore; 327 int32 fCount; 328}; 329 330 331class SeparatorLine : public BView { 332 public: 333 SeparatorLine(BPoint, float, bool vertical, const char* name = ""); 334 virtual void Draw(BRect bounds); 335}; 336 337 338class TitledSeparatorItem : public BMenuItem { 339 public: 340 TitledSeparatorItem(const char*); 341 virtual ~TitledSeparatorItem(); 342 343 virtual void SetEnabled(bool state); 344 345 protected: 346 virtual void GetContentSize(float* width, float* height); 347 virtual void Draw(); 348 349 private: 350 typedef BMenuItem _inherited; 351}; 352 353 354class LooperAutoLocker { 355 public: 356 LooperAutoLocker(BHandler* handler) 357 : fHandler(handler), 358 fHasLock(handler->LockLooper()) 359 { 360 } 361 362 ~LooperAutoLocker() 363 { 364 if (fHasLock) 365 fHandler->UnlockLooper(); 366 } 367 368 bool operator!() const 369 { 370 return !fHasLock; 371 } 372 373 bool IsLocked() const 374 { 375 return fHasLock; 376 } 377 378 private: 379 BHandler* fHandler; 380 bool fHasLock; 381}; 382 383 384class MessengerAutoLocker { 385 // move this into AutoLock.h 386 public: 387 MessengerAutoLocker(BMessenger* messenger) 388 : fMessenger(messenger), 389 fHasLock(messenger->LockTarget()) 390 {} 391 392 ~MessengerAutoLocker() 393 { 394 Unlock(); 395 } 396 397 bool operator!() const 398 { 399 return !fHasLock; 400 } 401 402 bool IsLocked() const 403 { 404 return fHasLock; 405 } 406 407 void Unlock() 408 { 409 if (fHasLock) { 410 BLooper* looper; 411 fMessenger->Target(&looper); 412 if (looper) 413 looper->Unlock(); 414 fHasLock = false; 415 } 416 } 417 418 private: 419 BMessenger* fMessenger; 420 bool fHasLock; 421}; 422 423 424class ShortcutFilter : public BMessageFilter { 425 public: 426 ShortcutFilter(uint32 shortcutKey, uint32 shortcutModifier, 427 uint32 shortcutWhat, BHandler* target); 428 429 protected: 430 filter_result Filter(BMessage*, BHandler**); 431 432 private: 433 uint32 fShortcutKey; 434 uint32 fShortcutModifier; 435 uint32 fShortcutWhat; 436 BHandler* fTarget; 437}; 438 439// iterates over all the refs in a message 440entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*), 441 void* passThru = 0); 442const entry_ref* EachEntryRef(const BMessage*, 443 const entry_ref* (*)(const entry_ref*, void*), void* passThru = 0); 444 445entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*), 446 void* passThru, int32 maxCount); 447const entry_ref* EachEntryRef(const BMessage*, 448 const entry_ref* (*)(const entry_ref*, void*), void* passThru, 449 int32 maxCount); 450 451 452bool ContainsEntryRef(const BMessage*, const entry_ref*); 453int32 CountRefs(const BMessage*); 454 455BMenuItem* EachMenuItem(BMenu* menu, bool recursive, 456 BMenuItem* (*func)(BMenuItem*)); 457const BMenuItem* EachMenuItem(const BMenu* menu, bool recursive, 458 BMenuItem* (*func)(const BMenuItem*)); 459 460int64 StringToScalar(const char* text); 461 // string to num, understands kB, MB, etc. 462 463// misc calls 464void EmbedUniqueVolumeInfo(BMessage*, const BVolume*); 465status_t MatchArchivedVolume(BVolume*, const BMessage*, int32 index = 0); 466void TruncateLeaf(BString* string); 467 468void StringFromStream(BString*, BMallocIO*, bool endianSwap = false); 469void StringToStream(const BString*, BMallocIO*); 470int32 ArchiveSize(const BString*); 471 472extern void EnableNamedMenuItem(BMenu* menu, const char* itemName, bool on); 473extern void MarkNamedMenuItem(BMenu* menu, const char* itemName, bool on); 474extern void EnableNamedMenuItem(BMenu* menu, uint32 commandName, bool on); 475extern void MarkNamedMenuItem(BMenu* menu, uint32 commandName, bool on); 476extern void DeleteSubmenu(BMenuItem* submenuItem); 477 478extern bool BootedInSafeMode(); 479 480// Now is in kits 481#if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI && !defined(__HAIKU__) 482 483// Should be in kits 484bool operator==(const rgb_color&, const rgb_color&); 485bool operator!=(const rgb_color&, const rgb_color&); 486 487#endif 488 489inline rgb_color 490Color(int32 r, int32 g, int32 b, int32 alpha = 255) 491{ 492 rgb_color result; 493 result.red = (uchar)r; 494 result.green = (uchar)g; 495 result.blue = (uchar)b; 496 result.alpha = (uchar)alpha; 497 498 return result; 499} 500 501void PrintToStream(rgb_color color); 502 503template <class InitCheckable> 504void 505ThrowOnInitCheckError(InitCheckable* item) 506{ 507 if (!item) 508 throw (status_t)B_ERROR; 509 510 status_t error = item->InitCheck(); 511 if (error != B_OK) 512 throw (status_t)error; 513} 514 515#if DEBUG 516#define ThrowOnError(error) _ThrowOnError(error, __FILE__, __LINE__) 517#define ThrowIfNotSize(error) _ThrowIfNotSize(error, __FILE__, __LINE__) 518#define ThrowOnErrorWithMessage(error, debugStr) _ThrowOnError(error, debugStr, __FILE__, __LINE__) 519#else 520#define ThrowOnError(x) _ThrowOnError(x, 0, 0) 521#define ThrowIfNotSize(x) _ThrowIfNotSize(x, 0, 0) 522#define ThrowOnErrorWithMessage(error, debugStr) _ThrowOnError(error, debugStr, __FILE__, __LINE__) 523#endif 524 525void _ThrowOnError(status_t, const char*, int32); 526void _ThrowIfNotSize(ssize_t, const char*, int32); 527void _ThrowOnError(status_t, const char* debugStr, const char*, int32); 528 529// stub calls that work around BAppFile info inefficiency 530status_t GetAppSignatureFromAttr(BFile*, char*); 531status_t GetAppIconFromAttr(BFile*, BBitmap*, icon_size); 532status_t GetFileIconFromAttr(BNode*, BBitmap*, icon_size); 533 534// debugging 535void HexDump(const void* buffer, int32 length); 536 537#if xDEBUG 538 539inline void 540PrintRefToStream(const entry_ref* ref, const char* trailer = "\n") 541{ 542 if (ref == NULL) { 543 PRINT(("NULL entry_ref%s", trailer)); 544 return; 545 } 546 547 BPath path; 548 BEntry entry(ref); 549 entry.GetPath(&path); 550 PRINT(("%s%s", path.Path(), trailer)); 551} 552 553 554inline void 555PrintEntryToStream(const BEntry* entry, const char* trailer = "\n") 556{ 557 if (entry == NULL) { 558 PRINT(("NULL entry%s", trailer)); 559 return; 560 } 561 562 BPath path; 563 entry->GetPath(&path); 564 PRINT(("%s%s", path.Path(), trailer)); 565} 566 567 568inline void 569PrintDirToStream(const BDirectory* dir, const char* trailer = "\n") 570{ 571 if (dir == NULL) { 572 PRINT(("NULL entry_ref%s", trailer)); 573 return; 574 } 575 576 BPath path; 577 BEntry entry; 578 dir->GetEntry(&entry); 579 entry.GetPath(&path); 580 PRINT(("%s%s", path.Path(), trailer)); 581} 582 583#else 584 585inline void PrintRefToStream(const entry_ref*, const char* = 0) {} 586inline void PrintEntryToStream(const BEntry*, const char* = 0) {} 587inline void PrintDirToStream(const BDirectory*, const char* = 0) {} 588 589#endif 590 591#ifdef xDEBUG 592 593 extern FILE* logFile; 594 595 inline void PrintToLogFile(const char* format, ...) 596 { 597 va_list ap; 598 va_start(ap, fmt); 599 vfprintf(logFile, fmt, ap); 600 va_end(ap); 601 } 602 603 #define WRITELOG(_ARGS_) \ 604 if (logFile == 0) \ 605 logFile = fopen("/var/log/tracker.log", "a+"); \ 606 if (logFile != 0) { \ 607 thread_info info; \ 608 get_thread_info(find_thread(NULL), &info); \ 609 PrintToLogFile("[t %Ld] \"%s\" (%s:%i) ", system_time(), \ 610 info.name, __FILE__, __LINE__); \ 611 PrintToLogFile _ARGS_; \ 612 PrintToLogFile("\n"); \ 613 fflush(logFile); \ 614 } 615 616#else 617 618#define WRITELOG(_ARGS_) 619 620#endif 621 622// fancy casting macros 623 624template <typename NewType, typename OldType> 625inline NewType assert_cast(OldType castedPointer) { 626 ASSERT(dynamic_cast<NewType>(castedPointer) != NULL); 627 return static_cast<NewType>(castedPointer); 628} 629 630// B_SWAP_INT32 have broken signedness, simple cover calls to fix that 631// should fix up in ByteOrder.h 632 633inline int32 SwapInt32(int32 value) 634 { return (int32)B_SWAP_INT32((uint32)value); } 635inline uint32 SwapUInt32(uint32 value) { return B_SWAP_INT32(value); } 636inline int64 SwapInt64(int64 value) 637 { return (int64)B_SWAP_INT64((uint64)value); } 638inline uint64 SwapUInt64(uint64 value) { return B_SWAP_INT64(value); } 639 640 641extern const float kExactMatchScore; 642float ComputeTypeAheadScore(const char* text, const char* match, 643 bool wordMode = false); 644 645} // namespace BPrivate 646 647#endif // _UTILITIES_H 648