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