1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All 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
61class BMessage;
62class BVolume;
63class BBitmap;
64class BTextView;
65class BView;
66
67namespace BPrivate {
68
69class Benaphore;
70class BPose;
71class BPoseView;
72
73// global variables
74static const rgb_color kBlack = {0, 0, 0, 255};
75static const rgb_color kWhite = {255, 255, 255 ,255};
76
77const int64 kHalfKBSize = 512;
78const int64 kKBSize = 1024;
79const int64 kMBSize = 1048576;
80const int64 kGBSize = 1073741824;
81const int64 kTBSize = kGBSize * kKBSize;
82
83const int32 kMiniIconSeparator = 3;
84
85#ifdef __HAIKU__
86const color_space kDefaultIconDepth = B_RGBA32;
87#else
88const color_space kDefaultIconDepth = B_CMAP8;
89#endif
90
91
92extern 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
101class 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
126extern 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
131class 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
150class 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
185void DisallowMetaKeys(BTextView*);
186void DisallowFilenameKeys(BTextView*);
187
188
189bool ValidateStream(BMallocIO*, uint32, int32 version);
190
191
192uint32 HashString(const char* string, uint32 seed);
193uint32 AttrHashString(const char* string, uint32 type);
194
195
196class 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
217extern void FadeRGBA32Horizontal(uint32* bits, int32 width, int32 height,
218	int32 from, int32 to);
219extern void FadeRGBA32Vertical(uint32* bits, int32 width, int32 height,
220	int32 from, int32 to);
221
222
223class 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
250class 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
276class 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
292class 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
331class SeparatorLine : public BView {
332	public:
333		SeparatorLine(BPoint, float, bool vertical, const char* name = "");
334		virtual void Draw(BRect bounds);
335};
336
337
338class 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
354class 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
384class 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
424class 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
440entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*),
441	void* passThru = 0);
442const entry_ref* EachEntryRef(const BMessage*,
443	const entry_ref* (*)(const entry_ref*, void*), void* passThru = 0);
444
445entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*),
446	void* passThru, int32 maxCount);
447const entry_ref* EachEntryRef(const BMessage*,
448	const entry_ref* (*)(const entry_ref*, void*), void* passThru,
449	int32 maxCount);
450
451
452bool ContainsEntryRef(const BMessage*, const entry_ref*);
453int32 CountRefs(const BMessage*);
454
455BMenuItem* EachMenuItem(BMenu* menu, bool recursive,
456	BMenuItem* (*func)(BMenuItem*));
457const BMenuItem* EachMenuItem(const BMenu* menu, bool recursive,
458	BMenuItem* (*func)(const BMenuItem*));
459
460int64 StringToScalar(const char* text);
461	// string to num, understands kB, MB, etc.
462
463// misc calls
464void EmbedUniqueVolumeInfo(BMessage*, const BVolume*);
465status_t MatchArchivedVolume(BVolume*, const BMessage*, int32 index = 0);
466void TruncateLeaf(BString* string);
467
468void StringFromStream(BString*, BMallocIO*, bool endianSwap = false);
469void StringToStream(const BString*, BMallocIO*);
470int32 ArchiveSize(const BString*);
471
472extern void EnableNamedMenuItem(BMenu* menu, const char* itemName, bool on);
473extern void MarkNamedMenuItem(BMenu* menu, const char* itemName, bool on);
474extern void EnableNamedMenuItem(BMenu* menu, uint32 commandName, bool on);
475extern void MarkNamedMenuItem(BMenu* menu, uint32 commandName, bool on);
476extern void DeleteSubmenu(BMenuItem* submenuItem);
477
478extern 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
484bool operator==(const rgb_color&, const rgb_color&);
485bool operator!=(const rgb_color&, const rgb_color&);
486
487#endif
488
489inline rgb_color
490Color(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
501void PrintToStream(rgb_color color);
502
503template <class InitCheckable>
504void
505ThrowOnInitCheckError(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
525void _ThrowOnError(status_t, const char*, int32);
526void _ThrowIfNotSize(ssize_t, const char*, int32);
527void _ThrowOnError(status_t, const char* debugStr, const char*, int32);
528
529// stub calls that work around BAppFile info inefficiency
530status_t GetAppSignatureFromAttr(BFile*, char*);
531status_t GetAppIconFromAttr(BFile*, BBitmap*, icon_size);
532status_t GetFileIconFromAttr(BNode*, BBitmap*, icon_size);
533
534// debugging
535void HexDump(const void* buffer, int32 length);
536
537#if xDEBUG
538
539inline void
540PrintRefToStream(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
554inline void
555PrintEntryToStream(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
568inline void
569PrintDirToStream(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
585inline void PrintRefToStream(const entry_ref*, const char* = 0) {}
586inline void PrintEntryToStream(const BEntry*, const char* = 0) {}
587inline 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
624template <typename NewType, typename OldType>
625inline 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
633inline int32 SwapInt32(int32 value)
634	{ return (int32)B_SWAP_INT32((uint32)value); }
635inline uint32 SwapUInt32(uint32 value) { return B_SWAP_INT32(value); }
636inline int64 SwapInt64(int64 value)
637	{ return (int64)B_SWAP_INT64((uint64)value); }
638inline uint64 SwapUInt64(uint64 value) { return B_SWAP_INT64(value); }
639
640
641extern const float kExactMatchScore;
642float ComputeTypeAheadScore(const char* text, const char* match,
643	bool wordMode = false);
644
645} // namespace BPrivate
646
647#endif	// _UTILITIES_H
648