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;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.