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