15edcfe96SAxel Dörfler/*
2be902ac4SJohn Scipione * Copyright 2001-2014 Haiku, Inc. All rights reserved.
35edcfe96SAxel Dörfler * Distributed under the terms of the MIT License.
45edcfe96SAxel Dörfler *
55edcfe96SAxel Dörfler * Authors:
6090dcfd4SAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
7be902ac4SJohn Scipione *		Erik Jaesler, erik@cgsoftware.com
85edcfe96SAxel Dörfler */
95edcfe96SAxel Dörfler
1052a38012Sejakowatz
115edcfe96SAxel Dörfler#include <TokenSpace.h>
1252a38012Sejakowatz
1352a38012Sejakowatz#include <AppDefs.h>
1452a38012Sejakowatz#include <Handler.h>
1552a38012Sejakowatz#include <Looper.h>
1652a38012Sejakowatz#include <Message.h>
1752a38012Sejakowatz#include <MessageFilter.h>
1852a38012Sejakowatz#include <Messenger.h>
1952a38012Sejakowatz#include <PropertyInfo.h>
2052a38012Sejakowatz
215edcfe96SAxel Dörfler#include <algorithm>
22f6c08206SAxel Dörfler#include <new>
235edcfe96SAxel Dörfler#include <stdlib.h>
24252f4767SRyan Leavengood#include <stdio.h>
255edcfe96SAxel Dörfler#include <string.h>
265edcfe96SAxel Dörfler#include <vector>
2752a38012Sejakowatz
2852a38012Sejakowatzusing std::map;
2952a38012Sejakowatzusing std::vector;
3052a38012Sejakowatzusing BPrivate::gDefaultTokens;
3152a38012Sejakowatz
3247761c47SAxel Dörfler
33f6c08206SAxel Dörflerstatic const char* kArchiveNameField = "_name";
34f6c08206SAxel Dörfler
35f6c08206SAxel Dörflerstatic const uint32 kMsgStartObserving = '_OBS';
36f6c08206SAxel Dörflerstatic const uint32 kMsgStopObserving = '_OBP';
37f6c08206SAxel Dörflerstatic const char* kObserveTarget = "be:observe_target";
38f6c08206SAxel Dörfler
3947761c47SAxel Dörfler
4047761c47SAxel Dörflerstatic property_info sHandlerPropInfo[] = {
4152a38012Sejakowatz	{
4247761c47SAxel Dörfler		"Suites",					// name
4347761c47SAxel Dörfler		{ B_GET_PROPERTY },			// commands
4447761c47SAxel Dörfler		{ B_DIRECT_SPECIFIER },		// specifiers
4547761c47SAxel Dörfler		NULL,						// usage
4647761c47SAxel Dörfler		0,							// extra data
4747761c47SAxel Dörfler		{ 0 },						// types
4847761c47SAxel Dörfler		{							// ctypes (compound_type)
4947761c47SAxel Dörfler			{						// ctypes[0]
5047761c47SAxel Dörfler				{					// pairs[0]
5152a38012Sejakowatz					{
5247761c47SAxel Dörfler						"suites",		// name
5347761c47SAxel Dörfler						B_STRING_TYPE	// type
5417e0fc6bSKarsten Heimrich					}
5552a38012Sejakowatz				}
5652a38012Sejakowatz			},
5747761c47SAxel Dörfler			{						// ctypes[1]
5847761c47SAxel Dörfler				{					// pairs[0]
5952a38012Sejakowatz					{
6052a38012Sejakowatz						"messages",
6152a38012Sejakowatz						B_PROPERTY_INFO_TYPE
6252a38012Sejakowatz					}
6352a38012Sejakowatz				}
6452a38012Sejakowatz			}
6552a38012Sejakowatz		},
6647761c47SAxel Dörfler		{}		// reserved
6752a38012Sejakowatz	},
6852a38012Sejakowatz	{
6952a38012Sejakowatz		"Messenger",
70ec9673bfSejakowatz			{ B_GET_PROPERTY },
71ec9673bfSejakowatz			{ B_DIRECT_SPECIFIER },
7252a38012Sejakowatz			NULL, 0,
7352a38012Sejakowatz			{ B_MESSENGER_TYPE },
7447761c47SAxel Dörfler			{},
7547761c47SAxel Dörfler			{}
7652a38012Sejakowatz	},
7752a38012Sejakowatz	{
7852a38012Sejakowatz		"InternalName",
79ec9673bfSejakowatz			{ B_GET_PROPERTY },
80ec9673bfSejakowatz			{ B_DIRECT_SPECIFIER },
8152a38012Sejakowatz			NULL, 0,
8252a38012Sejakowatz			{ B_STRING_TYPE },
8347761c47SAxel Dörfler			{},
8447761c47SAxel Dörfler			{}
8552a38012Sejakowatz	},
8616af9b4cSHumdinger
8716af9b4cSHumdinger	{ 0 }
8852a38012Sejakowatz};
8952a38012Sejakowatz
90be902ac4SJohn Scipionebool FilterDeleter(void* filter);
9152a38012Sejakowatz
92f6c08206SAxel Dörflernamespace BPrivate {
9347761c47SAxel Dörfler
94f6c08206SAxel Dörflerclass ObserverList {
9552a38012Sejakowatz	public:
96f6c08206SAxel Dörfler		ObserverList();
97f6c08206SAxel Dörfler		~ObserverList();
98f6c08206SAxel Dörfler
99f6c08206SAxel Dörfler		status_t SendNotices(uint32 what, const BMessage* notice);
100f6c08206SAxel Dörfler		status_t Add(const BHandler* handler, uint32 what);
101f6c08206SAxel Dörfler		status_t Add(const BMessenger& messenger, uint32 what);
102f6c08206SAxel Dörfler		status_t Remove(const BHandler* handler, uint32 what);
103f6c08206SAxel Dörfler		status_t Remove(const BMessenger& messenger, uint32 what);
10452a38012Sejakowatz		bool IsEmpty();
10552a38012Sejakowatz
10652a38012Sejakowatz	private:
107be902ac4SJohn Scipione		typedef map<uint32, vector<const BHandler*> > HandlerObserverMap;
108f6c08206SAxel Dörfler		typedef map<uint32, vector<BMessenger> > MessengerObserverMap;
109f6c08206SAxel Dörfler
110f6c08206SAxel Dörfler		void _ValidateHandlers(uint32 what);
111f6c08206SAxel Dörfler		void _SendNotices(uint32 what, BMessage* notice);
112f6c08206SAxel Dörfler
113f6c08206SAxel Dörfler		HandlerObserverMap		fHandlerMap;
114f6c08206SAxel Dörfler		MessengerObserverMap	fMessengerMap;
11552a38012Sejakowatz};
11652a38012Sejakowatz
117f6c08206SAxel Dörfler}	// namespace BPrivate
118f6c08206SAxel Dörfler
119f6c08206SAxel Dörflerusing namespace BPrivate;
120f6c08206SAxel Dörfler
12152a38012Sejakowatz
122090dcfd4SAxel Dörfler//	#pragma mark -
123090dcfd4SAxel Dörfler
124090dcfd4SAxel Dörfler
125be902ac4SJohn ScipioneBHandler::BHandler(const char* name)
12647761c47SAxel Dörfler	: BArchivable(),
12747761c47SAxel Dörfler	fName(NULL)
12852a38012Sejakowatz{
129f6c08206SAxel Dörfler	_InitData(name);
13052a38012Sejakowatz}
13147761c47SAxel Dörfler
13247761c47SAxel Dörfler
13352a38012SejakowatzBHandler::~BHandler()
13452a38012Sejakowatz{
135731b9ac7SKarsten Heimrich	if (LockLooper()) {
1362617261dSKarsten Heimrich		BLooper* looper = Looper();
1372617261dSKarsten Heimrich		looper->RemoveHandler(this);
1382617261dSKarsten Heimrich		looper->Unlock();
139731b9ac7SKarsten Heimrich	}
140731b9ac7SKarsten Heimrich
14147c2c0f2SStephan Aßmus	// remove all filters
14247c2c0f2SStephan Aßmus	if (fFilters) {
14347c2c0f2SStephan Aßmus		int32 count = fFilters->CountItems();
14447c2c0f2SStephan Aßmus		for (int32 i = 0; i < count; i++)
14547c2c0f2SStephan Aßmus			delete (BMessageFilter*)fFilters->ItemAtFast(i);
14647c2c0f2SStephan Aßmus		delete fFilters;
14747c2c0f2SStephan Aßmus	}
148ad236123SAxel Dörfler
149ad236123SAxel Dörfler	// remove all observers (the observer list manages itself)
150ad236123SAxel Dörfler	delete fObserverList;
151ad236123SAxel Dörfler
15247c2c0f2SStephan Aßmus	// free rest
15347761c47SAxel Dörfler	free(fName);
15452a38012Sejakowatz	gDefaultTokens.RemoveToken(fToken);
15552a38012Sejakowatz}
15647761c47SAxel Dörfler
15747761c47SAxel Dörfler
158be902ac4SJohn ScipioneBHandler::BHandler(BMessage* data)
15947761c47SAxel Dörfler	: BArchivable(data),
16047761c47SAxel Dörfler	fName(NULL)
16152a38012Sejakowatz{
162be902ac4SJohn Scipione	const char* name = NULL;
16352a38012Sejakowatz
16452a38012Sejakowatz	if (data)
1655b6aece6SStefano Ceccherini		data->FindString(kArchiveNameField, &name);
16652a38012Sejakowatz
167f6c08206SAxel Dörfler	_InitData(name);
16852a38012Sejakowatz}
16947761c47SAxel Dörfler
17047761c47SAxel Dörfler
171be902ac4SJohn ScipioneBArchivable*
172be902ac4SJohn ScipioneBHandler::Instantiate(BMessage* data)
17352a38012Sejakowatz{
17452a38012Sejakowatz	if (!validate_instantiation(data, "BHandler"))
17552a38012Sejakowatz		return NULL;
17652a38012Sejakowatz
17752a38012Sejakowatz	return new BHandler(data);
17852a38012Sejakowatz}
17947761c47SAxel Dörfler
18047761c47SAxel Dörfler
18147761c47SAxel Dörflerstatus_t
182be902ac4SJohn ScipioneBHandler::Archive(BMessage* data, bool deep) const
18352a38012Sejakowatz{
18447761c47SAxel Dörfler	status_t status = BArchivable::Archive(data, deep);
18547761c47SAxel Dörfler	if (status < B_OK)
18647761c47SAxel Dörfler		return status;
18752a38012Sejakowatz
188be902ac4SJohn Scipione	if (fName == NULL)
189157c0cedSJérôme Duval		return B_OK;
190be902ac4SJohn Scipione
1915b6aece6SStefano Ceccherini	return data->AddString(kArchiveNameField, fName);
19252a38012Sejakowatz}
19347761c47SAxel Dörfler
19447761c47SAxel Dörfler
19547761c47SAxel Dörflervoid
196be902ac4SJohn ScipioneBHandler::MessageReceived(BMessage* message)
19752a38012Sejakowatz{
1982f197f33SStefano Ceccherini	BMessage reply(B_REPLY);
1992f197f33SStefano Ceccherini
2002f197f33SStefano Ceccherini	switch (message->what) {
201f6c08206SAxel Dörfler		case kMsgStartObserving:
202f6c08206SAxel Dörfler		case kMsgStopObserving:
203f6c08206SAxel Dörfler		{
204f6c08206SAxel Dörfler			BMessenger target;
205f6c08206SAxel Dörfler			uint32 what;
206f6c08206SAxel Dörfler			if (message->FindMessenger(kObserveTarget, &target) != B_OK
207be902ac4SJohn Scipione				|| message->FindInt32(B_OBSERVE_WHAT_CHANGE, (int32*)&what)
208be902ac4SJohn Scipione					!= B_OK) {
209f6c08206SAxel Dörfler				break;
210be902ac4SJohn Scipione			}
211f6c08206SAxel Dörfler
212f6c08206SAxel Dörfler			ObserverList* list = _ObserverList();
213f6c08206SAxel Dörfler			if (list != NULL) {
214f6c08206SAxel Dörfler				if (message->what == kMsgStartObserving)
215f6c08206SAxel Dörfler					list->Add(target, what);
216f6c08206SAxel Dörfler				else
217f6c08206SAxel Dörfler					list->Remove(target, what);
218f6c08206SAxel Dörfler			}
219f6c08206SAxel Dörfler			break;
220f6c08206SAxel Dörfler		}
221dfb8cfeaSAxel Dörfler
22252a38012Sejakowatz		case B_GET_PROPERTY:
22352a38012Sejakowatz		{
2242f197f33SStefano Ceccherini			int32 cur;
2252f197f33SStefano Ceccherini			BMessage specifier;
2262f197f33SStefano Ceccherini			int32 form;
227be902ac4SJohn Scipione			const char* prop;
22847761c47SAxel Dörfler
22938d688ccSJérôme Duval			status_t err = message->GetCurrentSpecifier(&cur, &specifier,
23038d688ccSJérôme Duval				&form, &prop);
23138d688ccSJérôme Duval			if (err != B_OK && err != B_BAD_SCRIPT_SYNTAX)
2324bbb27e3SJerome Duval				break;
233a5845049SJérôme Duval			bool known = false;
23438d688ccSJérôme Duval			// B_BAD_SCRIPT_SYNTAX defaults to the Messenger property
23538d688ccSJérôme Duval			if (err == B_BAD_SCRIPT_SYNTAX || cur < 0
23638d688ccSJérôme Duval				|| (strcmp(prop, "Messenger") == 0)) {
237a5845049SJérôme Duval				err = reply.AddMessenger("result", this);
238a5845049SJérôme Duval				known = true;
239a5845049SJérôme Duval			} else if (strcmp(prop, "Suites") == 0) {
240a5845049SJérôme Duval				err = GetSupportedSuites(&reply);
241a5845049SJérôme Duval				known = true;
242a5845049SJérôme Duval			} else if (strcmp(prop, "InternalName") == 0) {
243a5845049SJérôme Duval				err = reply.AddString("result", Name());
244a5845049SJérôme Duval				known = true;
245a5845049SJérôme Duval			}
246dfb8cfeaSAxel Dörfler
247a5845049SJérôme Duval			if (known) {
248a5845049SJérôme Duval				reply.AddInt32("error", B_OK);
249a5845049SJérôme Duval				message->SendReply(&reply);
250a5845049SJérôme Duval				return;
25152a38012Sejakowatz			}
252a5845049SJérôme Duval			// let's try next handler
25352a38012Sejakowatz			break;
25452a38012Sejakowatz		}
25547761c47SAxel Dörfler
2562f197f33SStefano Ceccherini		case B_GET_SUPPORTED_SUITES:
2572f197f33SStefano Ceccherini		{
2582f197f33SStefano Ceccherini			reply.AddInt32("error", GetSupportedSuites(&reply));
2592f197f33SStefano Ceccherini			message->SendReply(&reply);
260dfb8cfeaSAxel Dörfler			return;
2612f197f33SStefano Ceccherini		}
262dfb8cfeaSAxel Dörfler	}
26347761c47SAxel Dörfler
264be902ac4SJohn Scipione	// ToDo: there is some more work needed here
265be902ac4SJohn Scipione	// (someone in the know should fill in)!
266dfb8cfeaSAxel Dörfler
267dfb8cfeaSAxel Dörfler	if (fNextHandler) {
268b360ada4SAxel Dörfler		// we need to apply the next handler's filters here, too
269b360ada4SAxel Dörfler		BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
270b360ada4SAxel Dörfler		if (target != NULL && target != this) {
271b360ada4SAxel Dörfler			// TODO: we also need to make sure that "target" is not before
272b360ada4SAxel Dörfler			//	us in the handler chain - at least in case it wasn't before
273b360ada4SAxel Dörfler			//	the handler actually targeted with this message - this could
274b360ada4SAxel Dörfler			//	get ugly, though.
275b360ada4SAxel Dörfler			target->MessageReceived(message);
276b360ada4SAxel Dörfler		}
27704dc040eSAxel Dörfler	} else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
27804dc040eSAxel Dörfler		&& (message->WasDropped() || message->HasSpecifiers())) {
279579d1b23SStefano Ceccherini		printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
280dfb8cfeaSAxel Dörfler		message->PrintToStream();
281dfb8cfeaSAxel Dörfler		message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
28252a38012Sejakowatz	}
28352a38012Sejakowatz}
28447761c47SAxel Dörfler
28547761c47SAxel Dörfler
286be902ac4SJohn ScipioneBLooper*
28747761c47SAxel DörflerBHandler::Looper() const
28852a38012Sejakowatz{
28952a38012Sejakowatz	return fLooper;
29052a38012Sejakowatz}
29147761c47SAxel Dörfler
29247761c47SAxel Dörfler
29347761c47SAxel Dörflervoid
294be902ac4SJohn ScipioneBHandler::SetName(const char* name)
29552a38012Sejakowatz{
29647761c47SAxel Dörfler	if (fName != NULL) {
29752a38012Sejakowatz		free(fName);
29852a38012Sejakowatz		fName = NULL;
29952a38012Sejakowatz	}
30052a38012Sejakowatz
30147761c47SAxel Dörfler	if (name != NULL)
30252a38012Sejakowatz		fName = strdup(name);
30352a38012Sejakowatz}
30447761c47SAxel Dörfler
30547761c47SAxel Dörfler
306be902ac4SJohn Scipioneconst char*
30747761c47SAxel DörflerBHandler::Name() const
30852a38012Sejakowatz{
30952a38012Sejakowatz	return fName;
31052a38012Sejakowatz}
31147761c47SAxel Dörfler
31247761c47SAxel Dörfler
31347761c47SAxel Dörflervoid
314be902ac4SJohn ScipioneBHandler::SetNextHandler(BHandler* handler)
31552a38012Sejakowatz{
316be902ac4SJohn Scipione	if (fLooper == NULL) {
31752a38012Sejakowatz		debugger("handler must belong to looper before setting NextHandler");
31852a38012Sejakowatz		return;
31952a38012Sejakowatz	}
32052a38012Sejakowatz
32147761c47SAxel Dörfler	if (!fLooper->IsLocked()) {
322abb57933Sejakowatz		debugger("The handler's looper must be locked before setting NextHandler");
32352a38012Sejakowatz		return;
32452a38012Sejakowatz	}
32552a38012Sejakowatz
326be902ac4SJohn Scipione	if (handler != NULL && fLooper != handler->Looper()) {
327abb57933Sejakowatz		debugger("The handler and its NextHandler must have the same looper");
328abb57933Sejakowatz		return;
32952a38012Sejakowatz	}
33052a38012Sejakowatz
33152a38012Sejakowatz	fNextHandler = handler;
33252a38012Sejakowatz}
33347761c47SAxel Dörfler
33447761c47SAxel Dörfler
335be902ac4SJohn ScipioneBHandler*
33647761c47SAxel DörflerBHandler::NextHandler() const
33752a38012Sejakowatz{
33852a38012Sejakowatz	return fNextHandler;
33952a38012Sejakowatz}
34047761c47SAxel Dörfler
34147761c47SAxel Dörfler
34247761c47SAxel Dörflervoid
343be902ac4SJohn ScipioneBHandler::AddFilter(BMessageFilter* filter)
34452a38012Sejakowatz{
3452617261dSKarsten Heimrich	BLooper* looper = fLooper;
346be902ac4SJohn Scipione	if (looper != NULL && !looper->IsLocked()) {
347689dc9f9SAxel Dörfler		debugger("Owning Looper must be locked before calling SetFilterList");
348689dc9f9SAxel Dörfler		return;
34952a38012Sejakowatz	}
35052a38012Sejakowatz
3512617261dSKarsten Heimrich	if (looper != NULL)
3522617261dSKarsten Heimrich		filter->SetLooper(looper);
35317e0fc6bSKarsten Heimrich
354be902ac4SJohn Scipione	if (fFilters == NULL)
35552a38012Sejakowatz		fFilters = new BList;
35617e0fc6bSKarsten Heimrich
35752a38012Sejakowatz	fFilters->AddItem(filter);
35852a38012Sejakowatz}
35947761c47SAxel Dörfler
36047761c47SAxel Dörfler
36147761c47SAxel Dörflerbool
362be902ac4SJohn ScipioneBHandler::RemoveFilter(BMessageFilter* filter)
36352a38012Sejakowatz{
3642617261dSKarsten Heimrich	BLooper* looper = fLooper;
365be902ac4SJohn Scipione	if (looper != NULL && !looper->IsLocked()) {
366689dc9f9SAxel Dörfler		debugger("Owning Looper must be locked before calling SetFilterList");
36752a38012Sejakowatz		return false;
36852a38012Sejakowatz	}
36952a38012Sejakowatz
370be902ac4SJohn Scipione	if (fFilters != NULL && fFilters->RemoveItem((void*)filter)) {
37147761c47SAxel Dörfler		filter->SetLooper(NULL);
37247761c47SAxel Dörfler		return true;
37352a38012Sejakowatz	}
37452a38012Sejakowatz
37552a38012Sejakowatz	return false;
37652a38012Sejakowatz}
37747761c47SAxel Dörfler
37847761c47SAxel Dörfler
37947761c47SAxel Dörflervoid
38047761c47SAxel DörflerBHandler::SetFilterList(BList* filters)
38152a38012Sejakowatz{
3822617261dSKarsten Heimrich	BLooper* looper = fLooper;
383be902ac4SJohn Scipione	if (looper != NULL && !looper->IsLocked()) {
38452a38012Sejakowatz		debugger("Owning Looper must be locked before calling SetFilterList");
38552a38012Sejakowatz		return;
38652a38012Sejakowatz	}
38752a38012Sejakowatz
38847761c47SAxel Dörfler	/**
38947761c47SAxel Dörfler		@note	I would like to use BObjectList internally, but this function is
39047761c47SAxel Dörfler				spec'd such that fFilters would get deleted and then assigned
39147761c47SAxel Dörfler				'filters', which would obviously mess this up.  Wondering if
39247761c47SAxel Dörfler				anyone ever assigns a list of filters and then checks against
39347761c47SAxel Dörfler				FilterList() to see if they are the same.
39447761c47SAxel Dörfler	 */
39547761c47SAxel Dörfler
39652a38012Sejakowatz	// TODO: Explore issues with using BObjectList
397be902ac4SJohn Scipione	if (fFilters != NULL) {
39852a38012Sejakowatz		fFilters->DoForEach(FilterDeleter);
39952a38012Sejakowatz		delete fFilters;
40052a38012Sejakowatz	}
40152a38012Sejakowatz
40252a38012Sejakowatz	fFilters = filters;
40347761c47SAxel Dörfler	if (fFilters) {
40447761c47SAxel Dörfler		for (int32 i = 0; i < fFilters->CountItems(); ++i) {
405be902ac4SJohn Scipione			BMessageFilter* filter =
406be902ac4SJohn Scipione				static_cast<BMessageFilter*>(fFilters->ItemAt(i));
40747761c47SAxel Dörfler			if (filter != NULL)
4082617261dSKarsten Heimrich				filter->SetLooper(looper);
40952a38012Sejakowatz		}
41052a38012Sejakowatz	}
41152a38012Sejakowatz}
41247761c47SAxel Dörfler
41347761c47SAxel Dörfler
414be902ac4SJohn ScipioneBList*
41547761c47SAxel DörflerBHandler::FilterList()
41652a38012Sejakowatz{
41752a38012Sejakowatz	return fFilters;
41852a38012Sejakowatz}
41947761c47SAxel Dörfler
42047761c47SAxel Dörfler
42147761c47SAxel Dörflerbool
42247761c47SAxel DörflerBHandler::LockLooper()
42352a38012Sejakowatz{
424be902ac4SJohn Scipione	BLooper* looper = fLooper;
425689dc9f9SAxel Dörfler	// Locking the looper also makes sure that the looper is valid
426689dc9f9SAxel Dörfler	if (looper != NULL && looper->Lock()) {
427689dc9f9SAxel Dörfler		// Have we locked the right looper? That's as far as the
428689dc9f9SAxel Dörfler		// "pseudo-atomic" operation mentioned in the BeBook.
42947761c47SAxel Dörfler		if (fLooper == looper)
430689dc9f9SAxel Dörfler			return true;
43147761c47SAxel Dörfler
432689dc9f9SAxel Dörfler		// we locked the wrong looper, bail out
433689dc9f9SAxel Dörfler		looper->Unlock();
43452a38012Sejakowatz	}
43552a38012Sejakowatz
43652a38012Sejakowatz	return false;
43752a38012Sejakowatz}
43847761c47SAxel Dörfler
43947761c47SAxel Dörfler
44047761c47SAxel Dörflerstatus_t
44147761c47SAxel DörflerBHandler::LockLooperWithTimeout(bigtime_t timeout)
44252a38012Sejakowatz{
443be902ac4SJohn Scipione	BLooper* looper = fLooper;
444689dc9f9SAxel Dörfler	if (looper == NULL)
445689dc9f9SAxel Dörfler		return B_BAD_VALUE;
44652a38012Sejakowatz
447689dc9f9SAxel Dörfler	status_t status = looper->LockWithTimeout(timeout);
448689dc9f9SAxel Dörfler	if (status != B_OK)
449689dc9f9SAxel Dörfler		return status;
45047761c47SAxel Dörfler
451689dc9f9SAxel Dörfler	if (fLooper != looper) {
452689dc9f9SAxel Dörfler		// we locked the wrong looper, bail out
453689dc9f9SAxel Dörfler		looper->Unlock();
45447761c47SAxel Dörfler		return B_MISMATCHED_VALUES;
45552a38012Sejakowatz	}
45652a38012Sejakowatz
457689dc9f9SAxel Dörfler	return B_OK;
45852a38012Sejakowatz}
45947761c47SAxel Dörfler
46047761c47SAxel Dörfler
46147761c47SAxel Dörflervoid
46247761c47SAxel DörflerBHandler::UnlockLooper()
46352a38012Sejakowatz{
4642617261dSKarsten Heimrich	fLooper->Unlock();
46552a38012Sejakowatz}
46647761c47SAxel Dörfler
46747761c47SAxel Dörfler
468be902ac4SJohn ScipioneBHandler*
469be902ac4SJohn ScipioneBHandler::ResolveSpecifier(BMessage* message, int32 index,
470be902ac4SJohn Scipione	BMessage* specifier, int32 what, const char* property)
47152a38012Sejakowatz{
47252a38012Sejakowatz	// Straight from the BeBook
47347761c47SAxel Dörfler	BPropertyInfo propertyInfo(sHandlerPropInfo);
474be902ac4SJohn Scipione	if (propertyInfo.FindMatch(message, index, specifier, what, property) >= 0)
47552a38012Sejakowatz		return this;
47652a38012Sejakowatz
47747761c47SAxel Dörfler	BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
47847761c47SAxel Dörfler	reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
47947761c47SAxel Dörfler	reply.AddString("message", "Didn't understand the specifier(s)");
480be902ac4SJohn Scipione	message->SendReply(&reply);
48152a38012Sejakowatz
48252a38012Sejakowatz	return NULL;
48352a38012Sejakowatz}
48447761c47SAxel Dörfler
48547761c47SAxel Dörfler
48647761c47SAxel Dörflerstatus_t
487be902ac4SJohn ScipioneBHandler::GetSupportedSuites(BMessage* data)
48852a38012Sejakowatz{
48952a38012Sejakowatz/**
49052a38012Sejakowatz	@note	This is the output from the original implementation (calling
49152a38012Sejakowatz			PrintToStream() on both data and the contained BPropertyInfo):
49252a38012Sejakowatz
49352a38012SejakowatzBMessage: what =  (0x0, or 0)
49417e0fc6bSKarsten Heimrich	entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
49517e0fc6bSKarsten Heimrich	entry       messages, type='SCTD', c=1, size= 0,
49617e0fc6bSKarsten Heimrich	  property   commands                       types                specifiers
49752a38012Sejakowatz--------------------------------------------------------------------------------
49817e0fc6bSKarsten Heimrich		Suites   PGET                                               1
49917e0fc6bSKarsten Heimrich				 (RTSC,suites)
50017e0fc6bSKarsten Heimrich				 (DTCS,messages)
50152a38012Sejakowatz
50217e0fc6bSKarsten Heimrich	 Messenger   PGET                          GNSM                 1
50352a38012Sejakowatz  InternalName   PGET                          RTSC                 1
50452a38012Sejakowatz
50552a38012Sejakowatz			With a good deal of trial and error, I determined that the
50652a38012Sejakowatz			parenthetical clauses are entries in the 'ctypes' field of
50752a38012Sejakowatz			property_info.  'ctypes' is an array of 'compound_type', which
50852a38012Sejakowatz			contains an array of 'field_pair's.  I haven't the foggiest what
50952a38012Sejakowatz			either 'compound_type' or 'field_pair' is for, being as the
51052a38012Sejakowatz			scripting docs are so bloody horrible.  The corresponding
51152a38012Sejakowatz			property_info array is declared in the globals section.
51252a38012Sejakowatz */
51347761c47SAxel Dörfler
514be902ac4SJohn Scipione	if (data == NULL)
5152776568dSJohn Scipione		return B_BAD_VALUE;
51652a38012Sejakowatz
5172776568dSJohn Scipione	status_t result = data->AddString("suites", "suite/vnd.Be-handler");
5182776568dSJohn Scipione	if (result == B_OK) {
5192776568dSJohn Scipione		BPropertyInfo propertyInfo(sHandlerPropInfo);
5202776568dSJohn Scipione		result = data->AddFlat("messages", &propertyInfo);
52152a38012Sejakowatz	}
52252a38012Sejakowatz
5232776568dSJohn Scipione	return result;
52452a38012Sejakowatz}
52547761c47SAxel Dörfler
52647761c47SAxel Dörfler
52747761c47SAxel Dörflerstatus_t
528f6c08206SAxel DörflerBHandler::StartWatching(BMessenger target, uint32 what)
52952a38012Sejakowatz{
530f6c08206SAxel Dörfler	BMessage message(kMsgStartObserving);
531f6c08206SAxel Dörfler	message.AddMessenger(kObserveTarget, this);
532f6c08206SAxel Dörfler	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
533f6c08206SAxel Dörfler
534f6c08206SAxel Dörfler	return target.SendMessage(&message);
53552a38012Sejakowatz}
53647761c47SAxel Dörfler
53747761c47SAxel Dörfler
53847761c47SAxel Dörflerstatus_t
539f6c08206SAxel DörflerBHandler::StartWatchingAll(BMessenger target)
54052a38012Sejakowatz{
541f6c08206SAxel Dörfler	return StartWatching(target, B_OBSERVER_OBSERVE_ALL);
54252a38012Sejakowatz}
54347761c47SAxel Dörfler
54447761c47SAxel Dörfler
54547761c47SAxel Dörflerstatus_t
546f6c08206SAxel DörflerBHandler::StopWatching(BMessenger target, uint32 what)
54752a38012Sejakowatz{
548f6c08206SAxel Dörfler	BMessage message(kMsgStopObserving);
549f6c08206SAxel Dörfler	message.AddMessenger(kObserveTarget, this);
550f6c08206SAxel Dörfler	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
551f6c08206SAxel Dörfler
552f6c08206SAxel Dörfler	return target.SendMessage(&message);
55352a38012Sejakowatz}
55447761c47SAxel Dörfler
55547761c47SAxel Dörfler
55647761c47SAxel Dörflerstatus_t
557f6c08206SAxel DörflerBHandler::StopWatchingAll(BMessenger target)
55852a38012Sejakowatz{
559f6c08206SAxel Dörfler	return StopWatching(target, B_OBSERVER_OBSERVE_ALL);
56052a38012Sejakowatz}
56147761c47SAxel Dörfler
56247761c47SAxel Dörfler
56347761c47SAxel Dörflerstatus_t
564f6c08206SAxel DörflerBHandler::StartWatching(BHandler* handler, uint32 what)
56552a38012Sejakowatz{
566f6c08206SAxel Dörfler	ObserverList* list = _ObserverList();
567f6c08206SAxel Dörfler	if (list == NULL)
568f6c08206SAxel Dörfler		return B_NO_MEMORY;
569f6c08206SAxel Dörfler
570f6c08206SAxel Dörfler	return list->Add(handler, what);
57152a38012Sejakowatz}
57247761c47SAxel Dörfler
57347761c47SAxel Dörfler
57447761c47SAxel Dörflerstatus_t
575f6c08206SAxel DörflerBHandler::StartWatchingAll(BHandler* handler)
57652a38012Sejakowatz{
577418ab064SStefano Ceccherini	return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
57852a38012Sejakowatz}
57947761c47SAxel Dörfler
58047761c47SAxel Dörfler
58147761c47SAxel Dörflerstatus_t
582f6c08206SAxel DörflerBHandler::StopWatching(BHandler* handler, uint32 what)
58352a38012Sejakowatz{
584f6c08206SAxel Dörfler	ObserverList* list = _ObserverList();
585f6c08206SAxel Dörfler	if (list == NULL)
586f6c08206SAxel Dörfler		return B_NO_MEMORY;
587f6c08206SAxel Dörfler
588f6c08206SAxel Dörfler	return list->Remove(handler, what);
58952a38012Sejakowatz}
59047761c47SAxel Dörfler
59147761c47SAxel Dörfler
59247761c47SAxel Dörflerstatus_t
593be902ac4SJohn ScipioneBHandler::StopWatchingAll(BHandler* handler)
59452a38012Sejakowatz{
59517adbf1fSStefano Ceccherini	return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
59652a38012Sejakowatz}
59747761c47SAxel Dörfler
59847761c47SAxel Dörfler
59947761c47SAxel Dörflerstatus_t
600be902ac4SJohn ScipioneBHandler::Perform(perform_code d, void* arg)
60152a38012Sejakowatz{
60252a38012Sejakowatz	return BArchivable::Perform(d, arg);
60352a38012Sejakowatz}
60447761c47SAxel Dörfler
60547761c47SAxel Dörfler
60647761c47SAxel Dörflervoid
607be902ac4SJohn ScipioneBHandler::SendNotices(uint32 what, const BMessage* notice)
60852a38012Sejakowatz{
609418ab064SStefano Ceccherini	if (fObserverList != NULL)
610be902ac4SJohn Scipione		fObserverList->SendNotices(what, notice);
61152a38012Sejakowatz}
61247761c47SAxel Dörfler
61347761c47SAxel Dörfler
61447761c47SAxel Dörflerbool
61547761c47SAxel DörflerBHandler::IsWatched() const
61652a38012Sejakowatz{
61752a38012Sejakowatz	return fObserverList && !fObserverList->IsEmpty();
61852a38012Sejakowatz}
61947761c47SAxel Dörfler
62047761c47SAxel Dörfler
62147761c47SAxel Dörflervoid
622be902ac4SJohn ScipioneBHandler::_InitData(const char* name)
62352a38012Sejakowatz{
62452a38012Sejakowatz	SetName(name);
62552a38012Sejakowatz
62647761c47SAxel Dörfler	fLooper = NULL;
62747761c47SAxel Dörfler	fNextHandler = NULL;
62847761c47SAxel Dörfler	fFilters = NULL;
62947761c47SAxel Dörfler	fObserverList = NULL;
63052a38012Sejakowatz
63152a38012Sejakowatz	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
63252a38012Sejakowatz}
63347761c47SAxel Dörfler
63447761c47SAxel Dörfler
635f6c08206SAxel DörflerObserverList*
636f6c08206SAxel DörflerBHandler::_ObserverList()
637f6c08206SAxel Dörfler{
638f6c08206SAxel Dörfler	if (fObserverList == NULL)
639f6c08206SAxel Dörfler		fObserverList = new (std::nothrow) BPrivate::ObserverList();
640f6c08206SAxel Dörfler
641f6c08206SAxel Dörfler	return fObserverList;
642f6c08206SAxel Dörfler}
643f6c08206SAxel Dörfler
644f6c08206SAxel Dörfler
64547761c47SAxel Dörflervoid
646be902ac4SJohn ScipioneBHandler::SetLooper(BLooper* looper)
64752a38012Sejakowatz{
6487089b0e3SStefano Ceccherini	fLooper = looper;
649be902ac4SJohn Scipione	gDefaultTokens.SetHandlerTarget(fToken,
650be902ac4SJohn Scipione		looper ? looper->fDirectTarget : NULL);
6519dbe170aSAxel Dörfler
652be902ac4SJohn Scipione	if (fFilters != NULL) {
653be902ac4SJohn Scipione		for (int32 i = 0; i < fFilters->CountItems(); i++) {
654be902ac4SJohn Scipione			static_cast<BMessageFilter*>(
655be902ac4SJohn Scipione				fFilters->ItemAtFast(i))->SetLooper(looper);
656be902ac4SJohn Scipione		}
6577089b0e3SStefano Ceccherini	}
65852a38012Sejakowatz}
65952a38012Sejakowatz
66052a38012Sejakowatz
66139fbf550SOliver Tappe#if __GNUC__ < 3
662d95383a3SAxel Dörfler// binary compatibility with R4.5
66339fbf550SOliver Tappe
66439fbf550SOliver Tappeextern "C" void
66539fbf550SOliver Tappe_ReservedHandler1__8BHandler(BHandler* handler, uint32 what,
66639fbf550SOliver Tappe	const BMessage* notice)
66739fbf550SOliver Tappe{
66839fbf550SOliver Tappe	handler->BHandler::SendNotices(what, notice);
66939fbf550SOliver Tappe}
67039fbf550SOliver Tappe
671ebb0db62SAugustin Cavalier
672ebb0db62SAugustin CavalierBHandler::BHandler(const BHandler &)
673ebb0db62SAugustin Cavalier{
674ebb0db62SAugustin Cavalier	// No copy construction allowed.
675ebb0db62SAugustin Cavalier}
676ebb0db62SAugustin Cavalier
677ebb0db62SAugustin Cavalier
678ebb0db62SAugustin CavalierBHandler &
679ebb0db62SAugustin CavalierBHandler::operator=(const BHandler &)
680ebb0db62SAugustin Cavalier{
681ebb0db62SAugustin Cavalier	// No assignments allowed.
682ebb0db62SAugustin Cavalier	return *this;
683ebb0db62SAugustin Cavalier}
684d95383a3SAxel Dörfler#endif
685d95383a3SAxel Dörfler
686d95383a3SAxel Dörflervoid BHandler::_ReservedHandler2() {}
687d95383a3SAxel Dörflervoid BHandler::_ReservedHandler3() {}
688d95383a3SAxel Dörflervoid BHandler::_ReservedHandler4() {}
689d95383a3SAxel Dörfler
690d95383a3SAxel Dörfler
69152a38012Sejakowatz//	#pragma mark -
69247761c47SAxel Dörfler
69347761c47SAxel Dörfler
694f6c08206SAxel DörflerObserverList::ObserverList()
69552a38012Sejakowatz{
69652a38012Sejakowatz}
69747761c47SAxel Dörfler
69847761c47SAxel Dörfler
699f6c08206SAxel DörflerObserverList::~ObserverList()
70052a38012Sejakowatz{
70152a38012Sejakowatz}
70247761c47SAxel Dörfler
70347761c47SAxel Dörfler
704f6c08206SAxel Dörflervoid
705f6c08206SAxel DörflerObserverList::_ValidateHandlers(uint32 what)
70652a38012Sejakowatz{
707be902ac4SJohn Scipione	vector<const BHandler*>& handlers = fHandlerMap[what];
708be902ac4SJohn Scipione	vector<const BHandler*>::iterator iterator = handlers.begin();
70952a38012Sejakowatz
7102f03d0e0SStefano Ceccherini	while (iterator != handlers.end()) {
711f6c08206SAxel Dörfler		BMessenger target(*iterator);
7122f03d0e0SStefano Ceccherini		if (!target.IsValid()) {
71317e0fc6bSKarsten Heimrich			iterator++;
714f6c08206SAxel Dörfler			continue;
7152f03d0e0SStefano Ceccherini		}
71652a38012Sejakowatz
717f6c08206SAxel Dörfler		Add(target, what);
71817e0fc6bSKarsten Heimrich		iterator = handlers.erase(iterator);
71952a38012Sejakowatz	}
720f6c08206SAxel Dörfler}
72152a38012Sejakowatz
722f6c08206SAxel Dörfler
723f6c08206SAxel Dörflervoid
724be902ac4SJohn ScipioneObserverList::_SendNotices(uint32 what, BMessage* notice)
725f6c08206SAxel Dörfler{
726be902ac4SJohn Scipione	// first iterate over the list of handlers and try to make valid
727be902ac4SJohn Scipione	// messengers out of them
728f6c08206SAxel Dörfler	_ValidateHandlers(what);
729f6c08206SAxel Dörfler
730f6c08206SAxel Dörfler	// now send it to all messengers we know
731