xref: /haiku/src/kits/tracker/Utilities.h (revision 1e314683024c28e778a59dd5f7ef27b8d1d9df92)
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 #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 
61 class BMessage;
62 class BVolume;
63 class BBitmap;
64 class BTextView;
65 class BView;
66 
67 namespace BPrivate {
68 
69 class Benaphore;
70 class BPose;
71 class BPoseView;
72 
73 // global variables
74 static const rgb_color kBlack = {0, 0, 0, 255};
75 static const rgb_color kWhite = {255, 255, 255 ,255};
76 
77 const int64 kHalfKBSize = 512;
78 const int64 kKBSize = 1024;
79 const int64 kMBSize = 1048576;
80 const int64 kGBSize = 1073741824;
81 const int64 kTBSize = kGBSize * kKBSize;
82 
83 const int32 kMiniIconSeparator = 3;
84 
85 #ifdef __HAIKU__
86 const color_space kDefaultIconDepth = B_RGBA32;
87 #else
88 const color_space kDefaultIconDepth = B_CMAP8;
89 #endif
90 
91 
92 extern 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 
101 class 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 
126 extern 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
131 class 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
150 class 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
185 void DisallowMetaKeys(BTextView*);
186 void DisallowFilenameKeys(BTextView*);
187 
188 
189 bool ValidateStream(BMallocIO*, uint32, int32 version);
190 
191 
192 bool SecondaryMouseButtonDown(int32 modifiers, int32 buttons);
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,
219 	int32 from, int32 to);
220 extern void FadeRGBA32Vertical(uint32* bits, int32 width, int32 height,
221 	int32 from, int32 to);
222 
223 
224 class FlickerFreeStringView : public BStringView {
225 	// adds support for offscreen bitmap drawing for string views that update
226 	// often this would be better implemented as an option of BStringView
227 	public:
228 		FlickerFreeStringView(BRect bounds, const char* name,
229 			const char* text, uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP,
230 			uint32 flags = B_WILL_DRAW);
231 		FlickerFreeStringView(BRect bounds, const char* name,
232 			const char* text, BBitmap* existingOffscreen,
233 			uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP,
234 			uint32 flags = B_WILL_DRAW);
235 		virtual ~FlickerFreeStringView();
236 		virtual void Draw(BRect);
237 		virtual void AttachedToWindow();
238 		virtual void SetViewColor(rgb_color);
239 		virtual void SetLowColor(rgb_color);
240 
241 	private:
242 		OffscreenBitmap* fBitmap;
243 		rgb_color fViewColor;
244 		rgb_color fLowColor;
245 		BBitmap* fOrigBitmap;
246 
247 		typedef BStringView _inherited;
248 };
249 
250 
251 class DraggableIcon : public BView {
252 	// used to determine a save location for a file
253 	public:
254 		DraggableIcon(BRect, const char*, const char* mimeType, icon_size,
255 			const BMessage*, BMessenger,
256 			uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP,
257 			uint32 flags = B_WILL_DRAW);
258 		virtual ~DraggableIcon();
259 
260 		static BRect PreferredRect(BPoint offset, icon_size);
261 		void SetTarget(BMessenger);
262 
263 	protected:
264 		virtual void AttachedToWindow();
265 		virtual void MouseDown(BPoint);
266 		virtual void Draw(BRect);
267 
268 		virtual bool DragStarted(BMessage* dragMessage);
269 
270 	protected:
271 		BBitmap* fBitmap;
272 		BMessage fMessage;
273 		BMessenger fTarget;
274 };
275 
276 
277 class PositionPassingMenuItem : public BMenuItem {
278 	public:
279 		PositionPassingMenuItem(const char* title, BMessage*,
280 			char shortcut = 0, uint32 modifiers = 0);
281 
282 		PositionPassingMenuItem(BMenu*, BMessage*);
283 
284 	protected:
285 		virtual status_t Invoke(BMessage* = 0);
286 			// appends the invoke location for NewFolder, etc. to use
287 
288 	private:
289 		typedef BMenuItem _inherited;
290 };
291 
292 
293 class Benaphore {
294 	// aka benaphore
295 	public:
296 		Benaphore(const char* name = "Light Lock")
297 		:	fSemaphore(create_sem(0, name)),
298 			fCount(1)
299 		{
300 		}
301 
302 		~Benaphore()
303 		{
304 			delete_sem(fSemaphore);
305 		}
306 
307 		bool Lock()
308 		{
309 			if (atomic_add(&fCount, -1) <= 0)
310 				return acquire_sem(fSemaphore) == B_OK;
311 
312 			return true;
313 		}
314 
315 		void Unlock()
316 		{
317 			if (atomic_add(&fCount, 1) < 0)
318 				release_sem(fSemaphore);
319 		}
320 
321 		bool IsLocked() const
322 		{
323 			return fCount <= 0;
324 		}
325 
326 	private:
327 		sem_id fSemaphore;
328 		int32 fCount;
329 };
330 
331 
332 class SeparatorLine : public BView {
333 	public:
334 		SeparatorLine(BPoint, float, bool vertical, const char* name = "");
335 		virtual void Draw(BRect bounds);
336 };
337 
338 
339 class TitledSeparatorItem : public BMenuItem {
340 	public:
341 		TitledSeparatorItem(const char*);
342 		virtual ~TitledSeparatorItem();
343 
344 		virtual void SetEnabled(bool state);
345 
346 	protected:
347 		virtual void GetContentSize(float* width, float* height);
348 		virtual void Draw();
349 
350 	private:
351 		typedef BMenuItem _inherited;
352 };
353 
354 
355 class LooperAutoLocker {
356 	public:
357 		LooperAutoLocker(BHandler* handler)
358 		:	fHandler(handler),
359 			fHasLock(handler->LockLooper())
360 		{
361 		}
362 
363 		~LooperAutoLocker()
364 		{
365 			if (fHasLock)
366 				fHandler->UnlockLooper();
367 		}
368 
369 		bool operator!() const
370 		{
371 			return !fHasLock;
372 		}
373 
374 		bool IsLocked() const
375 		{
376 			return fHasLock;
377 		}
378 
379 	private:
380 		BHandler* fHandler;
381 		bool fHasLock;
382 };
383 
384 
385 class ShortcutFilter : public BMessageFilter {
386 	public:
387 		ShortcutFilter(uint32 shortcutKey, uint32 shortcutModifier,
388 			uint32 shortcutWhat, BHandler* target);
389 
390 	protected:
391 		filter_result Filter(BMessage*, BHandler**);
392 
393 	private:
394 		uint32 fShortcutKey;
395 		uint32 fShortcutModifier;
396 		uint32 fShortcutWhat;
397 		BHandler* fTarget;
398 };
399 
400 // iterates over all the refs in a message
401 entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*),
402 	void* passThru = 0);
403 const entry_ref* EachEntryRef(const BMessage*,
404 	const entry_ref* (*)(const entry_ref*, void*), void* passThru = 0);
405 
406 entry_ref* EachEntryRef(BMessage*, entry_ref* (*)(entry_ref*, void*),
407 	void* passThru, int32 maxCount);
408 const entry_ref* EachEntryRef(const BMessage*,
409 	const entry_ref* (*)(const entry_ref*, void*), void* passThru,
410 	int32 maxCount);
411 
412 
413 bool ContainsEntryRef(const BMessage*, const entry_ref*);
414 int32 CountRefs(const BMessage*);
415 
416 BMenuItem* EachMenuItem(BMenu* menu, bool recursive,
417 	BMenuItem* (*func)(BMenuItem*));
418 const BMenuItem* EachMenuItem(const BMenu* menu, bool recursive,
419 	BMenuItem* (*func)(const BMenuItem*));
420 
421 int64 StringToScalar(const char* text);
422 	// string to num, understands kB, MB, etc.
423 
424 // misc calls
425 void EmbedUniqueVolumeInfo(BMessage*, const BVolume*);
426 status_t MatchArchivedVolume(BVolume*, const BMessage*, int32 index = 0);
427 void TruncateLeaf(BString* string);
428 
429 void StringFromStream(BString*, BMallocIO*, bool endianSwap = false);
430 void StringToStream(const BString*, BMallocIO*);
431 int32 ArchiveSize(const BString*);
432 
433 extern void EnableNamedMenuItem(BMenu* menu, const char* itemName, bool on);
434 extern void MarkNamedMenuItem(BMenu* menu, const char* itemName, bool on);
435 extern void EnableNamedMenuItem(BMenu* menu, uint32 commandName, bool on);
436 extern void MarkNamedMenuItem(BMenu* menu, uint32 commandName, bool on);
437 extern void DeleteSubmenu(BMenuItem* submenuItem);
438 
439 extern bool BootedInSafeMode();
440 
441 // Now is in kits
442 #if B_BEOS_VERSION <= B_BEOS_VERSION_MAUI && !defined(__HAIKU__)
443 
444 // Should be in kits
445 bool operator==(const rgb_color&, const rgb_color&);
446 bool operator!=(const rgb_color&, const rgb_color&);
447 
448 #endif
449 
450 inline rgb_color
451 Color(int32 r, int32 g, int32 b, int32 alpha = 255)
452 {
453 	rgb_color result;
454 	result.red = (uchar)r;
455 	result.green = (uchar)g;
456 	result.blue = (uchar)b;
457 	result.alpha = (uchar)alpha;
458 
459 	return result;
460 }
461 
462 void PrintToStream(rgb_color color);
463 
464 template <class InitCheckable>
465 void
466 ThrowOnInitCheckError(InitCheckable* item)
467 {
468 	if (!item)
469 		throw (status_t)B_ERROR;
470 
471 	status_t error = item->InitCheck();
472 	if (error != B_OK)
473 		throw (status_t)error;
474 }
475 
476 #if DEBUG
477 #define ThrowOnError(error) _ThrowOnError(error, __FILE__, __LINE__)
478 #define ThrowIfNotSize(error) _ThrowIfNotSize(error, __FILE__, __LINE__)
479 #define ThrowOnErrorWithMessage(error, debugStr) _ThrowOnError(error, debugStr, __FILE__, __LINE__)
480 #else
481 #define ThrowOnError(x) _ThrowOnError(x, 0, 0)
482 #define ThrowIfNotSize(x) _ThrowIfNotSize(x, 0, 0)
483 #define ThrowOnErrorWithMessage(error, debugStr) _ThrowOnError(error, debugStr, __FILE__, __LINE__)
484 #endif
485 
486 void _ThrowOnError(status_t, const char*, int32);
487 void _ThrowIfNotSize(ssize_t, const char*, int32);
488 void _ThrowOnError(status_t, const char* debugStr, const char*, int32);
489 
490 // stub calls that work around BAppFile info inefficiency
491 status_t GetAppSignatureFromAttr(BFile*, char*);
492 status_t GetAppIconFromAttr(BFile*, BBitmap*, icon_size);
493 status_t GetFileIconFromAttr(BNode*, BBitmap*, icon_size);
494 
495 // debugging
496 void HexDump(const void* buffer, int32 length);
497 
498 #if xDEBUG
499 
500 inline void
501 PrintRefToStream(const entry_ref* ref, const char* trailer = "\n")
502 {
503 	if (ref == NULL) {
504 		PRINT(("NULL entry_ref%s", trailer));
505 		return;
506 	}
507 
508 	BPath path;
509 	BEntry entry(ref);
510 	entry.GetPath(&path);
511 	PRINT(("%s%s", path.Path(), trailer));
512 }
513 
514 
515 inline void
516 PrintEntryToStream(const BEntry* entry, const char* trailer = "\n")
517 {
518 	if (entry == NULL) {
519 		PRINT(("NULL entry%s", trailer));
520 		return;
521 	}
522 
523 	BPath path;
524 	entry->GetPath(&path);
525 	PRINT(("%s%s", path.Path(), trailer));
526 }
527 
528 
529 inline void
530 PrintDirToStream(const BDirectory* dir, const char* trailer = "\n")
531 {
532 	if (dir == NULL) {
533 		PRINT(("NULL entry_ref%s", trailer));
534 		return;
535 	}
536 
537 	BPath path;
538 	BEntry entry;
539 	dir->GetEntry(&entry);
540 	entry.GetPath(&path);
541 	PRINT(("%s%s", path.Path(), trailer));
542 }
543 
544 #else
545 
546 inline void PrintRefToStream(const entry_ref*, const char* = 0) {}
547 inline void PrintEntryToStream(const BEntry*, const char* = 0) {}
548 inline void PrintDirToStream(const BDirectory*, const char* = 0) {}
549 
550 #endif
551 
552 #ifdef xDEBUG
553 
554 	extern FILE* logFile;
555 
556 	inline void PrintToLogFile(const char* format, ...)
557 	{
558 		va_list ap;
559 		va_start(ap, fmt);
560 		vfprintf(logFile, fmt, ap);
561 		va_end(ap);
562 	}
563 
564 	#define WRITELOG(_ARGS_)													\
565 		if (logFile == 0) 														\
566 			logFile = fopen("/var/log/tracker.log", "a+"); 						\
567 		if (logFile != 0) {														\
568 			thread_info info;													\
569 			get_thread_info(find_thread(NULL), &info);							\
570 			PrintToLogFile("[t %Ld] \"%s\" (%s:%i) ", system_time(),			\
571 				info.name, __FILE__, __LINE__);									\
572 			PrintToLogFile _ARGS_;												\
573 			PrintToLogFile("\n");												\
574 			fflush(logFile);													\
575 		}
576 
577 #else
578 
579 #define WRITELOG(_ARGS_)
580 
581 #endif
582 
583 // fancy casting macros
584 
585 template <typename NewType, typename OldType>
586 inline NewType assert_cast(OldType castedPointer) {
587 	ASSERT(dynamic_cast<NewType>(castedPointer) != NULL);
588 	return static_cast<NewType>(castedPointer);
589 }
590 
591 // B_SWAP_INT32 have broken signedness, simple cover calls to fix that
592 // should fix up in ByteOrder.h
593 
594 inline int32 SwapInt32(int32 value)
595 	{ return (int32)B_SWAP_INT32((uint32)value); }
596 inline uint32 SwapUInt32(uint32 value) { return B_SWAP_INT32(value); }
597 inline int64 SwapInt64(int64 value)
598 	{ return (int64)B_SWAP_INT64((uint64)value); }
599 inline uint64 SwapUInt64(uint64 value) { return B_SWAP_INT64(value); }
600 
601 
602 extern const float kExactMatchScore;
603 float ComputeTypeAheadScore(const char* text, const char* match,
604 	bool wordMode = false);
605 
606 } // namespace BPrivate
607 
608 #endif	// _UTILITIES_H
609