This is MiscTee.m in view mode; [Download] [Up]
//
// MiscTee.h -- An object which will pass a message on to any of the objects
// connected to it. This is useful for splitting an action
// message to multiple recipients or for allowing multiple
// delegates to be connected to provide different services.
//
// Written by David Fedchenko. Copyright 1994 by David Fedchenko.
// Version 1.1 All rights reserved.
// Additions by Don Yacktman to remove warnings and avoid infinite loops.
//
// This notice may not be removed from this source code.
//
// This object is included in the MiscKit by permission from the author
// and its use is governed by the MiscKit license, found in the file
// "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
// for a list of all applicable permissions and restrictions.
//
#import "MiscTee.h"
typedef struct
{
// Object *idObject; // Using this would remove warnings _if_ isa were
// not protected, but as things stand, we'll have to live with the
// warnings. :-( That's what you get for "isa hacking"!
//id idObject; // This is where we got warnings...original definition...
struct objc_class *idObject; // This seems to work right...
SEL selAction;
} CONPAIR;
@implementation MiscTee
- init
{
[super init];
inTee = NO;
idConnections = [[Storage alloc] initCount:0 elementSize:sizeof(CONPAIR)
description:@encode(CONPAIR)];
return self;
}
- free
{
[idConnections free];
return [super free];
}
- addConnection:anObject with:(SEL)anAction
{
CONPAIR cp;
CONPAIR * pcp;
int i;
cp.idObject = anObject;
cp.selAction = anAction;
// replace the action if the object is already in the list
for (i = 0; i < [idConnections count]; i++)
{
pcp = (CONPAIR *)[idConnections elementAt:i];
if (pcp->idObject == anObject)
{
pcp->selAction = anAction;
return self;
}
}
// new connection
[idConnections addElement:&cp];
return self;
}
- removeConnection:anObject
{
CONPAIR * pcp;
int i;
for (i = 0; i < [idConnections count]; i++)
{
pcp = (CONPAIR *)[idConnections elementAt:i];
if (pcp->idObject == anObject)
{
[idConnections removeElementAt:i];
break;
}
}
return self;
}
- ping:sender
{
int i;
CONPAIR * pcp;
if (inTee) return self;
inTee = YES;
for (i = 0; i < [idConnections count]; i++) {
pcp = (CONPAIR *)[idConnections elementAt:i];
if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
pcp->idObject != sender && pcp->selAction) {
[pcp->idObject perform:pcp->selAction with:sender];
}
}
inTee = NO;
return self;
}
- forward:(SEL)aSelector :(marg_list)argFrame
{
int i;
CONPAIR * pcp;
void * pv = nil;
BOOL fSent = NO;
if (inTee) return self;
inTee = YES;
for (i = 0; i < [idConnections count]; i++)
{
pcp = (CONPAIR *)[idConnections elementAt:i];
if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
[pcp->idObject respondsTo:aSelector])
{
pv = [pcp->idObject performv:aSelector :argFrame];
fSent = YES;
}
}
if (!fSent)
{
[self doesNotRecognize:aSelector];
}
inTee = NO;
return (id)pv;
}
-(BOOL) respondsTo:(SEL)aSelector
{
int i;
CONPAIR * pcp;
if ([super respondsTo:aSelector])
{
return YES;
}
for (i = 0; i < [idConnections count]; i++)
{
pcp = (CONPAIR *)[idConnections elementAt:i];
if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
[pcp->idObject respondsTo:aSelector])
{
// don't worry about multiple positive responses
return YES;
}
}
return NO;
}
- read:(NXTypedStream *)stream
{
[super read:stream];
idConnections = NXReadObject(stream);
inTee = NO;
return self;
}
- write:(NXTypedStream *)stream
{
[super write:stream];
NXWriteObject(stream, idConnections);
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.