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.