This is eTComponent.m in view mode; [Download] [Up]
/////////////////////////////////////////////////////////////////////////////// // FILENAME: eTComponent.m // SUMMARY: Implementation of a generic external-data-container class. // SUPERCLASS: Object // INTERFACE: None // PROTOCOLS: <ComponentData, // ETFDSupport,ASCIISupport,HTMDSupport, LaTeXSupport> // AUTHOR: Rohit Khare and Tom Zavisca // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project /////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION COMMENTS // This implementation is a hack: it uses system() calls to have files // copied. This avoids setting up our own buffer functions and works // for directories, too. This also just a default implementation; subclasses // will most likely define their own methods. // // The revision of 7/19 introduces a new two-phase lifecycle, // initInDoc:linked: followed by readComponent from path or Pboard. // // Eventually, there is room for an eTComponentBinder that will uniq' refs. /////////////////////////////////////////////////////////////////////////////// // HISTORY // 12/23/94: Patched to reset eTDoc everywhere // 08/06/94: Added symbolic linking support. // 07/19/94: Rewritten/Reorganized as described in Actors/eTComponent.rtf // 07/10/94: Created. /////////////////////////////////////////////////////////////////////////////// #import "eTComponent.h" #define _eTComponentVERSION 20 @implementation eTComponent // NXAtom componentName; // NXAtom currentPath; // BOOL shouldEdit; // BOOL isDirty; // BOOl isLinked; // id etDoc; // id icon; //////////// ACCESSOR METHODS //////////////// - setComponentName:(const char*)newComponentName {componentName = NXUniqueString(newComponentName); return self;} - (const char *) componentName {return componentName;} - (const char *) currentPath {return currentPath;} - etDoc {return etDoc;} - icon { if (!icon) { icon = [[Application workspace] getIconForFile:currentPath]; if (!icon) icon = [NXImage findImageNamed:"NXdefaulticon"]; } return icon;} - (BOOL) isLinked {return isLinked;} - (BOOL) isMutable // this call checks shouldEdit {return (shouldEdit && (!isLinked));} - setShouldEdit:(BOOL) newState {shouldEdit = newState; return self;} - setLinked:(BOOL) newState {isLinked = newState; return self;} - setDoc:newDoc { if (newDoc && [newDoc respondsTo:@selector(registerComponent:)]) etDoc = newDoc; // Always reset if possible; bugfix for shared images, 12/23 return self; } - touch {isDirty=YES; return self;} //////////// LIFECYCLE MANAGEMENT //////////// - init // default initializer { return [self initInDoc:nil linked:NO]; } - initInDoc:newDoc linked: (BOOL) linked { char tmp[128]; [super init]; isLinked = linked; etDoc = newDoc; isDirty = NO; shouldEdit = YES; icon = nil; sprintf(tmp, "Untitled-%d", [NXApp uniqueID]); componentName = NXUniqueString(tmp); currentPath = NXUniqueString(""); return self; } ////////////// READING/WRITING /////////////// - readComponentFromPath:(const char*)newPath { char *tmp; // Have we been passed a valid pathname? if(!(newPath && (*newPath))) { NXLogError("Severe Error, bad path to readComponentFromPath"); return nil; } if (access(newPath, F_OK|R_OK)) { NXLogError("%s could not access(%s)", [[self class]name],newPath); } currentPath = NXUniqueString(newPath); tmp = rindex(newPath,'/'); if (tmp && *(tmp+1)) componentName = NXUniqueString(tmp+1); return self; } - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat { char target[MAXPATHLEN]; char cmd[2*MAXPATHLEN]; switch(theFormat) { case ETFD_FMT: [etDoc registerComponent:componentName]; // always register // if it's linked, just return. if (isLinked) break; sprintf(target,"%s/%s",path,componentName); // see if the diskfile already exists if ((!isDirty) && (!access(target, F_OK|R_OK))) break; // ok, copy the raw bits. if (currentPath && *currentPath && target && *target) { sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target); system(cmd); } // since we have saved ETFD, reset the "clean" state currentPath = NXUniqueString(target); isDirty = NO; break; case TeXD_FMT: if (isLinked) break; case HTMD_FMT: // In these formats, we always force copying of the data resource [etDoc registerComponent:componentName]; // always register sprintf(target,"%s/%s",path,componentName); // see if the diskfile already exists if ((!isDirty) && (!access(target, F_OK|R_OK))) break; if (currentPath && *currentPath && target && *target) { sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target); system(cmd); } break; } return self; } - linkComponentToPath:(NXAtom)path { char target[MAXPATHLEN]; char cmd[2*MAXPATHLEN]; [etDoc registerComponent:componentName]; // always register sprintf(target,"%s/%s",path,componentName); // see if the diskfile already exists if (access(target, F_OK|R_OK)){ if (currentPath && *currentPath && target && *target) { sprintf(cmd,"ln -s \"%s\" \"%s\"", currentPath, target); system(cmd); } } return self; } - readComponentFromPboard:(Pasteboard *)thePboard { NXAtom foundType; NXAtom supportedTypes[2] = {NXFilenamePboardType, NXFileContentsPboardType}; foundType = [thePboard findAvailableTypeFrom:supportedTypes num:2]; if (foundType == NXFilenamePboardType) { // can we derive a resource name? if not, make path the resource name char *path; int len; [thePboard readType:NXFilenamePboardType data:&path length:&len]; // we only process _ONE_ filename; this defeats the tab-separation if (index(path, '\t')) *index(path, '\t')=0; if (rindex(path, '/')) { componentName = NXUniqueString(rindex(path,'/')+1); currentPath = NXUniqueString(path); } else { currentPath = componentName = NXUniqueString(path); } [thePboard deallocatePasteboardData:path length:len]; } else if (foundType == NXFileContentsPboardType) { char *path,tmp[MAXPATHLEN]; sprintf(tmp,"/tmp/eTComponent.in.%x", [NXApp uniqueID]); path = [thePboard readFileContentsType:NULL toFile:tmp]; currentPath = NXUniqueString(path); componentName = NXUniqueString(rindex(path,'/')+1); free(path); // readFile... returns a malloc'd actual path } return self; } - writeComponentToPboard:(Pasteboard *)thePboard { // find out where the file is and encode that to the Pboard. if (!(*currentPath) || access(currentPath, F_OK)) return nil; [thePboard declareTypes:&NXFilenamePboardType num:1 owner:nil]; [thePboard writeType:NXFilenamePboardType data:currentPath length:strlen(currentPath)]; return self; } - addToPboard:thePboard { if (!(*currentPath) || access(currentPath, F_OK)) return nil; [thePboard addTypes:&NXFilenamePboardType num:1 owner:nil]; [thePboard writeType:NXFilenamePboardType data:currentPath length:strlen(currentPath)]; return self; } ///////// ADDITIONAL FMT PROTOCOL SUPPORT //////////// - readRichText:(NXStream *)stream forView:view { char buf[MAXPATHLEN]; const char *tmp; int i; id temp; temp = [view etDoc]; if (temp && [temp respondsTo:@selector(registerComponent:)]) etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23 NXScanf(stream, "%d ", &i); if (i != _eTComponentVERSION) { // bad version block. NXLogError("eTComponent found unparseable version %d at position %d", i, NXTell(stream)); return nil; } NXScanf(stream, "%c %c %d", &isLinked, &shouldEdit, &i); NXGetc(stream); // space-eater isLinked -= 'A'; shouldEdit -= 'A'; if (i) NXRead(stream, buf, i); buf[i] = 0; currentPath = NXUniqueString(buf); NXScanf(stream, " %d", &i); NXGetc(stream); // space-eater if (i) NXRead(stream, buf, i); buf[i] = 0; componentName = NXUniqueString(buf); if(!access(currentPath, F_OK|R_OK) || isLinked) return self; if(etDoc && (tmp = [[etDoc docInfo] docPath])) { sprintf(buf,"%s/%s",tmp,componentName); if(!access(buf, F_OK|R_OK)) { currentPath = NXUniqueString(buf); #ifdef DEBUG NXLogError("Found %s at %s not %s/%s", componentName,buf,currentPath,componentName); #endif return self; } } #ifdef DEBUG NXLogError("Could not access %s or %s! %s readRichText: failed!", currentPath,buf,[[self class] name]); #endif return nil; } - writeRichText:(NXStream *)stream forView:view { // since this method is called before any writeComponents, we attempt // to precompute the future currentPath // RULE: if (isLinked), currentPath is valid // RULE: otherwise, componentName is valid, so precompute currentPath const char *tmp; char target[MAXPATHLEN]; id temp; temp = [view etDoc]; if (temp && [temp respondsTo:@selector(registerComponent:)]) etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23 if (isLinked) tmp = currentPath; else { sprintf(target, "%s/%s",[[etDoc docInfo] docPath], componentName); tmp = target; } NXPrintf(stream, "%d %c %c %d %s %d %s", _eTComponentVERSION, isLinked+'A', shouldEdit+'A', strlen(tmp), tmp, strlen(componentName), componentName); return self; } - writeASCIIRef:(NXStream *)stream forView:view { id temp; temp = [view etDoc]; if (temp && [temp respondsTo:@selector(registerComponent:)]) etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23 NXPrintf(stream, "A %s%s reference to the file %s\n", (isLinked ? "linked " : ""), [[self class] name], (isLinked ? currentPath : componentName)); return self; } - writeHTML:(NXStream *)stream forView:view {return [self writeHTML:stream forView:view andClose:YES];} - writeHTML:(NXStream *)stream forView:view andClose:(BOOL)closeIt { id temp; temp = [view etDoc]; if (temp && [temp respondsTo:@selector(registerComponent:)]) etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23 //NXPrintf(stream, "<A HREF=\"%V%V\">%v:%v</A>", // (isLinked ? "http://localhost/" : ""), // (isLinked ? currentPath : componentName), // [[self class] name],(isLinked ? currentPath : componentName)); // In the NEW scheme of things, HTML component data is _ALWAYS_ // written out explicitly, so none of this localhost shit. NXPrintf(stream,"<A HREF=\"%V\">",componentName); if (closeIt) NXPrintf(stream,"%v</A>",componentName); return self; } - writeLaTeX:(NXStream *)stream forView:view {return [self writeLaTeX:stream forView:view andClose:YES];} - writeLaTeX:(NXStream *)stream forView:view andClose:(BOOL)closeIt { id temp; temp = [view etDoc]; if (temp && [temp respondsTo:@selector(registerComponent:)]) etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23 NXPrintf(stream, "\n\\footnote{A %w%w reference to the file %w.", (isLinked ? "linked " : ""), [[self class] name], (isLinked ? currentPath : componentName)); if (closeIt) NXPrintf(stream, "}\n"); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.