This is DrawingView.m in view mode; [Download] [Up]
/* * (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved. * * (b) If this Sample Code is distributed as part of the Display PostScript * System Software Development Kit from Adobe Systems Incorporated, * then this copy is designated as Development Software and its use is * subject to the terms of the License Agreement attached to such Kit. * * (c) If this Sample Code is distributed independently, then the following * terms apply: * * (d) This file may be freely copied and redistributed as long as: * 1) Parts (a), (d), (e) and (f) continue to be included in the file, * 2) If the file has been modified in any way, a notice of such * modification is conspicuously indicated. * * (e) PostScript, Display PostScript, and Adobe are registered trademarks of * Adobe Systems Incorporated. * * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO * CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED * AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED. * ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY * OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO * WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY) * WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY * DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT * OF THIRD PARTY RIGHTS. */ /* * DrawingView.m * * This view represents the page that the image is drawn onto. * * An offscreen buffer, bufferId, is used to draw into and then * this buffer is composited onscreen. This technique allows for the * separation of the static drawing from the temporal drawing (modal * loop redrawing and control point display). The static drawing takes * place in the buffer while the temporal drawing takes place in this view. * The static drawing is stuff that is complex and that will stay around for * a while. Saving this drawing in a buffer elimates having to redraw it * for something simple like drawing a control point or something. * (The bufferId is the content view of a plain window the size of this view); * * Version: 2.0 * Author: Ken Fromm * History: * 03-17-91 Added this comment, fixed the preview exporting * section. */ #import "DrawingView.h" #import "Document.h" #import "GraphicImport.h" #import "SaveAsPanel.h" #import "epsf.h" #import "DrawingViewWraps.h" #import <appkit/Cell.h> #import <appkit/ClipView.h> #import <appkit/Matrix.h> #import <appkit/NXCursor.h> #import <appkit/NXImage.h> #import <appkit/NXBitmapImageRep.h> #import <appkit/Text.h> #import <appkit/nextstd.h> #import <dpsclient/dpsclient.h> #import <dpsclient/wraps.h> #import <math.h> extern char ControlFont[ ]; extern const NXRect DefaultWindowRect; static char EpsfProcSet[] = "EPSF_Illustrator_abbrev 0 0"; void compositeBuffer(int gstate, const NXRect *srce, const NXPoint *dest, int op) { PScomposite(NX_X(srce), NX_Y(srce), NX_WIDTH(srce), NX_HEIGHT(srce), gstate, dest->x, dest->y, op); } /* * The buffer is used to prevent unnecessary drawing by * retaining the image offscreen. * * Create a plain window the size of the rectangle passed in and * then insert a view into the window as a subview. */ static id createBuffer(const NXSize *size) { id buffer, window; NXRect contRect; contRect.origin.x = contRect.origin.y = 0; contRect.size = *size; window = [Window newContent:&contRect style:NX_PLAINSTYLE backing:NX_RETAINED buttonMask:0 defer:NO] ; buffer = [[[View newFrame:&contRect] allocateGState] setClipping:NO]; [[window setContentView:buffer ] free]; [ window display]; return buffer; } @implementation DrawingView +newFrame:(const NXRect *) frameRect { self = [super newFrame:frameRect]; [[self allocateGState] setClipping:NO]; bufferId = createBuffer(&frameRect->size); return self; } - free { [graphicId free]; return [super free]; } - buffer { return bufferId; } - image { return imageId; } - (float) controlPointSize { return FONTSIZE; } - resetCursorRects { [self addCursorRect:&bounds cursor:[NXApp cursor]]; return self; } /* * This method copies the PostScript code for the graphics and writes it to the * stream passed in. Includes the preview image when appropriate. */ - writePSToStream:(NXStream *) stream { id nximageId; NXRect bbox; if (stream) { nximageId = NULL; imageId = NULL; [graphicId getBounds:&bbox]; if ([[SaveAsPanel new] format] == SAVE_EPSPREVIEW) { nximageId = [[NXImage alloc] initSize:&bbox.size]; [nximageId useCacheWithDepth:NX_TwoBitGrayDepth]; if ([nximageId lockFocus]) { PStranslate(-bbox.origin.x, -bbox.origin.y); PSsetgray(NX_WHITE); NXRectFill(&bbox); [graphicId drawObject:&bbox withFlags:NOFLAGS inView:self]; imageId = [[NXBitmapImageRep alloc] initData:NULL fromRect:&bbox]; [nximageId unlockFocus]; } } [self copyPSCodeInside:&bbox to:stream]; [nximageId free]; [imageId free]; imageId = NULL; } return self; } /* Deletes the epsf object if it is selected. */ - delete:sender { float knobsize; NXRect rect; if ([graphicId selected]) { knobsize = -[self controlPointSize]; [graphicId getBounds:&rect]; NXInsetRect(&rect, knobsize, knobsize); [graphicId free]; graphicId = NULL; [self display:&rect :1]; } return self; } /* * Constrain the point within the view. An offset is needed because when * an object is moved, it is often grabbed in the center of the object. If the * lower left offset and the upper right offset were not included then part of * the object could be moved off of the view. (In some applications, that might * be allowed but in this one the object is constrained to always lie in the * page.) */ - constrainPoint:(NXPoint *)aPt withOffset:(const NXSize*)llOffset :(const NXSize*)urOffset { float margin; NXPoint viewMin, viewMax; margin = ceil(FONTSIZE/2); viewMin.x = bounds.origin.x + llOffset->width + margin; viewMin.y = bounds.origin.y + llOffset->height + margin; viewMax.x = bounds.origin.x + bounds.size.width - urOffset->width - margin; viewMax.y = bounds.origin.y + bounds.size.height - urOffset->height - margin; aPt->x = MAX(viewMin.x, aPt->x); aPt->y = MAX(viewMin.y, aPt->y); aPt->x = MIN(viewMax.x, aPt->x); aPt->y = MIN(viewMax.y, aPt->y); return self; } /* * Constrain a rectangle within the view. */ - constrainRect:(NXRect *)aRect { float margin; NXPoint viewMin, viewMax; margin = ceil(FONTSIZE/2); viewMin.x = bounds.origin.x + margin; viewMin.y = bounds.origin.y + margin; viewMax.x = bounds.origin.x + bounds.size.width - aRect->size.width - margin; viewMax.y = bounds.origin.y + bounds.size.height - aRect->size.height - margin; aRect->origin.x = MAX(viewMin.x, aRect->origin.x); aRect->origin.y = MAX(viewMin.y, aRect->origin.y); aRect->origin.x = MIN(viewMax.x, aRect->origin.x ); aRect->origin.y = MIN(viewMax.y, aRect->origin.y); return self; } /* * Redraws the graphic. The image from the buffer is composited * into the window and then the changed object is drawn atop the * old image. A copy of the image is necessary because if the * window were to allow scrolling the buffer would also have to be * scrolled. Were this to happen the old image might have to be redrawn. * As a result, a copy is created and the changes performed on the * copy. Care is taken to limit the amount of area that must be * composited and redrawn. * * Even though scrolling is not allowed in this instance, a copy is * created anyways. */ - redrawObject:(int) pt_num { id copyId; BOOL tracking, dirtyFlag = NO; int old_mask; float knobsize; NXPoint pt, pt_last, pt_old, delta; NXRect rect_now, rect_start, rect_last; NXEvent *event; /* * The freeTemp method is messaged at the bottom so as not to free * the shared items. */ copyId = [graphicId copy]; knobsize = -[self controlPointSize]; [copyId getBounds:&rect_start]; NXInsetRect(&rect_start, knobsize, knobsize); rect_now = rect_last = rect_start; [copyId getPoint:pt_num :&pt_last]; pt_old = pt_last; old_mask = [window addToEventMask:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; if (event->type != NX_MOUSEUP) { tracking = YES; while (tracking) { pt = pt_old = event->location; [self convertPoint:&pt fromView:nil]; [copyId constrainPoint:&pt forPtNum:&pt_num inRect:&bounds withFlags:event->flags]; delta.x = pt.x - pt_last.x; delta.y = pt.y - pt_last.y; if (delta.x || delta.y) { dirtyFlag = YES; /* Change the point location and get the new bounds. */ [copyId setPoint:pt_num :&delta]; [copyId getBounds:&rect_now]; NXInsetRect(&rect_now, knobsize, knobsize); /* Composite the old image and then redraw the new one. */ compositeBuffer([bufferId gState], &rect_last, &rect_last.origin, NX_COPY); [self drawObject:copyId forRect:&rect_now withFlags:REDRAWFLAG]; [self drawControl:copyId forRect:&rect_now withFlags:NOFLAGS]; /* Sync up the drawing so it proceeds a little smoother. */ [window flushWindow]; NXPing(); rect_last = rect_now; pt_last = pt; } event = [NXApp getNextEvent:NX_MOUSEUPMASK| NX_MOUSEDRAGGEDMASK]; tracking = (event->type != NX_MOUSEUP); } } [window setEventMask:old_mask]; [graphicId freeTemp]; graphicId = copyId; if (dirtyFlag) { /* * The view has already been focused and we know what * has to be redrawn so call drawSelf:: instead of display */ NXUnionRect(&rect_last, &rect_start); [self drawSelf:&rect_start :1]; [window flushWindow]; NXPing(); } return self; } /* * Moves the selected objects by performing a translate before drawing * the objects. This approach is used because the objects are drawn * into windows and drawing simply means compositing the windows. * * The offsets constrain the selected object to stay within the dimensions * of the view. */ - moveObject:(NXEvent *)event { BOOL tracking, dirtyFlag = NO; int old_mask; float knobsize; NXSize llOffset, urOffset; NXPoint pt, pt_last, pt_old, delta; NXRect rect_now, rect_start, rect_last; knobsize = -[self controlPointSize]; [graphicId getBounds:&rect_start]; NXInsetRect(&rect_start, knobsize, knobsize); rect_now = rect_last = rect_start; pt_last = pt_old = event->location; [self convertPoint:&pt_last fromView:nil]; /* Calculate where the mouse point falls relative to the object. */ llOffset.width = pt_last.x - rect_start.origin.x; llOffset.height = pt_last.y - rect_start.origin.y; urOffset.width = rect_start.origin.x + rect_start.size.width - pt_last.x; urOffset.height = rect_start.origin.y + rect_start.size.height - pt_last.y; /* Return nil if the the mouse was not dragged. */ old_mask = [window addToEventMask:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; if (event->type != NX_MOUSEUP) { tracking = YES; while (tracking) { pt = pt_old = event->location; [self convertPoint:&pt fromView:nil]; [self constrainPoint:&pt withOffset:&llOffset :&urOffset]; [self constrainPoint:&pt_last withOffset:&llOffset :&urOffset]; delta.x = pt.x - pt_last.x; delta.y = pt.y - pt_last.y; if (delta.x || delta.y) { dirtyFlag = YES; NXOffsetRect(&rect_now, delta.x, delta.y); [self constrainRect:&rect_now]; /* * Composite the old image into the window and then * translate the user space and draw the graphicId object. */ compositeBuffer([bufferId gState], &rect_last, &rect_last.origin, NX_COPY); PSgsave(); PStranslate(rect_now.origin.x - rect_start.origin.x, rect_now.origin.y - rect_start.origin.y); [self drawObject:graphicId forRect:&rect_start withFlags:MOVEFLAG]; [self drawControl:graphicId forRect:&rect_start withFlags:NOFLAGS]; PSgrestore(); [window flushWindow]; NXPing(); rect_last = rect_now; pt_last = pt; } event = [NXApp getNextEvent:NX_MOUSEUPMASK| NX_MOUSEDRAGGEDMASK]; tracking = (event->type != NX_MOUSEUP); } if (dirtyFlag) { delta.x = rect_now.origin.x - rect_start.origin.x; delta.y = rect_now.origin.y - rect_start.origin.y; [graphicId moveAll:&delta]; /* * The view has already been focused and we know what * has to be redrawn so call drawSelf:: instead of display */ NXUnionRect(&rect_now, &rect_start); [self drawSelf:&rect_start :1]; [window flushWindow]; NXPing(); } } [window setEventMask:old_mask]; return self; } /* Check to see whether a control point has been hit. */ - checkControl:(const NXPoint *) p :(int *) pt_num { NXRect hitRect; NXSetRect(&hitRect, p->x - HITSETTING/2, p->y - HITSETTING/2, HITSETTING, HITSETTING); return [graphicId hitControl:&hitRect :pt_num forSize:[self controlPointSize]]; } /* * Check to see whether the epsf object has been hit. Return it if yes. */ - checkObject:(const NXPoint *) p { UPath *hitPoint; /* Bounding Box */ hitPoint = [NXApp hitPoint]; hitPoint->pts[0] = floor(p->x - HITSETTING/2); hitPoint->pts[1] = floor(p->y - HITSETTING/2); hitPoint->pts[2] = ceil(p->x + HITSETTING/2); hitPoint->pts[3] = ceil(p->y + HITSETTING/2); /* Moveto */ hitPoint->pts[4] = p->x - HITSETTING/2; hitPoint->pts[5] = p->y - HITSETTING/2; /* Rlineto's */ hitPoint->pts[7] = HITSETTING; hitPoint->pts[8] = HITSETTING; hitPoint->pts[11] = -HITSETTING; return [graphicId hitObject:hitPoint]; } /* * Set the object as selected then draw the control points. */ - selectObject { float knobsize; NXRect drawRect; [graphicId setSelected:YES]; knobsize = -[self controlPointSize]; [graphicId getBounds:&drawRect]; NXInsetRect(&drawRect, knobsize, knobsize); [self drawControl:graphicId forRect:&drawRect withFlags:NOFLAGS]; [window flushWindow]; return self; } /* * Redraw thecontrol points for the occupied portion. The control points * are drawn in this view since they can be drawn quickly. */ - deselectObject { float knobsize; NXRect drawRect; [graphicId setSelected:NO]; knobsize = -[self controlPointSize]; [graphicId getBounds:&drawRect]; NXInsetRect(&drawRect, knobsize, knobsize); [self drawControl:graphicId forRect:&drawRect withFlags:CLEARFLAG]; [window flushWindow]; return self; } /* * Test for a mouse down hit on either the control points or the object. */ - testObject:(NXEvent *)event { int pt_num; NXPoint p; p = event->location; [self convertPoint:&p fromView:nil]; [self lockFocus]; if ([graphicId selected]) { if ([self checkControl:&p :&pt_num]) [self redrawObject:pt_num]; else if ([self checkObject:&p]) [self moveObject:event]; else [self deselectObject]; } else if ([self checkObject:&p]) [self selectObject]; [self unlockFocus]; return self; } /* * Pass the file name to the factory TIFF or EPS object to create a new * instance. If successful then free the previous epsf object. */ - importFile:(const char *) file { id tempId; char *end; NXStream *stream; if (file) { end = strrchr(file, '.'); if (end) { stream = NXMapFile(file, NX_READONLY); if (stream) { if (strncmp(end, ".tiff", 5) == 0 || strncmp(end, ".ps", 3) == 0 || strncmp(end, ".eps", 4) == 0) { tempId = [[GraphicImport alloc] initFromStream:stream]; if (tempId) { [tempId setFilename:file]; [self delete:self]; [graphicId free]; graphicId = tempId; [NXApp setOperation:OP_IMPORT]; return self; } NXCloseMemory(stream, NX_FREEBUFFER); } else Notify("Import Error", "Unable to open file."); } } else Notify("Import Error", "Unable to import file. Unrecognized file type."); } return nil; } /* * Place the epsId with its upper left corner at p; */ - placeObjectAt:(const NXPoint *) p { float knobsize; NXPoint pt; NXRect rect_draw; if (graphicId) { pt = *p; [graphicId getBounds:&rect_draw]; pt.y = pt.y - rect_draw.size.height; [graphicId setOrigin:&pt]; knobsize = -[self controlPointSize]; [graphicId getBounds:&rect_draw]; NXInsetRect(&rect_draw, knobsize, knobsize); [self display:&rect_draw :1]; } return self; } /* * Begins the setup for placing an imported file into the document. * The object for the file is created and then waits for the mouse * down to begin placement and sizing. This method first gets the * object and then messages the redrawObject method to draw * the subsequent sizing rectangles. */ - importObject:(NXEvent *)event { float knobsize; NXPoint p; NXRect rect_draw; if (graphicId) { p = event->location; [self convertPoint:&p fromView:nil]; NXSetRect(&rect_draw, p.x, p.y-SIZE_MIN, SIZE_MIN, SIZE_MIN); [graphicId setBounds:&rect_draw]; knobsize = -[self controlPointSize]; [graphicId getBounds:&rect_draw]; NXInsetRect(&rect_draw, knobsize, knobsize); [self lockFocus]; [self drawObject:graphicId forRect:&rect_draw withFlags:REDRAWFLAG]; [self drawControl:graphicId forRect:&rect_draw withFlags:NOFLAGS]; [self redrawObject:8]; if ([graphicId error]) { [graphicId getBounds:&rect_draw]; NXInsetRect(&rect_draw, knobsize, knobsize); [graphicId free]; graphicId = NULL; [self display:&rect_draw :1]; } else [self selectObject]; [self unlockFocus]; } return self; } /* * Depending on the current operation, check for selection, zoom or * import a file. */ - mouseDown:(NXEvent *)event { int operation; operation = [NXApp operation]; switch (operation) { case OP_SELECT: [self testObject:event]; break; case OP_IMPORT: [self importObject:event]; [NXApp setOperation:OP_SELECT]; break; } return self; } /* * Deletes the epsf object if selected. */ - keyDown:(NXEvent *) event { if ([NXApp operation] == OP_SELECT && event->data.key.charSet == NX_ASCIISET && event->data.key.charCode == NX_DELETE) return [self delete:self]; else return nil; } /* * Draw the control points using the user path buffer to hold * the data for the xyshow. */ - drawControl:object forRect:(NXRect *)r withFlags:(int)flags { float knobsize; NXPoint lastpoint; NXRect rect; UPath *upathBuffer; if (r) rect = *r; else [self getVisibleRect:&rect]; if (flags & CLEARFLAG) compositeBuffer([bufferId gState], &rect, &rect.origin, NX_COPY); if ([object selected]) { lastpoint.x = 0; lastpoint.y = 0; upathBuffer = [NXApp upathBuffer]; upathBuffer->num_ops = 0; upathBuffer->num_pts = 0; knobsize = [self controlPointSize]; NXInsetRect(&rect, -knobsize/2, -knobsize/2); [object putControlPoints:upathBuffer forRect:&rect :&lastpoint]; upathBuffer->ops[upathBuffer->num_ops] = 0; upathBuffer->pts[upathBuffer->num_pts] = 0; upathBuffer->pts[upathBuffer->num_pts + 1] = 0; if (upathBuffer->num_ops > 0) { PSWSetControlPoints(ControlFont, knobsize, NX_BLACK, 0.15); PSWDrawControlPoints(upathBuffer->pts[0], upathBuffer->pts[1], &upathBuffer->pts[2], upathBuffer->num_pts, upathBuffer->ops); } } return self; } - drawObject:object forRect:(NXRect *)r withFlags:(int) flags { NXRect rect; if (r) rect = *r; else [self getVisibleRect:&rect]; [object drawObject:&rect withFlags:flags inView:self]; return self; } /* * Fill in the background of the rectangle and then draw the epsf object. * If NX_DRAWING, then draw into the buffer and composite it into * the window. */ - drawSelf:(NXRect *)r :(int) count { if (NXDrawingStatus == NX_DRAWING) { [bufferId lockFocus]; PSsetgray(NX_WHITE); NXRectFill(r); } [self drawObject:graphicId forRect:r withFlags:REFRESHFLAG]; if (NXDrawingStatus == NX_DRAWING && !imageId) { [bufferId unlockFocus]; compositeBuffer([bufferId gState], r, &r->origin, NX_COPY); [self drawControl:graphicId forRect:r withFlags:NOFLAGS]; } return self; } /* * This method is only overridden to eliminate during a copy * the rectclip and gsave/grestore pairing that results from * a lockFocus. These are usually harmless operations but * they interfere with trying to produce Illustrator format files. */ - display:(NXRect *)r :(int) count :(BOOL)flag { if (NXDrawingStatus == NX_COPYING) { [self drawSelf:r :count]; DPSFlushContext(DPSGetCurrentContext()); } else [super display:r :count :flag]; return self; } - (BOOL)acceptsFirstResponder { return YES; } /* * Used when printing. Returns the global resources used in the document. */ - addResources:(Resource *) resourceDoc { NXAtom string; if (NXDrawingStatus == NX_COPYING) { string = NXUniqueString(EpsfProcSet); if (!resourceDoc[RES_PROCSETS].states[RES_PRESENT]) resourceDoc[RES_PROCSETS].states[RES_PRESENT] = [List new]; [resourceDoc[RES_PROCSETS].states[RES_PRESENT] addObjectIfAbsent:(id) string]; if (!resourceDoc[RES_PROCSETS].states[RES_SUPPLIED]) resourceDoc[RES_PROCSETS].states[RES_SUPPLIED] = [List new]; [resourceDoc[RES_PROCSETS].states[RES_SUPPLIED] addObjectIfAbsent:(id) string]; } return self; } /* * Print the %%DocumentResource comments. A list of the resources is * accumulated from the epsf files (only one in this case). * The list is then written to the current context. */ - beginResourceComments:(const NXRect *) bbox { int i, j; Resource resourceDoc[RES_NUMTYPES]; bzero(&resourceDoc, sizeof(resourceDoc)); [self addResources:resourceDoc]; [graphicId addResources:resourceDoc for:(NXRect *) bbox]; for (i = 0; i < RES_NUMTYPES; i++) { for (j = 0; j < RES_NUMSTATES; j++) { if (resourceDoc[i].states[j]) { WriteEpsfResource(resourceDoc[i].states[j], i, j); [resourceDoc[i].states[j] free]; } } } return self; } /* * Write out the necessary information. Overridden to include * the fonts from the EPSF files. */ - beginPrologueBBox:(const NXRect *)boundingBox creationDate:(const char *)dateCreated createdBy:(const char *)anApplication fonts:(const char *)fontNames forWhom:(const char *)user pages:(int)numPages title:(const char *)aTitle { time_t clock; DPSContext ctxt; ctxt = DPSGetCurrentContext(); if (!boundingBox) boundingBox = &bounds; if (!dateCreated) { clock = time(0); dateCreated = ctime(&clock); } if (!anApplication) anApplication = [NXApp appName]; if (!user) user = (char *) getlogin(); if (numPages <= 0) numPages = 1; if (!aTitle) aTitle = [[window delegate] filename]; DPSPrintf(ctxt, "%%!PS-Adobe-2.0 EPSF-1.2\n"); DPSPrintf(ctxt, "%%%%Creator: %s\n", anApplication); DPSPrintf(ctxt, "%%%%For: %s\n", user); DPSPrintf(ctxt, "%%%%Title: %s\n", aTitle); DPSPrintf(ctxt, "%%%%CreationDate: %s", dateCreated); DPSPrintf(ctxt, "%%%%BoundingBox: %d %d %d %d\n", (int) floor(boundingBox->origin.x), (int) floor(boundingBox->origin.y), (int) ceil(boundingBox->origin.x + boundingBox->size.width), (int) ceil(boundingBox->origin.y + boundingBox->size.height)); if (NXDrawingStatus == NX_COPYING) DPSPrintf(ctxt, "%%AI3_TemplateBox: %d %d %d %d\n", 306, 396, 306, 396); if (NXDrawingStatus != NX_COPYING) DPSPrintf(ctxt, "%%%%Pages: %d\n", numPages); [self beginResourceComments:boundingBox]; return self; } /* * Includes the abbreviated Illustrator proc set so that * the eps files produced through Save To will print on their * own. Also includes the preview data as a comment when * specified. */ - endHeaderComments { DPSContext ctxt; if (NXDrawingStatus == NX_COPYING) { ctxt = DPSGetCurrentContext(); DPSPrintf(ctxt, "%%%%EndComments\n\n"); DPSPrintf(ctxt, "%%%%BeginProcSet: EPSF_Illustrator_abbrev 0 0\n"); WriteEpsfProcSetDef (); DPSPrintf(ctxt, "%%%%EndProcSet\n\n"); if (imageId && [[SaveAsPanel new] format] == SAVE_EPSPREVIEW) WriteEpsfPreview(imageId); } else [super endHeaderComments]; return self; } /* * If saving in illustrator, override the prologue comment. */ - endPrologue { DPSContext ctxt; if (NXDrawingStatus == NX_COPYING) { ctxt = DPSGetCurrentContext(); DPSPrintf(ctxt, "%%%%EndProlog\n\n"); } else [super endPrologue]; return self; } /* Initialize the Illustrator abbreviated proc set. */ - beginSetup { DPSContext ctxt; if (NXDrawingStatus == NX_COPYING) { ctxt = DPSGetCurrentContext(); DPSPrintf(ctxt, "%%%%BeginSetup\n"); WriteEpsfProcSetInit(); } else [super beginSetup]; return self; } - endSetup { DPSContext ctxt; if (NXDrawingStatus == NX_COPYING) { ctxt = DPSGetCurrentContext(); DPSPrintf(ctxt, "%%%%EndSetup\n"); } else [super endSetup]; return self; } /* Terminate the Illustrator abbreviated proc set. */ - beginTrailer { DPSContext ctxt; if (NXDrawingStatus == NX_COPYING) { ctxt = DPSGetCurrentContext(); DPSPrintf(ctxt, "%%%%Trailer\n"); WriteEpsfProcSetTerm(); } else [super beginTrailer]; return self; } - endTrailer { if (NXDrawingStatus != NX_COPYING) [super endTrailer]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.