xref: /haiku/src/kits/tracker/Utilities.h (revision e688bf23d48bfd1216a0cacbdbda5e35a1bcd779)
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 #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 
61 class BMessage;
62 class BVolume;
63 class BBitmap;
64 class BTextView;
65 class BView;
66 
67 namespace BPrivate {
68 
69 class Benaphore;
70 class BPose;
71 class BPoseView;
72 
73 // global variables
74 static const rgb_color kBlack = {0, 0, 0, 255};
75 static const rgb_color kWhite = {255, 255, 255 ,255};
76 
77 const int64 kHalfKBSize = 512;
78 const int64 kKBSize = 1024;
79 const int64 kMBSize = 1048576;
80 const int64 kGBSize = 1073741824;
81 const int64 kTBSize = kGBSize * kKBSize;
82 
83 const int32 kMiniIconSeparator = 3;
84 
85 #ifdef __HAIKU__
86 const color_space kDefaultIconDepth = B_RGBA32;
87 #else
88 const color_space kDefaultIconDepth = B_CMAP8;
89 #endif
90 
91 
92 extern 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 
101 class 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 
126 extern 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
131 class 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
150 class 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
185 void DisallowMetaKeys(BTextView*);
186 void DisallowFilenameKeys(BTextView*);
187 
188 
189 bool ValidateStream(BMallocIO*, uint32, int32 version);
190 
191 
192 uint32 HashString(const char* string, uint32 seed);
193 uint32 AttrHashString(const char* string, uint32 type);
194 
195 
196 class 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
217 extern void FadeRGBA32Horizontal(uint32* bits, int32 width, int32 height,
218 	int32 from, int32 to);
219 extern void FadeRGBA32Vertical(uint32* bits, int32 width, int32 height,
220 	int32 from, int32 to);
221 
222 
223 class 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 
250 class 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 
276 class 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 
292 class 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 
331 class SeparatorLine : public BView {
332 	public:
333 		SeparatorLine(BPoint, float, bool vertical, const char* name = "");
334 		virtual void Draw(BRect bounds);
335 };
336 
337 
338 class 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 
354 class 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 
384 class 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 
424 class 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
440 entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*),
441 	void* passThru = 0);
442 const entry_ref* EachEntryRef(const BMessage*,
443 	const entry_ref* (*)(const entry_ref*, void*), void* passThru = 0);
444 
445 entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*),
446 	void* passThru, int32 maxCount);
447 const entry_ref* EachEntryRef(const BMessage*,
448 	const entry_ref* (*)(const entry_ref*, void*), void* passThru,
449 	int32 maxCount);
450 
451 
452 bool ContainsEntryRef(const BMessage*, const entry_ref*);
453 int32 CountRefs(const BMessage*);
454 
455 BMenuItem* EachMenuItem(BMenu* menu, bool recursive,
456 	BMenuItem* (*func)(BMenuItem*));
457 const BMenuItem* EachMenuItem(const BMenu* menu, bool recursive,
458 	BMenuItem* (*func)(const BMenuItem*));
459 
460 int64 StringToScalar(const char* text);
461 	// string to num, understands kB, MB, etc.
462 
463 // misc calls
464 void EmbedUniqueVolumeInfo(BMessage*, const BVolume*);
465 status_t MatchArchivedVolume(BVolume*, const BMessage*, int32 index = 0);
466 void TruncateLeaf(BString* string);
467 
468 void StringFromStream(BString*, BMallocIO*, bool endianSwap = false);
469 void StringToStream(const BString*, BMallocIO*);
470 int32 ArchiveSize(const BString*);
471 
472 extern void EnableNamedMenuItem(BMenu* menu, const char* itemName, bool on);
473 extern void MarkNamedMenuItem(BMenu* menu, const char* itemName, bool on);
474 extern void EnableNamedMenuItem(BMenu* menu, uint32 commandName, bool on);
475 extern void MarkNamedMenuItem(BMenu* menu, uint32 commandName, bool on);
476 extern void DeleteSubmenu(BMenuItem* submenuItem);
477 
478 extern 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
484 bool operator==(const rgb_color&, const rgb_color&);
485 bool operator!=(const rgb_color&, const rgb_color&);
486 
487 #endif
488 
489 inline rgb_color
490 Color(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 
501 void PrintToStream(rgb_color color);
502 
503 template <class InitCheckable>
504 void
505 ThrowOnInitCheckError(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 
525 void _ThrowOnError(status_t, const char*, int32);
526 void _ThrowIfNotSize(ssize_t, const char*, int32);
527 void _ThrowOnError(status_t, const char* debugStr, const char*, int32);
528 
529 // stub calls that work around BAppFile info inefficiency
530 status_t GetAppSignatureFromAttr(BFile*, char*);
531 status_t GetAppIconFromAttr(BFile*, BBitmap*, icon_size);
532 status_t GetFileIconFromAttr(BNode*, BBitmap*, icon_size);
533 
534 // debugging
535 void HexDump(const void* buffer, int32 length);
536 
537 #if xDEBUG
538 
539 inline void
540 PrintRefToStream(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 
554 inline void
555 PrintEntryToStream(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 
568 inline void
569 PrintDirToStream(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 
585 inline void PrintRefToStream(const entry_ref*, const char* = 0) {}
586 inline void PrintEntryToStream(const BEntry*, const char* = 0) {}
587 inline 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 
624 template <typename NewType, typename OldType>
625 inline 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 
633 inline int32 SwapInt32(int32 value)
634 	{ return (int32)B_SWAP_INT32((uint32)value); }
635 inline uint32 SwapUInt32(uint32 value) { return B_SWAP_INT32(value); }
636 inline int64 SwapInt64(int64 value)
637 	{ return (int64)B_SWAP_INT64((uint64)value); }
638 inline uint64 SwapUInt64(uint64 value) { return B_SWAP_INT64(value); }
639 
640 
641 extern const float kExactMatchScore;
642 float ComputeTypeAheadScore(const char* text, const char* match,
643 	bool wordMode = false);
644 
645 } // namespace BPrivate
646 
647 #endif	// _UTILITIES_H
648