This is CEMethod.m in view mode; [Download] [Up]
/* CEMethod.m
*
* This object controls the data of a beaker (molecules, cameras, groups etc.)
* It is the main document of BeakerBoy and controls everything from loading to
* setting up the browser which does most of the other work.
*
* For interface-info see the header file. The comments in this file mostly
* cover only the real implementation details.
*
* Written by: Thomas Engel
* Created: 23.10.1993 (Copyleft)
* Last modified: 12.11.1994
*/
#define CURRENT_VERSION 1
#import <CEMethod.h>
#import <misckit/MiscString.h>
@implementation CEMethod
+ initialize
{
if ( self == [CEMethod class] )
[CEMethod setVersion:CURRENT_VERSION];
return self;
}
- init
{
[super init];
return [self initFromText:[MiscString newWithString:"- myMethod:sender"]];
// BUG BUG..memory leak !
}
- initFromText:theLine
{
// We will create a new method that stores the given string
// representation.
// The method name WILL be changed to conform to the following
// example..as far as spaces ar concerned:
//
// old: - ( char*)getStringFor: (aType) string andMore:(char *) this ;
// new: - (char *)getStringFor:(aType)string andMore:(char *)this
id tokens;
int i;
id tempString;
int parts;
[super init];
name = [MiscString new];
[name takeStringValue:theLine];
// removing the "\" sign should be enough to support basic RTF source
// properly.
[name replaceEveryOccurrenceOf:";" with:" "];
[name replaceEveryOccurrenceOf:"\\" with:" "];
[name trimWhiteSpaces];
[name squashSpaces];
// Now charAt:0 _MUST_ be the method type !!
selectorName = [MiscString new];
tokens = [self methodTokens];
parts = 0;
for( i=0; i<[tokens count]; i++ )
{
tempString = [tokens objectAt:i];
if( [tempString grep:":"] )
{
[selectorName concatenate:tempString];
parts++;
}
}
// Now if we haven't add even one part...this method has only one. And we
// have to use at least that one. It has to be the last string because we
// can't have valid parameters anyway..right...
if( parts == 0 ) [selectorName concatenate:
[tokens objectAt:[tokens count]-1]];
[[tokens freeObjects] free];
return self;
}
- free
{
[name free];
[selectorName free];
return [super free];
}
- (const char *)name
{
return [name stringValue];
}
- (const char *)selectorName
{
return [selectorName stringValue];
}
- methodTokens
{
// this method returns a list htat contains the single tokens of this
// method. like: (BOOL), set:, (char *), aString
// The receiver has to free the method !
int i;
id tokens;
id aString;
BOOL isCast;
char current;
// First let's tokenize according to the braces and spaces.
// Remember that the method should be clean right now. Only Spaces.
// And only one at a time.
// It will be simpler to dangle trought the string by hand...then
// finding some cool tokenize-regex combination.
tokens = [List new];
isCast = NO;
aString = [MiscString new];
for( i=2; i<[name length]; i++ )
{
// Now lets check the differnt type of tokens...
// First lets split them at the places where they have
current = [name charAt:i];
[aString addChar:current];
// Now if we find a "(" we will start parsing a cast. Until we find a
// ")" we will add everything we find.
if( current == '(' )
{
isCast = YES;
}
else if( current == ')' )
{
[tokens addObject:aString];
aString = [MiscString new];
isCast = NO;
}
// Finding a ":" means that we will add a selector.
else if( current == ':' )
{
[tokens addObject:aString];
aString = [MiscString new];
}
// Now given tha fact that we can only have one Space at the time
// this must be the end of a parameter is it is not part of a cast.
// sure..we sould remove the space from the string before adding it.
else if( current == ' ' &&
isCast == NO )
{
[aString trimSpaces];
if( [aString emptyString] == NO )
{
[tokens addObject:aString];
aString = [MiscString new];
}
}
}
// If there is something inside the string we will add it to the
// tokens. This is to be sure that we catch all the parts.
if( [aString emptyString] == NO )
[tokens addObject:aString];
return tokens;
}
- (int)numberOfArguments
{
// returns the number of arguments this method takes.
return [selectorName numOfChar:':'];
}
- (BOOL)isInstanceMethod
{
if( [name charAt:0] == '+' ) return NO;
return YES;
}
// dragging handling
- dragImage
{
if( [self isInstanceMethod] )
return [NXImage findImageNamed:"InstanceMethod"];
return [NXImage findImageNamed:"ClassMethod"];
}
- (const char *)dragImageTitle
{
return [self selectorName];
}
- prepareDraggingPboard:aPboard
{
return [self copyTo:aPboard];
}
- copy
{
return self;
}
- copyTo:aPasteboard
{
NXAtom textTypes[5];
NXStream *textStream;
textTypes[0] = NXRTFPboardType;
textTypes[1] = NXAsciiPboardType;
textTypes[2] = NULL;
[aPasteboard declareTypes:textTypes num:2 owner:self];
// Just write the selector...this might be useful for creating references !
// It is not intended to be absolutely cool in the future.
// In the future we will place some kind of object ref on the pasteboard
// and perhaps even the whole source when we do ASCII / RTF drags.
// First lets put down the RTF version..
textStream = NXOpenMemory( NULL, 0, NX_WRITEONLY );
NXPrintf( textStream, "{\\rtf0\\ansi{\\fonttbl" );
NXPrintf( textStream, "\\f0\\fnil Symbol;" );
NXPrintf( textStream, "\\f1\\fnil Times-Roman;" );
NXPrintf( textStream, "\\f2\\fnil Times-Bold;" );
NXPrintf( textStream, "}\n" );
NXPrintf( textStream, "\\f0\\fs28 " );
NXPrintf( textStream, "-" );
NXPrintf( textStream, "\\f1 " );
NXPrintf( textStream, " " );
NXPrintf( textStream, "\\f2 " );
NXPrintf( textStream, [self selectorName] );
NXPrintf( textStream, "\\f1 " );
NXPrintf( textStream, ", " );
NXPrintf( textStream, "}" );
[aPasteboard writeType:NXRTFPboardType fromStream:textStream];
NXCloseMemory( textStream, NX_FREEBUFFER );
// Now write the ASCII version..
textStream = NXOpenMemory( NULL, 0, NX_WRITEONLY );
NXPrintf( textStream, "- " );
NXPrintf( textStream, [self selectorName] );
NXPrintf( textStream, ", " );
[aPasteboard writeType:NXAsciiPboardType fromStream:textStream];
NXCloseMemory( textStream, NX_FREEBUFFER );
return self;
}
// we are conform to the MiscCompare protocol...actuall all we have is
// a single compare method.
- (int)compare:anObject
{
// Compares the to selectors...caseSensitive !
// BUG: We will only compare to other methods...but don't chack for that !
return [selectorName cmp:[anObject selectorName]];
}
- (int)compare:anObject ignoreCase:(BOOL)flag
{ return [self compare:anObject];
}
- (int)compare:anObject length:(unsigned long)length
{ return [self compare:anObject];
}
- (int)compare:anObject length:(unsigned long)length ignoreCase:(BOOL)flag
{ return [self compare:anObject];
}
- (int)compareLiteral:(const char *)literal
{ return 0;
}
- (int)compareLiteral:(const char *)literal ignoreCase:(BOOL)flag
{ return 0;
}
- (int)compareLiteral:(const char *)literal length:(unsigned long)length
{ return 0;
}
- (int)compareLiteral:(const char *)literal length:(unsigned long)length ignoreCase:(BOOL)flag
{ return 0;
}
@end
/*
* History: 13.01.95 Buh
*
*
* Bugs: - ...
*/These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.