This is eTRTFDFileLink.m in view mode; [Download] [Up]
/////////////////////////////////////////////////////////////////////////////// // FILENAME: eTRTFDFileLink.h // SUMMARY: Implementation of an RTFD inclusion handler // SUPERCLASS: eTFileLink:eTImage:Object // INTERFACE: None // PROTOCOLS: None added // AUTHOR: Rohit Khare // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project /////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION COMMENTS // Okay: here are the facts of life about NeXT's lousy RTFD implementation // (trust me, I know, I know the Text object every which way except from the // inside... grrr). It goes: // <space char>string<spacechar>\width<inTwips>\height<inTwips>\n} // (the string spec is such that you have to read it in two passes -- that's // why I always prefix a string by the length. (e.g. NeXT fails on a file // named "\width960")) // // OK, once you have the string, you have a relative filename component. Where // do we get the root filename component? We assume that we can reach out // and access() [[[view etDoc] docInfo] docPath]. // // OK, now we have a fully-qualified absolute pathname. If it's a TIFF image, // we want to promote self to be an eTImage object encapsulating that file. // otherwise we want to be an eTFileLink. // // THERE ARE NO eTRTFDFileLinks IN THE SYSTEM AFTER readRichText: !!!! // All such instances are "promoted" by redirecting their isa pointer // Thus, when the file is written out, RTFD-objects will be implicitly // promoted to first-class eText objects. // // As an exercise for the reader: With enough cojones, it should be possible // to write a generic mutator to eTImage-derived objects; just make sure that // this object has as many bytes of storage as the larget morph target. Then // you could _automatically_ morph a .snd inclusion into an eTAudio :) /////////////////////////////////////////////////////////////////////////////// // HISTORY // 07/23/94: Created. First actual implementation. /////////////////////////////////////////////////////////////////////////////// #import "eTRTFDFileLink.h" @implementation eTRTFDFileLink + toolAwake: theApp { [theApp registerAnnotation: [eTRTFDFileLink class] name: "eTRTFDFileLink" RTFDirective: "NeXTGraphic" menuLabel: NULL menuKey: '\0' menuIcon: (NXImage *) nil]; return self; } - readRichText:(NXStream *) stream forView:view { const char *const * types; char *ext; NXAtom localPath,rootPath; char buffer[MAXPATHLEN],ch; int height=0, width=0,i=0; char *tmp; BOOL foundImage=NO; // we first have to do this because this silly hack-class of ours can't // call [super readRichText:...] (this code is in eTImage.m) if (!etDoc || !theText) { theText = view; etDoc = [theText etDoc]; [etDoc registerNotification:self]; } // first fill in the buffer with all the characters up to and including \n while ((i < MAXPATHLEN) && ((ch = NXGetc(stream)) != '\n')) { buffer[i++] = ch; } buffer[i] = 0; // now work backward to get height. tmp = rindex(buffer,'\\'); if (tmp && !strncmp(tmp, "\\height",7)) { //we have a valid \height entry beginning at tmp sscanf(tmp+7,"%d",&height); // now nullify the \ so we can go backwards to \width *tmp = 0; } // now work backward to get width. tmp = rindex(buffer,'\\'); if (tmp && !strncmp(tmp, "\\width",6)) { //we have a valid \height entry beginning at tmp sscanf(tmp+6,"%d",&width); // now nullify the \ so we can go backwards to the string *tmp = 0; // and also consume the space character separating string from \width *(tmp - 1) = 0; } // skip the leading space -- is there one? tmp = buffer; if (*tmp == ' ') tmp++; localPath = NXUniqueString(tmp); rootPath = [[[view etDoc] docInfo] docPath]; sprintf(buffer, "%s/%s", rootPath, localPath); // OK, now what? We have valid data. //NXLogError("\\NeXTGraphic got \"%s\" h:%d w:%d in \"%s\"", // localPath, height, width, rootPath); tmp = rindex(buffer,'/'); //get the extension of the basename. tmp = rindex(tmp,'.'); if (tmp && *(++tmp)) { // ext is now a pointer to the extension of buffer, if there is one. ext = NXUniqueString(tmp); // ext of basename types = [NXImage imageFileTypes]; for(i=0; (types[i] && !foundImage); i++) if (!strcmp(ext,types[i])) foundImage = YES; } if (foundImage) { // If the target file can be viewed as imageable data, we should // "morph" into an eTImage instance based on that file. // The code that eTImage would execute in this situation: // 1) create an imageComponent // 2) [self setImageComponent] self->isa = [eTImage class]; // assumes that we are a subclass of it [self setImageComponent: [[[eTImageComponent alloc] initInDoc:etDoc linked:NO] readComponentFromPath:buffer]]; } else { // else we need to init etFileComponent _and_ attempt to initialize // eTImageComponent from buffer.tiff. self->isa = [eTFileLink class]; etFileComponent = [[[eTComponent alloc] initInDoc:etDoc linked:NO] readComponentFromPath:buffer]; strcat(buffer,".tiff"); //this is NeXT's default behavior [self setImageComponent: [[[eTImageComponent alloc] initInDoc:etDoc linked:NO] readComponentFromPath:buffer]] ; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.