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