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.