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