xref: /haiku/src/kits/app/Handler.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		Handler.cpp
23 //	Author:			Erik Jaesler (erik@cgsoftware.com)
24 //	Description:	BHandler defines the message-handling protocol.
25 //					MessageReceived() is its lynchpin.
26 //------------------------------------------------------------------------------
27 /**
28 	@note	Some musings on the member variable 'fToken'.  In searching a dump
29 			of libbe.so, I found a struct/class called 'TokenSpace', which has
30 			various member functions like 'new_token'.  More intriguing is a
31 			dump of Dano's version of libbe.so:  there is BPrivate::BTokenSpace,
32 			which also has functions like 'NewToken'.  There's more: one
33 			version of BTokenSpace::NewToken takes a pointer to another new
34 			class, BPrivate::BDirectMessageTarget.  Only a constructor,
35 			destructor and vtable are listed for it, so I'm guessing it's an
36 			abstract base class (or not very useful ;).  My guess is that
37 			BDirectMessageTarget facilitates sending messages straight to an
38 			associated BHandler.  Maybe from app_server?  Probably not, since
39 			you'd have to do IPC anyway.  But maybe within the same team, or
40 			even between teams?  It might save unnecessary trips to and from
41 			app_server for messages which otherwise are entirely client-side.
42 
43 			Back to tokens. There are also these functions in R5:
44 				_safe_get_server_token_(const BLooper*, int32*)
45 				BWindow::find_token_and_handler(BMessage*, int32*, BHandler**)
46 				BWindow::get_server_token
47 
48 			and Dano adds a few more provocative sounding functions:
49 				get_handler_token(short, void*) (listed 3 times, actually)
50 				new_handler_token(short, void*)
51 				remove_handler_token(short, void*)
52 
53 			Taken all together, I think there's a sound argument to be made that
54 			each BHandler has an int32 token associated with it in app_server.
55 
56 			Furthermore, there is, in R5, a function set_token_type(long, short)
57 			which leads me to think that although BHandler's have server tokens
58 			associated with them, the tokening facility is, in fact, generic.
59 			These functions would seem to support that theory:
60 				BBitmap::get_server_token
61 				BPicture::set_token
62 
63 			An important question is whether tokens are generated on the client
64 			side and registered with the server or generated on the server and
65 			given back to the client.  The exported functions of TokenSpace in
66 			libbe's dump are:
67 				~TokenSpace
68 				TokenSpace
69 				adjust_free(long, long)
70 				dump()
71 				find_free_entry(long*, long*)
72 				full_search_adjust()
73 				get_token(void**)
74 				get_token(short*, void**)
75 				new_token(long, short, void*)
76 				new_token_array(long)
77 				remove_token(long)
78 				set_token_type(long, short)
79 
80 			TokenSpace functions are also exported from app_server:
81 				~TokenSpace
82 				TokenSpace
83 				adjust_free(long, long)
84 				cleanup_dead(long)
85 				delete_atom(SAtom*)
86 				dump_tokens()
87 				find_free_entry(long*, long*)
88 				full_search_adjust()
89 				get_token(long, void**)
90 				get_token(long, short*, void**)
91 				get_token_by_type(int*, short, long, void**)
92 				grab_atom(long, SAtom**)
93 				iterate_tokens(long, short,
94 							   unsigned long(*)(long, long, short, void*, void*),
95 							   void*)
96 				new_token(long, short, void*)
97 				new_token_array(long)
98 				remove_token(long)
99 				set_token_type(long, short)
100 
101 			While there are common functions in both locations, the fact that
102 			app_server exports TokenSpace functions which libbe.so does not
103 			leads me to believe that libbe.so and app_server each have their own
104 			versions of TokenSpace.  While it's possible that the libbe version
105 			simply acts as a proxy for the app_server version, it seems not
106 			only inefficient but unnecessary as well:  client-side objects
107 			exists in a different "namespace" than server-side objects, so over-
108 			lap between the two token sets shouldn't be an issue.
109 
110 			Obviously, I can't be entirely sure this is how R5 does it, but it
111 			seems like a reasonable design to follow for our purposes.
112  */
113 /**
114 	@note	Thought on "pseudo-atomic" operations in Lock(), LockWithTimeout(),
115 			and Unlock().  Seems like avoiding the possibility of a looper
116 			change during these functions would be the way to go, and having a
117 			semaphore that protects SetLooper() would do the job very nicely.
118 			Maybe that's too heavy-weight a solution, though.
119  */
120 
121 // Standard Includes -----------------------------------------------------------
122 #include <algorithm>
123 #include <stdlib.h>
124 #include <string.h>
125 #include <map>
126 #include <vector>
127 
128 // System Includes -------------------------------------------------------------
129 #include <AppDefs.h>
130 #include <Handler.h>
131 #include <Looper.h>
132 #include <Message.h>
133 #include <MessageFilter.h>
134 #include <Messenger.h>
135 #include <PropertyInfo.h>
136 
137 // Project Includes ------------------------------------------------------------
138 #include <TokenSpace.h>
139 
140 // Local Includes --------------------------------------------------------------
141 
142 // Local Defines ---------------------------------------------------------------
143 
144 // Globals ---------------------------------------------------------------------
145 
146 using std::map;
147 using std::vector;
148 using BPrivate::gDefaultTokens;
149 
150 const char*	gArchiveNameField = "_name";
151 static property_info gHandlerPropInfo[] =
152 {
153 	{
154 		// name
155 		"Suites",
156 		// commands
157 		{ B_GET_PROPERTY },
158 		// specifiers
159 		{ B_DIRECT_SPECIFIER },
160 		// usage
161 		NULL,
162 		// extra data
163 		0,
164 		// types
165 		{ },
166 		// ctypes (compound_type)
167 		{
168 			// ctypes[0]
169 			{
170 				// pairs[0]
171 				{
172 					{
173 						// name
174 						"suites",
175 						// type
176 						B_STRING_TYPE
177 					}
178 				}
179 			},
180 			// ctypes[1]
181 			{
182 				// pairs[1]
183 				{
184 					{
185 						// name
186 						"messages",
187 						// type
188 						B_PROPERTY_INFO_TYPE
189 					}
190 				}
191 			}
192 		},
193 		// reserved
194 		{}
195 	},
196 	{
197 		"Messenger",
198 			{ B_GET_PROPERTY },
199 			{ B_DIRECT_SPECIFIER },
200 			NULL, 0,
201 			{ B_MESSENGER_TYPE },
202 			{},
203 			{}
204 	},
205 	{
206 		"InternalName",
207 			{ B_GET_PROPERTY },
208 			{ B_DIRECT_SPECIFIER },
209 			NULL, 0,
210 			{ B_STRING_TYPE },
211 			{},
212 			{}
213 	},
214 	{}
215 };
216 
217 bool FilterDeleter(void* filter);
218 
219 typedef map<unsigned long, vector<BHandler*> >	THandlerObserverMap;
220 typedef map<unsigned long, vector<BMessenger> >	TMessengerObserverMap;
221 //------------------------------------------------------------------------------
222 // TODO: Change to BPrivate::BObserverList if possible
223 class _ObserverList
224 {
225 	public:
226 		_ObserverList(void);
227 		~_ObserverList(void);
228 		status_t SendNotices(unsigned long, BMessage const *);
229 		status_t StartObserving(BHandler *, unsigned long);
230 		status_t StartObserving(const BMessenger&, unsigned long);
231 		status_t StopObserving(BHandler *, unsigned long);
232 		status_t StopObserving(const BMessenger&, unsigned long);
233 		bool IsEmpty();
234 
235 	private:
236 		THandlerObserverMap		fHandlerMap;
237 		TMessengerObserverMap	fMessengerMap;
238 };
239 //------------------------------------------------------------------------------
240 
241 
242 //------------------------------------------------------------------------------
243 BHandler::BHandler(const char* name)
244 	:	BArchivable(), fName(NULL)
245 {
246 	InitData(name);
247 }
248 //------------------------------------------------------------------------------
249 BHandler::~BHandler()
250 {
251 	if (fName)
252 	{
253 		free(fName);
254 	}
255 
256 	gDefaultTokens.RemoveToken(fToken);
257 }
258 //------------------------------------------------------------------------------
259 BHandler::BHandler(BMessage* data)
260 	:	BArchivable(data), fName(NULL)
261 {
262 	const char* name = NULL;
263 
264 	if (data)
265 	{
266 		data->FindString(gArchiveNameField, &name);
267 	}
268 
269 	InitData(name);
270 }
271 //------------------------------------------------------------------------------
272 BArchivable* BHandler::Instantiate(BMessage* data)
273 {
274 	if (!validate_instantiation(data, "BHandler"))
275 	{
276 		return NULL;
277 	}
278 
279 	return new BHandler(data);
280 }
281 //------------------------------------------------------------------------------
282 status_t BHandler::Archive(BMessage* data, bool deep) const
283 {
284 	status_t err = BArchivable::Archive(data, deep);
285 	if (!err)
286 	{
287 		err = data->AddString(gArchiveNameField, fName);
288 	}
289 
290 	return err;
291 }
292 //------------------------------------------------------------------------------
293 void BHandler::MessageReceived(BMessage* message)
294 {
295 	switch (message->what)
296 	{
297 		case B_GET_PROPERTY:
298 		{
299 			BMessage	Specifier;
300 			int32		form;
301 			const char*	prop;
302 			int32		cur;
303 			status_t	err;
304 
305 			err = message->GetCurrentSpecifier(&cur, &Specifier, &form, &prop);
306 			if (!err)
307 			{
308 				BMessage Reply(B_REPLY);
309 				if (strcmp(prop, "Suites") == 0)
310 				{
311 					if (GetSupportedSuites(&Reply) == B_OK &&
312 						Reply.AddInt32("error", B_OK) == B_OK)
313 					{
314 						message->SendReply(&Reply);
315 					}
316 				}
317 				else if (strcmp(prop, "Messenger") == 0)
318 				{
319 					if (Reply.AddMessenger("result", this) == B_OK &&
320 						Reply.AddInt32("error", B_OK) == B_OK)
321 
322 					{
323 						message->SendReply(&Reply);
324 					}
325 				}
326 				else if (strcmp(prop, "InternalName") == 0)
327 				{
328 					if (Reply.AddString("result", Name()) == B_OK &&
329 						Reply.AddInt32("error", B_OK) == B_OK)
330 
331 					{
332 						message->SendReply(&Reply);
333 					}
334 				}
335 				else
336 				{
337 					// Should never be here
338 					debugger("We are *not* supposed to be here");
339 				}
340 			}
341 			break;
342 		}
343 
344 		default:
345 			if (fNextHandler)
346 			{
347 				fNextHandler->MessageReceived(message);
348 			}
349 			else
350 			{
351 				message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
352 			}
353 			break;
354 	}
355 }
356 //------------------------------------------------------------------------------
357 BLooper* BHandler::Looper() const
358 {
359 	return fLooper;
360 }
361 //------------------------------------------------------------------------------
362 void BHandler::SetName(const char* name)
363 {
364 	if (fName)
365 	{
366 		free(fName);
367 		fName = NULL;
368 	}
369 
370 	if (name)
371 	{
372 		fName = strdup(name);
373 	}
374 }
375 //------------------------------------------------------------------------------
376 const char* BHandler::Name() const
377 {
378 	return fName;
379 }
380 //------------------------------------------------------------------------------
381 void BHandler::SetNextHandler(BHandler* handler)
382 {
383 	if (!fLooper)
384 	{
385 		debugger("handler must belong to looper before setting NextHandler");
386 		fNextHandler = NULL;
387 		return;
388 	}
389 
390 	if (!fLooper->IsLocked())
391 	{
392 		debugger("The handler's looper must be locked before setting NextHandler");
393 		return;
394 	}
395 
396 	if (handler && fLooper != handler->Looper())
397 	{
398 		debugger("The handler and its NextHandler must have the same looper");
399 		return;
400 	}
401 
402 	// NOTE:  I'm sure some sort of threading protection should happen here,
403 	// hopefully the spec-mandated BLooper lock is sufficient.
404 	// TODO: implement correctly
405 	fNextHandler = handler;
406 }
407 //------------------------------------------------------------------------------
408 BHandler* BHandler::NextHandler() const
409 {
410 	return fNextHandler;
411 }
412 //------------------------------------------------------------------------------
413 void BHandler::AddFilter(BMessageFilter* filter)
414 {
415 	// NOTE:  Although the documentation states that the handler must belong to
416 	// a looper and the looper must be locked in order to use this method,
417 	// testing shows that this is not the case in the original implementation.
418 	// We may want to investigate enforcing these rules; it would be interesting
419 	// to see how many apps out there have violated the dictates of the docs.
420 	// For now, though, we'll play nicely.
421 #if 0
422 	if (!fLooper)
423 	{
424 		// TODO: error handling
425 		return false;
426 	}
427 
428 	if (!fLooper->IsLocked())
429 	{
430 		// TODO: error handling
431 		return false;
432 	}
433 #endif
434 
435 	if (!fFilters)
436 	{
437 		fFilters = new BList;
438 	}
439 
440 	fFilters->AddItem(filter);
441 }
442 //------------------------------------------------------------------------------
443 bool BHandler::RemoveFilter(BMessageFilter* filter)
444 {
445 	// NOTE:  Although the documentation states that the handler must belong to
446 	// a looper and the looper must be locked in order to use this method,
447 	// testing shows that this is not the case in the original implementation.
448 	// We may want to investigate enforcing these rules; it would be interesting
449 	// to see how many apps out there have violated the dictates of the docs.
450 	// For now, though, we'll play nicely.
451 #if 0
452 	if (!fLooper)
453 	{
454 		// TODO: error handling
455 		return false;
456 	}
457 
458 	if (!fLooper->IsLocked())
459 	{
460 		// TODO: error handling
461 		return false;
462 	}
463 #endif
464 
465 	if (fFilters)
466 	{
467 		if (fFilters->RemoveItem((void*)filter))
468 		{
469 			filter->SetLooper(NULL);
470 			return true;
471 		}
472 	}
473 
474 	return false;
475 }
476 //------------------------------------------------------------------------------
477 void BHandler::SetFilterList(BList* filters)
478 {
479 /**
480 	@note	Although the documentation states that the handler must belong to
481 			a looper and the looper must be locked in order to use this method,
482 			testing shows that this is not the case in the original implementation.
483  */
484 #if 0
485 	if (!fLooper)
486 	{
487 		// TODO: error handling
488 		return;
489 	}
490 #endif
491 
492 	if (fLooper && !fLooper->IsLocked())
493 	{
494 		debugger("Owning Looper must be locked before calling SetFilterList");
495 		return;
496 	}
497 
498 /**
499 	@note	I would like to use BObjectList internally, but this function is
500 			spec'd such that fFilters would get deleted and then assigned
501 			'filters', which would obviously mess this up.  Wondering if
502 			anyone ever assigns a list of filters and then checks against
503 			FilterList() to see if they are the same.
504  */
505 	// TODO: Explore issues with using BObjectList
506 	if (fFilters)
507 	{
508 		fFilters->DoForEach(FilterDeleter);
509 		delete fFilters;
510 	}
511 
512 	fFilters = filters;
513 	if (fFilters)
514 	{
515 		for (int32 i = 0; i < fFilters->CountItems(); ++i)
516 		{
517 			BMessageFilter* Filter =
518 				static_cast<BMessageFilter*>(fFilters->ItemAt(i));
519 			if (Filter)
520 			{
521 				Filter->SetLooper(fLooper);
522 			}
523 		}
524 	}
525 }
526 //------------------------------------------------------------------------------
527 BList* BHandler::FilterList()
528 {
529 	return fFilters;
530 }
531 //------------------------------------------------------------------------------
532 bool BHandler::LockLooper()
533 {
534 /**
535 	@note	BeBook says that this function "retrieves the handler's looper and
536 			unlocks it in a pseudo-atomic operation, thus avoiding a race
537 			condition."  How "pseudo-atomic" would look completely escapes me,
538 			so we'll go with the dumb version for now.  Maybe I should use a
539 			benaphore?
540 
541 			BeBook mentions handling the case where the handler's looper
542 			changes during this call.  I've attempted a "pseudo-atomic"
543 			operation to check that.
544  */
545 	BLooper* Looper = fLooper;
546 	if (Looper)
547 	{
548 		bool result = Looper->Lock();
549 
550 		// Are we still assigned to the same looper?
551 		if (fLooper == Looper)
552 		{
553 			return result;
554 		}
555 		else if (result)
556 		{
557 			// Our looper is different, and the lock was successful on the old
558 			// one; undo the lock
559 			Looper->Unlock();
560 		}
561 	}
562 
563 	return false;
564 }
565 //------------------------------------------------------------------------------
566 status_t BHandler::LockLooperWithTimeout(bigtime_t timeout)
567 {
568 /**
569 	@note	BeBook says that this function "retrieves the handler's looper and
570 			unlocks it in a pseudo-atomic operation, thus avoiding a race
571 			condition."  How "pseudo-atomic" would look completely escapes me,
572 			so we'll go with the dumb version for now.  Maybe I should use a
573 			benaphore?
574 
575 			BeBook mentions handling the case where the handler's looper
576 			changes during this call.  I've attempted a "pseudo-atomic"
577 			operation to check for that.
578  */
579 	BLooper* Looper = fLooper;
580 	if (Looper)
581 	{
582 		status_t result = Looper->LockWithTimeout(timeout);
583 
584 		// Are we still assigned to the same looper?
585 		if (fLooper == Looper)
586 		{
587 			return result;
588 		}
589 		else
590 		{
591 			// Our looper changed during the lock attempt
592 			if (result == B_OK)
593 			{
594 				// The lock was successful on the old looper; undo the lock
595 				Looper->Unlock();
596 			}
597 
598 			return B_MISMATCHED_VALUES;
599 		}
600 	}
601 
602 	return B_BAD_VALUE;
603 }
604 //------------------------------------------------------------------------------
605 void BHandler::UnlockLooper()
606 {
607 /**
608 	@note	BeBook says that this function "retrieves the handler's looper and
609 			unlocks it in a pseudo-atomic operation, thus avoiding a race
610 			condition."  How "pseudo-atomic" would look completely escapes me,
611 			so we'll go with the dumb version for now.  Maybe I should use a
612 			benaphore?
613 
614 			The solution I used for Lock() and LockWithTimeout() seems out of
615 			place here; if our looper does change while attempting to unlock it,
616 			re-Lock()ing the original looper just doesn't seem right.
617  */
618 	// TODO: implement correctly
619 	BLooper* Looper = fLooper;
620 	if (Looper)
621 	{
622 		Looper->Unlock();
623 	}
624 }
625 //------------------------------------------------------------------------------
626 BHandler* BHandler::ResolveSpecifier(BMessage* msg, int32 index,
627 									 BMessage* specifier, int32 form,
628 									 const char* property)
629 {
630 	// Straight from the BeBook
631 	BPropertyInfo PropertyInfo(gHandlerPropInfo);
632 	if (PropertyInfo.FindMatch(msg, index, specifier, form, property) >= 0)
633 	{
634 		return this;
635 	}
636 
637 	BMessage Reply(B_MESSAGE_NOT_UNDERSTOOD);
638 	Reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
639 	Reply.AddString("message", "Didn't understand the specifier(s)");
640 	msg->SendReply(&Reply);
641 
642 	return NULL;
643 }
644 //------------------------------------------------------------------------------
645 status_t BHandler::GetSupportedSuites(BMessage* data)
646 {
647 /**
648 	@note	This is the output from the original implementation (calling
649 			PrintToStream() on both data and the contained BPropertyInfo):
650 
651 BMessage: what =  (0x0, or 0)
652     entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
653     entry       messages, type='SCTD', c=1, size= 0,
654       property   commands                       types                specifiers
655 --------------------------------------------------------------------------------
656         Suites   PGET                                               1
657                  (RTSC,suites)
658                  (DTCS,messages)
659 
660      Messenger   PGET                          GNSM                 1
661   InternalName   PGET                          RTSC                 1
662 
663 			With a good deal of trial and error, I determined that the
664 			parenthetical clauses are entries in the 'ctypes' field of
665 			property_info.  'ctypes' is an array of 'compound_type', which
666 			contains an array of 'field_pair's.  I haven't the foggiest what
667 			either 'compound_type' or 'field_pair' is for, being as the
668 			scripting docs are so bloody horrible.  The corresponding
669 			property_info array is declared in the globals section.
670  */
671 	status_t err = B_OK;
672 	if (!data)
673 	{
674 		err = B_BAD_VALUE;
675 	}
676 
677 	if (!err)
678 	{
679 		err = data->AddString("suites", "suite/vnd.Be-handler");
680 		if (!err)
681 		{
682 			BPropertyInfo PropertyInfo(gHandlerPropInfo);
683 			err = data->AddFlat("message", &PropertyInfo);
684 		}
685 	}
686 
687 	return err;
688 }
689 //------------------------------------------------------------------------------
690 status_t BHandler::StartWatching(BMessenger Messenger, uint32 what)
691 {
692 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
693 	return fObserverList->StartObserving(Messenger, what);
694 }
695 //------------------------------------------------------------------------------
696 status_t BHandler::StartWatchingAll(BMessenger Messenger)
697 {
698 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
699 	return fObserverList->StartObserving(Messenger, B_OBSERVER_OBSERVE_ALL);
700 }
701 //------------------------------------------------------------------------------
702 status_t BHandler::StopWatching(BMessenger Messenger, uint32 what)
703 {
704 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
705 	return fObserverList->StopObserving(Messenger, what);
706 }
707 //------------------------------------------------------------------------------
708 status_t BHandler::StopWatchingAll(BMessenger Messenger)
709 {
710 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
711 	return fObserverList->StopObserving(Messenger, B_OBSERVER_OBSERVE_ALL);
712 }
713 //------------------------------------------------------------------------------
714 status_t BHandler::StartWatching(BHandler* Handler, uint32 what)
715 {
716 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
717 	return fObserverList->StartObserving(Handler, what);
718 }
719 //------------------------------------------------------------------------------
720 status_t BHandler::StartWatchingAll(BHandler* Handler)
721 {
722 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
723 	return fObserverList->StartObserving(Handler, B_OBSERVER_OBSERVE_ALL);
724 }
725 //------------------------------------------------------------------------------
726 status_t BHandler::StopWatching(BHandler* Handler, uint32 what)
727 {
728 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
729 	return fObserverList->StopObserving(Handler, what);
730 }
731 //------------------------------------------------------------------------------
732 status_t BHandler::StopWatchingAll(BHandler* Handler)
733 {
734 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
735 	return fObserverList->StopObserving(Handler, B_OBSERVER_OBSERVE_ALL);
736 }
737 //------------------------------------------------------------------------------
738 status_t BHandler::Perform(perform_code d, void* arg)
739 {
740 	return BArchivable::Perform(d, arg);
741 }
742 //------------------------------------------------------------------------------
743 void BHandler::SendNotices(uint32 what, const BMessage* msg)
744 {
745 	fObserverList ? fObserverList : fObserverList = new _ObserverList;
746 	fObserverList->SendNotices(what, msg);
747 }
748 //------------------------------------------------------------------------------
749 bool BHandler::IsWatched() const
750 {
751 	return fObserverList && !fObserverList->IsEmpty();
752 }
753 //------------------------------------------------------------------------------
754 void BHandler::_ReservedHandler2()
755 {
756 	// Unused
757 	;
758 }
759 //------------------------------------------------------------------------------
760 void BHandler::_ReservedHandler3()
761 {
762 	// Unused
763 	;
764 }
765 //------------------------------------------------------------------------------
766 void BHandler::_ReservedHandler4()
767 {
768 	// Unused
769 	;
770 }
771 //------------------------------------------------------------------------------
772 void BHandler::InitData(const char* name)
773 {
774 	SetName(name);
775 
776 	fLooper			= NULL;
777 	fNextHandler	= NULL;
778 	fFilters		= NULL;
779 	fObserverList	= NULL;
780 
781 	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
782 }
783 //------------------------------------------------------------------------------
784 BHandler::BHandler(const BHandler& )
785 {
786 	// No copy construction allowed.
787 	;
788 }
789 //------------------------------------------------------------------------------
790 BHandler& BHandler::operator=(const BHandler& )
791 {
792 	// No assignments allowed.
793 	return *this;
794 }
795 //------------------------------------------------------------------------------
796 void BHandler::SetLooper(BLooper* loop)
797 {
798 	fLooper = loop;
799 }
800 //------------------------------------------------------------------------------
801 
802 
803 //------------------------------------------------------------------------------
804 //	#pragma mark -
805 //	#pragma mark _ObserverList
806 //	#pramga mark -
807 //------------------------------------------------------------------------------
808 _ObserverList::_ObserverList(void)
809 {
810 }
811 //------------------------------------------------------------------------------
812 _ObserverList::~_ObserverList(void)
813 {
814 }
815 //------------------------------------------------------------------------------
816 status_t _ObserverList::SendNotices(unsigned long what, BMessage const* Message)
817 {
818 	// Having to new a temporary is really irritating ...
819 	BMessage* CopyMsg = NULL;
820 	if (Message)
821 	{
822 		CopyMsg = new BMessage(*Message);
823 		CopyMsg->what = B_OBSERVER_NOTICE_CHANGE;
824 		CopyMsg->AddInt32(B_OBSERVE_ORIGINAL_WHAT, Message->what);
825 	}
826 	else
827 	{
828 		CopyMsg = new BMessage(B_OBSERVER_NOTICE_CHANGE);
829 	}
830 
831 	CopyMsg->AddInt32(B_OBSERVE_WHAT_CHANGE, what);
832 
833 	vector<BHandler*>& Handlers = fHandlerMap[what];
834 	for (uint32 i = 0; i < Handlers.size(); ++i)
835 	{
836 		BMessenger msgr(Handlers[i]);
837 		msgr.SendMessage(CopyMsg);
838 	}
839 
840 	vector<BMessenger>& Messengers = fMessengerMap[what];
841 	for (uint32 i = 0; i < Messengers.size(); ++i)
842 	{
843 		Messengers[i].SendMessage(CopyMsg);
844 	}
845 
846 	// Gotta make sure to clean up the annoying temporary ...
847 	delete CopyMsg;
848 
849 	return B_OK;
850 }
851 //------------------------------------------------------------------------------
852 status_t _ObserverList::StartObserving(BHandler* Handler, unsigned long what)
853 {
854 	if (!Handler)
855 	{
856 		return B_BAD_HANDLER;
857 	}
858 
859 	vector<BHandler*>& Handlers = fHandlerMap[what];
860 	vector<BHandler*>::iterator iter;
861 	iter = find(Handlers.begin(), Handlers.end(), Handler);
862 	if (iter != Handlers.end())
863 	{
864 		// TODO: verify
865 		return B_OK;
866 	}
867 
868 	Handlers.push_back(Handler);
869 	return B_OK;
870 }
871 //------------------------------------------------------------------------------
872 status_t _ObserverList::StartObserving(const BMessenger& Messenger,
873 									   unsigned long what)
874 {
875 	vector<BMessenger>& Messengers = fMessengerMap[what];
876 	vector<BMessenger>::iterator iter;
877 	iter = find(Messengers.begin(), Messengers.end(), Messenger);
878 	if (iter != Messengers.end())
879 	{
880 		// TODO: verify
881 		return B_OK;
882 	}
883 
884 	Messengers.push_back(Messenger);
885 	return B_OK;
886 }
887 //------------------------------------------------------------------------------
888 status_t _ObserverList::StopObserving(BHandler* Handler, unsigned long what)
889 {
890 	if (Handler)
891 	{
892 		vector<BHandler*>& Handlers = fHandlerMap[what];
893 		vector<BHandler*>::iterator iter;
894 		iter = find(Handlers.begin(), Handlers.end(), Handler);
895 		if (iter != Handlers.end())
896 		{
897 			Handlers.erase(iter);
898 			if (Handlers.empty())
899 			{
900 				fHandlerMap.erase(what);
901 			}
902 			return B_OK;
903 		}
904 	}
905 
906 	return B_BAD_HANDLER;
907 }
908 //------------------------------------------------------------------------------
909 status_t _ObserverList::StopObserving(const BMessenger& Messenger,
910 									  unsigned long what)
911 {
912 	// ???:	What if you call StartWatching(MyMsngr, aWhat) and then call
913 	//		StopWatchingAll(MyMsnger)?  Will MyMsnger be removed from the aWhat
914 	//		watcher list?  For now, we'll assume that they're discreet lists
915 	//		which do no cross checking; i.e., MyMsnger would *not* be removed in
916 	//		this scenario.
917 	vector<BMessenger>& Messengers = fMessengerMap[what];
918 	vector<BMessenger>::iterator iter;
919 	iter = find(Messengers.begin(), Messengers.end(), Messenger);
920 	if (iter != Messengers.end())
921 	{
922 		Messengers.erase(iter);
923 		if (Messengers.empty())
924 		{
925 			fMessengerMap.erase(what);
926 		}
927 		return B_OK;
928 	}
929 
930 	return B_BAD_HANDLER;
931 }
932 //------------------------------------------------------------------------------
933 bool _ObserverList::IsEmpty()
934 {
935 	return fHandlerMap.empty() && fMessengerMap.empty();
936 }
937 //------------------------------------------------------------------------------
938 
939 
940 //------------------------------------------------------------------------------
941 bool FilterDeleter(void* filter)
942 {
943 	BMessageFilter* Filter = static_cast<BMessageFilter*>(filter);
944 	if (Filter)
945 	{
946 		delete Filter;
947 		Filter = NULL;
948 	}
949 
950 	return false;
951 }
952 //------------------------------------------------------------------------------
953 
954 /*
955  * $Log $
956  *
957  * $Id  $
958  *
959  */
960 
961