This is MMText.m in view mode; [Download] [Up]
/* written by Joe Freeman from Next Computer Inc * Version 2 * As with all my code, use at your own risk. * * Notes: * 1) This objects is very similar to the text object used by Edit * and the one used by Mail, supporting both graphics and attach * * Mail supports embeded graphics in a different format from Edit * with Edit adding height and width parameters to the RTF. * * Mail supports attachments using the "attachment" command * that is not supported in edit in Edit. * * This program will not interchange attachments with Mail * because using the "attachment" command in this objec will let * attachments be copied out of this object and into mail but then * no attachments can be pasted or loaded back in from an rtf * stream. The use of "attach" means this object works fine but * all attachment interchange with mail is lost. * * 2) This object makes all graphics (tiff and eps) embeded graphics * similar to edit. * * It also supports other files as attachments, storing just the * pointers to the files * * * MMText.[hm] * Multi media text object! * * 1) Handles embeded graphics in rtf * 2) Saves and loads from rtfd files * 3) Suports "drag and drop" of tiff and eps files * 4) Supports copy and paste of rtf with embedded graphics * 5) Has methods for open: and saveAs: to simplify programming * 6) Handles attached documents via pointers * */ /* Generated by Interface Builder */ #import "MMText.h" #import "MMGraphicCell.h" #import "MMFileCell.h" #import <appkit/Application.h> /* ask for app speaker port */ #import <appkit/Cell.h> /* where we put our view */ #import <appkit/NXImage.h> /* to load the cell */ #import <appkit/Listener.h> #import <appkit/OpenPanel.h> #import <appkit/nextstd.h> #import <appkit/Pasteboard.h> #import <appkit/publicWraps.h> /* NXConvertWinNumToGlobal ... */ #import <appkit/SavePanel.h> #import <appkit/Speaker.h> /* set send port */ #import <streams/streams.h> #import <stdio.h> @implementation MMText:Text static char rcsstring[] = "@(#)Object:MMText.m Developer:Joe Freeman Version:2 July, 1991"; + initialize { [super initialize]; [self registerDirective:"NeXTGraphic" forClass: [MMGraphicCell class]]; [self registerDirective:"attach" forClass: [MMFileCell class]]; [self registerDirective:"attachment" forClass: [MMFileCell class]]; return self; } - initFrame:(NXRect *)r { self = [super initFrame:r]; [self notifyAncestorWhenFrameChanged:YES]; [self setMonoFont:NO]; [self setVertResizable:YES]; [self setHorizResizable:NO]; [self setSel:0:0]; [self setOpaque:YES]; copyGraphics = YES; copyAttachments = NO; { NXSize aSize = {1.0E38,1.0E38}; [self setMinSize:&r->size]; [self setMaxSize:&aSize]; } return self; } - free { /* un register this window */ unsigned int windowNum; id speaker = [NXApp appSpeaker]; if (privateListener) { [speaker setSendPort: NXPortFromName(NX_WORKSPACEREQUEST, NULL)]; NXConvertWinNumToGlobal([window windowNum], &windowNum); [speaker unregisterWindow:windowNum]; [privateListener free]; } return self; } /*================================================== * * *==================================================*/ - (int)iconEntered:(int)windowNum at:(double)x :(double)y iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY iconWidth:(double)iconWidth iconHeight:(double)iconHeight pathList:(char *)pathList /* * Called whenever an icon is dragged from the Workspace over the document * window. At this point, all that is done is to salt away the list of files * represented by the icon. All the real work is done in iconReleasedAt::ok:. */ { #ifdef DEBUG fprintf(stderr,"icon Entered\n"); #endif DEBUG if (!iconPathList || strcmp(iconPathList, pathList)) { if (iconPathList) NX_FREE(iconPathList); NX_MALLOC(iconPathList,char, strlen(pathList)+1); //iconPathList = NXCopyStringBufferFromZone(pathList, [self zone]); strcpy(iconPathList, pathList); } return 0; } - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag { /* we are blocked by the workspace if we try and get the tiff for a * non graphical file so just return ok and do the stuff after ws is ready */ if (![self isEditable]) { *flag = NO; } else { *flag = YES; [self perform:@selector(delayIconReleasedAt:) with:self afterDelay:5 cancelPrevious:YES]; } return 0; } - delayIconReleasedAt:sender /* * This is where the real work is done. * look for eps and tiff files and pass them off to the MMGraphicCell * all others should be passed to MMFileCell * Insert each one as we find it * */ { /* these are vars that used to come in from iconReleasedAt::ok: */ int dummy,*flag; NXPoint p; char *file, *tab, *extension; id newCell; int foundOne ; flag = &dummy; /* another dummy statement */ foundOne = NO; /* should make sure it is in this text object */ [window convertScreenToBase:&p]; [self convertPoint:&p fromView:nil]; #ifdef DEBUG fprintf(stderr,"user dragged in files %s\n",iconPathList); #endif DEBUG file = iconPathList; while (file) { tab = strchr(file, '\t'); if (tab) *tab = '\0'; extension = strrchr(file, '.'); if (extension && ( !strcmp(extension, ".ps") || !strcmp(extension, ".eps") || !strcmp(extension,".tiff") || !strcmp(extension,".tif") )) { newCell = [[MMGraphicCell alloc] initFromFile: file copy:copyGraphics]; [self replaceSelWithCell:newCell]; foundOne = YES; } else { newCell = [[MMFileCell alloc] initFromFile: file copy:copyAttachments]; [self replaceSelWithCell:newCell]; foundOne = YES; } file = tab ? ++tab : NULL; } *flag = foundOne; return 0; } /*================================================== * * *==================================================*/ - write:(NXTypedStream *)stream { [super write:stream]; NXWriteTypes(stream,"**ii", &iconPathList,&rtfdName,©Graphics,©Attachments); NXWriteObjectReference(stream,privateListener); return self; } - read:(NXTypedStream *)stream { [super read:stream]; NXReadTypes(stream,"**ii", &iconPathList,&rtfdName,©Graphics,©Attachments); privateListener = NXReadObject(stream); return self; } /*================================================== * * *==================================================*/ - becomeFirstResponder { unsigned int windowNum; id speaker; if (!privateListener ) { #ifdef DEBUG fprintf(stderr,"registering private port\n"); #endif DEBUG speaker = [NXApp appSpeaker]; privateListener = [Listener new]; [privateListener setDelegate:self]; [privateListener usePrivatePort]; [privateListener addPort]; NXConvertWinNumToGlobal([window windowNum], &windowNum); [speaker setSendPort: NXPortFromName(NX_WORKSPACEREQUEST, NULL)]; [speaker registerWindow:windowNum toPort:[privateListener listenPort]]; } [super becomeFirstResponder]; return self; } - (const char *)filename { return (const char *)rtfdName; } - (BOOL)copyGraphics { return copyGraphics; } - (BOOL)copyAttachments { return copyAttachments; } - setCopyGraphics:sender { copyGraphics = YES; return self; } - setLinkGraphics:sender { copyGraphics = NO; return self; } - setCopyAttachments:sender { copyAttachments = YES; return self; } - setLinkAttachments:sender { copyAttachments = NO; return self; } /*================================================== * * overriden to set stream instance variable * *==================================================*/ - paste:sender { id pb; char *const *types; char *data; int length; NXStream *stream; id newCell; /* for debugging attachments pb = [Pasteboard new]; types = [pb types]; while (*types ){ fprintf(stderr,"pboard %s\n",*types); [pb readType:*types data:&data length:&length]; types++; } return self; */ if (![super paste:sender]){ /* was no ascii or rtf sitting there so lets look for eps and tiff */ pb = [Pasteboard new]; types = [pb types]; while (*types ){ if ( !strcmp(*types, NXPostScriptPboardType) || !strcmp(*types, NXTIFFPboardType)) { [pb readType:*types data:&data length:&length]; stream = NXOpenMemory(data, length, NX_READONLY); newCell = [[MMGraphicCell alloc] initFromStream: stream copy:YES]; NXCloseMemory(stream, NX_SAVEBUFFER); [self replaceSelWithCell:newCell]; /* this has to be here otherwise no file name so can't * paste rtf... need pointers for graphics */ [self save:self]; break; } types++; } } return self; } /*================================================== * * This is to support save in palette * we want to test graphics being written to streams * *==================================================*/ - openFileName:(char *)aFile { NXStream *aStream; char fileName[MAXPATHLEN+1]; fprintf(stderr,"opening file %s\n",aFile); if (!rtfdName || strcmp(aFile,rtfdName)){ // NULL or current file if (rtfdName) free(rtfdName); rtfdName = malloc((strlen(aFile)+1) * sizeof(char)); strcpy(rtfdName,aFile); } sprintf(fileName,"%s/TXT.rtf",aFile); aStream = NXMapFile(fileName, NX_READONLY); [self readRichText:aStream]; //NXCloseMemory(aStream, NX_FREEBUFFER); NXClose(aStream); return self; } - open:sender { id openPanel = [OpenPanel new]; const char * const fileTypes[2] = {"rtfd",NULL}; const char * const * filenames; char fullname[MAXPATHLEN+1]; [openPanel allowMultipleFiles:YES]; [openPanel setDelegate:self]; if ([openPanel runModalForTypes:fileTypes]){ filenames = [openPanel filenames]; while (filenames && *filenames){ strcpy(fullname,[openPanel directory]); strcat(fullname,"/"); strcat(fullname,*filenames); [self openFileName:fullname]; filenames++; } } return self; } - saveFileName:(char *)aFile { NXStream *aStream; char fileName[MAXPATHLEN+1]; if (!rtfdName || strcmp(aFile,rtfdName)){ if (rtfdName) free(rtfdName); rtfdName = malloc((strlen(aFile)+1) * sizeof(char)); strcpy(rtfdName,aFile); } /* make the directory for aFile */ mkdir(aFile, 0755); sprintf(fileName,"%s/TXT.rtf",aFile); aStream = NXOpenMemory(NULL,0, NX_WRITEONLY); [self writeRichText:aStream]; NXSaveToFile(aStream, fileName); NXCloseMemory(aStream, NX_FREEBUFFER); return self; } - saveAs:sender { id savePanel; savePanel = [SavePanel new]; [savePanel setRequiredFileType:"rtfd"]; if ([savePanel runModal]) { [self saveFileName:(char *)[savePanel filename]]; } return self; } - save:sender { if (rtfdName && *rtfdName) [self saveFileName:rtfdName]; else [self saveAs:sender]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.