This is eTFileLink.m in view mode; [Download] [Up]
/////////////////////////////////////////////////////////////////////////////// // FILENAME: eTFileLink.m // SUMMARY: Implementation of file components for eText documents // SUPERCLASS: eTImage // INTERFACE: None // PROTOCOLS: <Annotation,HTMDSupport,ASCIISupport,LaTeXSupport,Tool, // InspectableTarget> // AUTHOR: Rohit Khare // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project /////////////////////////////////////////////////////////////////////////////// // DESCRIPTION // Does its job by an eTComponent and execString. /////////////////////////////////////////////////////////////////////////////// // HISTORY // 10/30/94: Modified to support <InspectableTarget> // 08/06/94: Added symbolic linking support. // 07/21/94: Created. First actual implementation. /////////////////////////////////////////////////////////////////////////////// #import "eTFileLink.h" #define _eTFileLinkPR1 10 #define _eTFileLinkVERSION 20 @implementation eTFileLink // id etFileComponent; // char *execString; // BOOL isExecEnabled; // BOOL useSymlink; - setSymlink:(BOOL)newState {useSymlink = newState; return self;} - setExecEnabled:(BOOL)newState {isExecEnabled = newState; return self;} - (BOOL)useSymlink {return useSymlink;} - (BOOL)isExecEnabled {return isExecEnabled;} - (const char *)componentName {return ((etFileComponent) ? [etFileComponent componentName] : NXUniqueString(""));} - (BOOL)isLinked {return ((etFileComponent) ? [etFileComponent isLinked] : NO);} - (const char *)execString {return execString;} - setExecString:(const char *) newString { if (!newString) return self; if ((!(*execString)) && *newString) isExecEnabled = YES; execString = realloc(execString, (strlen(newString)+1)*sizeof(char)); strcpy(execString, newString); return self; } //////////////////////////// + toolAwake:theApp { [theApp registerAnnotation: [eTFileLink class] name: "eTFileLink" RTFDirective: "eTFileLink" menuLabel: NULL menuKey: '\0' menuIcon: (NXImage *) nil]; [theApp registerType:NXCreateFileContentsPboardType(ANY_TYPE) for:[eTFileLink class]]; [eTRTFDFileLink toolAwake:theApp]; // "delegate chain" return self; } - init { [super init]; [self setUsesButtonStyle:NO]; [self setDraggable:YES]; isExecEnabled = NO; useSymlink = NO; if (!execString) { execString = malloc(2 * sizeof(char)); execString[0] = '\0'; } return self; } - free { free(execString); etFileComponent = [etFileComponent free]; return self = [super free]; } - _hack:sender { // this is to prevent deadlock with the Workspace when // requesting an icon during a dragging session // This is hardcoded: all FileLinks are ANY_TYPE; icons are .tiff char imgName[MAXPATHLEN]; sprintf(imgName,"%s.tiff",[etFileComponent componentName]); [self setImageComponent:[[[eTImageComponent alloc] initInDoc:etDoc linked:NO] useImage:[etFileComponent icon] name:imgName path:NXUniqueString("") shared:NO]]; [self updateGraphics]; return self; } - initFromPboard:thePB inDoc:theDoc linked:(BOOL) linked { NXAtom types[3]; char *data; int len; [self init]; // we prevent super from executing initFromPboard, so we have to: etDoc = theDoc; theText = [[etDoc docUI] eTextObj]; // consistency checking [etDoc registerNotification:self]; types[0] = NXCreateFileContentsPboardType(ANY_TYPE); types[1] = NXFilenamePboardType; types[2] = [thePB findAvailableTypeFrom:types num:2]; if (!types[2]) return self; if (types[2] == NXFilenamePboardType) { [thePB readType:NXFilenamePboardType data:&data length:&len]; if (index(data,'\t')) *(index(data,'\t'))=0; etFileComponent = [[eTComponent alloc] initInDoc:etDoc linked:linked]; [etFileComponent readComponentFromPath:data]; [self perform:@selector(_hack:) with:nil afterDelay:0 cancelPrevious:NO]; [thePB deallocatePasteboardData:data length:len]; } else { NXLogError("%s got fcontents without fnamepboard! %s instead.\n", [[self class] name], types[2]); } return self; } - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat { if(!etDoc) NXLogError("etDoc is nil at %s %u",__FILE__,__LINE__); if (useSymlink) [etFileComponent writeComponentToPath:path inFormat:theFormat]; else [etFileComponent linkComponentToPath:path]; return [super writeComponentToPath:path inFormat:theFormat]; } - addToPboard:pboard { [etFileComponent addToPboard:pboard]; return self; } - readRichText:(NXStream *)stream forView:view { int i, ver; char buf[MAXPATHLEN]; NXScanf(stream, "%d ", &ver); if ((ver != _eTFileLinkVERSION) && (ver != _eTFileLinkPR1)) { // bad version block. NXLogError("eTFileLink found unparseable version %d at position %d", ver, NXTell(stream)); return nil; } NXScanf(stream, "%c ", &isExecEnabled); isExecEnabled -= 'A'; if (ver == _eTFileLinkVERSION) { NXScanf(stream, "%c ", &useSymlink); useSymlink -= 'A'; } NXScanf(stream, "%d", &i); NXGetc(stream); // space-eater if (i) { NXRead(stream, buf, i); buf[i] = 0; [self setExecString:buf]; NXGetc(stream); // trailing space } // if i was zero, we have already advanced to the next non-white bit. [super readRichText:stream forView:view]; NXGetc(stream); // separating space etFileComponent = [[[eTComponent alloc] init] readRichText:stream forView:view]; return self; } - writeRichText:(NXStream *)stream forView:view { NXPrintf(stream, "%d %c %c %d %s ", _eTFileLinkVERSION, isExecEnabled + 'A', useSymlink + 'A', strlen(execString), execString); [super writeRichText:stream forView:view]; NXPutc(stream, ' '); // separate the two visually [etFileComponent writeRichText:stream forView:view]; return self; } - writeASCIIRef:(NXStream *)stream forView:view { NXPrintf(stream, "See the file %y (last known address:%s)\n\t", [etFileComponent componentName], [etFileComponent currentPath]); [super writeASCIIRef:stream forView:view]; return self; } - writeLaTeX:(NXStream*)stream forView:view { [super writeLaTeX:stream forView:view]; [etFileComponent writeLaTeX:stream forView:view andClose:(*execString ? YES : NO)]; if (*execString) NXPrintf(stream, " Try executing the file with {\\tt %w}.}\n", execString); return self; } - writeHTML:(NXStream *)stream forView:view { [etFileComponent writeHTML:stream forView:view andClose:NO]; [super writeHTML:stream forView:view]; // icon-buttons. if (*execString) NXPrintf(stream, "(execute this file with <TT>"%v"</TT>)", execString); NXPrintf(stream,"</A>"); return self; } - doubleClick:(NXEvent*)e { NXAtom fname = [etFileComponent currentPath]; if (*fname && !access(fname, F_OK|R_OK)) { //ok, now do we open or use execString? if (isExecEnabled && *execString) { char cmd[MAXPATHLEN]; id sPanel; sprintf(cmd, execString, fname, fname, fname); // undocumented hole: extra fnames are passed on the stack sPanel = NXGetAlertPanel("eTFileLink", "Executing the command \"%s\"", NULL, NULL, NULL, cmd); [sPanel setFloatingPanel:NO]; [sPanel setHideOnDeactivate:YES]; [sPanel orderFront:self]; NXPing(); system(cmd); if (sPanel) { [sPanel orderOut:self]; NXFreeAlertPanel(sPanel); } } else { // we need to flip the location y coord NXPoint pt; NXSize sz; id img; pt = e->location; img = [etFileComponent icon]; [theText convertPoint:&pt fromView:nil]; [img getSize:&sz]; pt.x -= sz.width/2; pt.y += sz.height/2; [[Application workspace] openFile:fname fromImage: img at: &pt inView:theText]; } } else { if (*fname) NXRunAlertPanel("eTFileLink","Could not access() %s.","OK",NULL,NULL,fname); } return self; } - inspect:(NXEvent *) e { [[NXApp inspector] inspect:self]; return self; } - (id <Inspectable>) inspectableDelegate { return [[eTFileLinkUI new] setAnnotation:self]; } - drag: (Pasteboard *)draggingPboard image:(NXImage **)proxyImage { if (! etFileComponent) { *proxyImage = nil; return nil; } [etFileComponent writeComponentToPboard:draggingPboard]; *proxyImage = [etFileComponent icon]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.