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