1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1995-1997 Presto Studios, Inc.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  */
25 
26 #include "pegasus/constants.h"
27 #include "pegasus/notification.h"
28 
29 namespace Pegasus {
30 
31 typedef ReceiverList::iterator ReceiverIterator;
32 
Notification(const NotificationID id,NotificationManager * owner)33 Notification::Notification(const NotificationID id, NotificationManager *owner) : IDObject(id) {
34 	_owner = owner;
35 	_currentFlags = kNoNotificationFlags;
36 	if (_owner)
37 		_owner->addNotification(this);
38 }
39 
~Notification()40 Notification::~Notification() {
41 	for (uint i = 0; i < _receivers.size(); i++)
42 		_receivers[i].receiver->newNotification(NULL);
43 
44 	if (_owner)
45 		_owner->removeNotification(this);
46 }
47 
48 // Selectively set or clear notificiation bits.
49 // Wherever mask is 0, leave existing bits untouched.
50 // Wherever mask is 1, set bit equivalent to flags.
notifyMe(NotificationReceiver * receiver,NotificationFlags flags,NotificationFlags mask)51 void Notification::notifyMe(NotificationReceiver *receiver, NotificationFlags flags, NotificationFlags mask) {
52 	for (uint i = 0; i < _receivers.size(); i++) {
53 		if (_receivers[i].receiver == receiver) {
54 			_receivers[i].mask = (_receivers[i].mask & ~mask) | (flags & mask);
55 			receiver->newNotification(this);
56 			return;
57 		}
58 	}
59 
60 	ReceiverEntry newEntry;
61 	newEntry.receiver = receiver;
62 	newEntry.mask = flags;
63 	_receivers.push_back(newEntry);
64 
65 	receiver->newNotification(this);
66 }
67 
cancelNotification(NotificationReceiver * receiver)68 void Notification::cancelNotification(NotificationReceiver *receiver) {
69 	for (uint i = 0; i < _receivers.size(); i++) {
70 		if (_receivers[i].receiver == receiver) {
71 			_receivers.remove_at(i);
72 			i--;
73 		}
74 	}
75 }
76 
setNotificationFlags(NotificationFlags flags,NotificationFlags mask)77 void Notification::setNotificationFlags(NotificationFlags flags, NotificationFlags mask) {
78 	_currentFlags = (_currentFlags & ~mask) | flags;
79 }
80 
checkReceivers()81 void Notification::checkReceivers() {
82 	NotificationFlags currentFlags = _currentFlags;
83 	_currentFlags = kNoNotificationFlags;
84 
85 	for (uint i = 0; i < _receivers.size(); i++)
86 		if (_receivers[i].mask & currentFlags)
87 			_receivers[i].receiver->receiveNotification(this, currentFlags);
88 }
89 
90 // Receiver entries are equal if their receivers are equal.
91 
operator ==(const ReceiverEntry & entry1,const ReceiverEntry & entry2)92 int operator==(const ReceiverEntry &entry1, const ReceiverEntry &entry2) {
93 	return	entry1.receiver == entry2.receiver;
94 }
95 
operator !=(const ReceiverEntry & entry1,const ReceiverEntry & entry2)96 int operator!=(const ReceiverEntry &entry1, const ReceiverEntry &entry2) {
97 	return	entry1.receiver != entry2.receiver;
98 }
99 
NotificationReceiver()100 NotificationReceiver::NotificationReceiver() {
101 	_notification = NULL;
102 }
103 
~NotificationReceiver()104 NotificationReceiver::~NotificationReceiver() {
105 	if (_notification)
106 		_notification->cancelNotification(this);
107 }
108 
receiveNotification(Notification *,const NotificationFlags)109 void NotificationReceiver::receiveNotification(Notification *, const NotificationFlags) {
110 }
111 
newNotification(Notification * notification)112 void NotificationReceiver::newNotification(Notification *notification) {
113 	_notification = notification;
114 }
115 
116 typedef NotificationList::iterator NotificationIterator;
117 
NotificationManager()118 NotificationManager::NotificationManager() {
119 }
120 
~NotificationManager()121 NotificationManager::~NotificationManager() {
122 	detachNotifications();
123 }
124 
addNotification(Notification * notification)125 void NotificationManager::addNotification(Notification *notification) {
126 	_notifications.push_back(notification);
127 }
128 
removeNotification(Notification * notification)129 void NotificationManager::removeNotification(Notification *notification) {
130 	for (NotificationIterator it = _notifications.begin(); it != _notifications.end();) {
131 		if ((*it) == notification)
132 			it = _notifications.erase(it);
133 		else
134 			it++;
135 	}
136 }
137 
detachNotifications()138 void NotificationManager::detachNotifications() {
139 	for (NotificationIterator it = _notifications.begin(); it != _notifications.end(); it++)
140 		(*it)->_owner = 0;
141 }
142 
checkNotifications()143 void NotificationManager::checkNotifications() {
144 	for (NotificationIterator it = _notifications.begin(); it != _notifications.end(); it++)
145 		if ((*it)->_currentFlags != kNoNotificationFlags)
146 			(*it)->checkReceivers();
147 }
148 
149 } // End of namespace Pegasus
150