home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Palettes / MiscTeePalette / MiscTee.subproj / MiscTee.m < prev    next >
Encoding:
Text File  |  1994-10-24  |  3.7 KB  |  183 lines

  1. //
  2. //    MiscTee.h -- An object which will pass a message on to any of the objects
  3. //                 connected to it.  This is useful for splitting an action
  4. //                 message to multiple recipients or for allowing multiple
  5. //                 delegates to be connected to provide different services.
  6. //
  7. //        Written by David Fedchenko.  Copyright 1994 by David Fedchenko.
  8. //                Version 1.1  All rights reserved.
  9. //        Additions by Don Yacktman to remove warnings and avoid infinite loops.
  10. //
  11. //        This notice may not be removed from this source code.
  12. //
  13. //    This object is included in the MiscKit by permission from the author
  14. //    and its use is governed by the MiscKit license, found in the file
  15. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  16. //    for a list of all applicable permissions and restrictions.
  17. //    
  18.  
  19. #import "MiscTee.h"
  20.  
  21. typedef struct
  22.     {
  23.     // Object *idObject; // Using this would remove warnings _if_ isa were
  24.     // not protected, but as things stand, we'll have to live with the
  25.     // warnings.  :-(  That's what you get for "isa hacking"!
  26.     //id idObject; // This is where we got warnings...original definition...
  27.     struct objc_class *idObject; // This seems to work right...
  28.     SEL    selAction;
  29.     } CONPAIR;
  30.  
  31. @implementation MiscTee
  32.  
  33. - init
  34.     {
  35.     [super init];
  36.     inTee = NO;    
  37.     idConnections = [[Storage alloc] initCount:0 elementSize:sizeof(CONPAIR)
  38.                                      description:@encode(CONPAIR)];
  39.     return self;
  40.     }
  41.  
  42. - free
  43.     {
  44.     [idConnections free];
  45.     
  46.     return [super free];
  47.     }
  48.  
  49. - addConnection:anObject with:(SEL)anAction
  50.     {
  51.     CONPAIR cp;
  52.     CONPAIR * pcp;
  53.     int i;
  54.     
  55.     cp.idObject = anObject;
  56.     cp.selAction = anAction;
  57.     
  58.     // replace the action if the object is already in the list
  59.     for (i = 0; i < [idConnections count]; i++)
  60.         {
  61.         pcp = (CONPAIR *)[idConnections elementAt:i];
  62.         if (pcp->idObject == anObject)
  63.             {
  64.             pcp->selAction = anAction;
  65.             return self;
  66.             }
  67.         }
  68.     
  69.     // new connection
  70.     [idConnections addElement:&cp];
  71.     
  72.     return self;
  73.     }
  74.  
  75. - removeConnection:anObject
  76.     {
  77.     CONPAIR * pcp;
  78.     int i;
  79.     
  80.     for (i = 0; i < [idConnections count]; i++)
  81.         {
  82.         pcp = (CONPAIR *)[idConnections elementAt:i];
  83.         if (pcp->idObject == anObject)
  84.             {
  85.             [idConnections removeElementAt:i];
  86.             break;
  87.             }
  88.         }
  89.     
  90.     return self;
  91.     }
  92.  
  93. - ping:sender
  94. {
  95.     int            i;
  96.     CONPAIR *    pcp;
  97.  
  98.     if (inTee) return self;
  99.     inTee = YES;
  100.     for (i = 0; i < [idConnections count]; i++) {
  101.         pcp = (CONPAIR *)[idConnections elementAt:i];
  102.         if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
  103.                 pcp->idObject != sender && pcp->selAction) {
  104.             [pcp->idObject perform:pcp->selAction with:sender];
  105.         }
  106.     }
  107.     inTee = NO;
  108.     return self;
  109. }
  110.  
  111. - forward:(SEL)aSelector :(marg_list)argFrame
  112.     {
  113.     int            i;
  114.     CONPAIR *    pcp;
  115.     void *        pv = nil;
  116.     BOOL        fSent = NO;
  117.     
  118.     if (inTee) return self;
  119.     inTee = YES;
  120.     for (i = 0; i < [idConnections count]; i++)
  121.         {
  122.         pcp = (CONPAIR *)[idConnections elementAt:i];
  123.         if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
  124.             [pcp->idObject respondsTo:aSelector])
  125.             {
  126.             pv = [pcp->idObject performv:aSelector :argFrame];
  127.             fSent = YES;
  128.             }
  129.         }
  130.     
  131.     if (!fSent)
  132.         {
  133.         [self doesNotRecognize:aSelector];
  134.         }
  135.     inTee = NO;
  136.  
  137.     return (id)pv;
  138.     }
  139.  
  140. -(BOOL) respondsTo:(SEL)aSelector
  141.     {
  142.     int            i;
  143.     CONPAIR *    pcp;
  144.     
  145.     if ([super respondsTo:aSelector])
  146.         {
  147.         return YES;
  148.         }
  149.     
  150.     for (i = 0; i < [idConnections count]; i++)
  151.         {
  152.         pcp = (CONPAIR *)[idConnections elementAt:i];
  153.         if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
  154.             [pcp->idObject respondsTo:aSelector])
  155.             {
  156.             // don't worry about multiple positive responses
  157.             return YES;
  158.             }
  159.         }
  160.     
  161.     return NO;
  162.     }
  163.  
  164. - read:(NXTypedStream *)stream
  165.     {
  166.     [super read:stream];
  167.     
  168.     idConnections = NXReadObject(stream);
  169.     inTee = NO;
  170.     return self;
  171.     }
  172.  
  173. - write:(NXTypedStream *)stream
  174.     {
  175.     [super write:stream];
  176.     
  177.     NXWriteObject(stream, idConnections);
  178.     
  179.     return self;
  180.     }
  181.  
  182. @end
  183.