This is TGIF.m in view mode; [Download] [Up]
#import "TGIF.h" #import "ListCell.h" #import "ListMatrix.h" #import "NXBitmapGraphicRep.h" #import "PolyInspector.h" #import "TGIFCell.h" #import "miscutil.h" #import <appkit/Application.h> #import <appkit/Matrix.h> #import <appkit/NXCursor.h> #import <appkit/OpenPanel.h> #import <appkit/SavePanel.h> #import <appkit/ScrollView.h> #import <appkit/Window.h> #import <appkit/color.h> #import <appkit/graphics.h> #import <appkit/nextstd.h> #import <stdio.h> #import <streams/streams.h> #import <sys/param.h> // import command cell objects #import "CmdBgcolor.h" #import "CmdBgnpoly.h" #import "CmdCircle.h" #import "CmdComment.h" #import "CmdDraw.h" #import "CmdEndpoly.h" #import "CmdFgcolor.h" #import "CmdFps.h" #import "CmdHold.h" #import "CmdMove.h" #import "CmdNewframe.h" #import "CmdVertex.h" #import "AbsPoly.h" NXBitmapGraphicRep *theBitmap=nil; @implementation TGIF id backup; // for undo id openPanel, savePanel; id pbList; // for a "pasteboard" of cells. BOOL getOpenPath(char *buf, char const *type1, char const *type2) { char const *fileTypes[3] = {0,0,0}; if (!openPanel) openPanel = [OpenPanel new]; [openPanel allowMultipleFiles:NO]; if (type1 && *type1) fileTypes[0] = type1; if (type2 && *type2) fileTypes[1] = type2; [NXApp setAutoupdate:NO]; if ([openPanel runModalForDirectory:(const char*)buf file:"" types:fileTypes]) { strcpy(buf,[openPanel filename]); [NXApp setAutoupdate:YES]; return YES; } else { [NXApp setAutoupdate:YES]; return NO; } } BOOL getSavePath(char *returnBuf, char *dir, char *name, char const *theType) { if (!savePanel) { savePanel = [SavePanel new]; [savePanel setTitle:"GraphicsWrap Save"]; } if (theType && *theType) [savePanel setRequiredFileType:theType]; [NXApp setAutoupdate:NO]; if ([savePanel runModalForDirectory:dir file:name]) { strcpy(returnBuf,[savePanel filename]); [NXApp setAutoupdate:YES]; return YES; } else { [NXApp setAutoupdate:YES]; return NO; } } void parsePath(char *path, char *dir, char *name) { char *c1, *c2; int dirlen, namelen; c1 = strrchr(path, '.'); c2 = strrchr(path, '/'); dirlen = (c2) ? c2-path+1 : 0; namelen = ((c1) ? c1-path : strlen(path)) -dirlen; strncpy(dir,path,dirlen); dir[dirlen] = '\0'; strncpy(name, path+dirlen, namelen); name[namelen] = '\0'; } void getPath(char *path, char *dir, char *name, char *ext) /* construct a path given a file name, directory, and type */ { strcpy(path,(dir)?dir:NXHomeDirectory()); if (name) { strcat(path,name); if (strlen(ext) && (ext[0] != '.')) strcat(path,"."); strcat(path,ext); } } - displayMatrix:aMatrix { [aMatrix sizeToCells]; [aMatrix display]; return self; } - initMatrix { NXRect aRect, bRect; NXSize cellSpacing={0.0,0.0}, cellSize; [tgif_view getFrame:&aRect]; [ScrollView getContentSize:&(bRect.size) forFrameSize:&(aRect.size) horizScroller:YES vertScroller:YES borderType:NX_BEZEL]; tgif_matrix = [[ListMatrix alloc] initFrame:&bRect mode:NX_LISTMODE cellClass:[TGIFCell class] numRows:0 numCols:1]; [tgif_matrix setIntercell:&cellSpacing]; [tgif_matrix allowEmptySel:YES]; [tgif_matrix setControlDrag:YES]; [tgif_matrix getCellSize:&cellSize]; cellSize.width = NX_WIDTH(&bRect); [tgif_matrix setCellSize:&cellSize]; [tgif_matrix sizeToCells]; [tgif_matrix setAutosizeCells:YES]; [tgif_matrix setAutoscroll:YES]; [tgif_view setDocView:tgif_matrix]; [[tgif_matrix superview] setAutoresizeSubviews:YES]; [tgif_matrix setAutosizing:NX_WIDTHSIZABLE]; [tgif_matrix setBackgroundGray:NX_LTGRAY]; [tgif_matrix setCellBackgroundGray:NX_LTGRAY]; [tgif_view setBackgroundGray:NX_LTGRAY]; [tgif_view setDocCursor:NXArrow]; [tgif_matrix setTarget:self]; [tgif_matrix setAction:@selector(tgif_click:)]; [self displayMatrix:tgif_matrix]; return self; } - initWithBitmap:abp andView:av; { char title[100]; [super init]; [NXApp loadNibSection:"TGIF.nib" owner:self withNames:NO]; theBitmap=abp; bitmap_view=av; poly_insp=[[PolyInspector alloc] init]; NX_MALLOC(filePath,char,MAXPATHLEN+1); NX_MALLOC(fileName,char,MAXPATHLEN+1); NX_MALLOC(fileDir,char,MAXPATHLEN+1); sprintf(title,"UNTITLED.tgif"); [tgif_window setTitleAsFilename:(const char*)title]; NXPing(); sprintf(filePath,"~/"); sprintf(fileName,title); sprintf(fileDir,"~/"); [self initMatrix]; return self; } - perform:sender { id cellList=[tgif_matrix cellListIncludeAll:NO]; int i, max=[cellList count]; if(!max)cellList=[tgif_matrix cellListIncludeAll:YES]; for(i=0;i<max;i++){ [[cellList objectAt:i] doCmd]; [bitmap_view display]; } return self; } - tgif_click:sender { id tList=[tgif_matrix cellListIncludeAll:NO]; if(([tList count] == 1) && [[tList objectAt:0] isMemberOf:[AbsPoly class]]){ [poly_insp inspect:[tList objectAt:0]]; [[poly_insp window] makeKeyAndOrderFront:self]; } else [[poly_insp window] orderOut:self]; return self; } - saveToFile { int i; id cmdList; NXStream *theStream; if (!getSavePath(filePath,fileDir,fileName,"tgif")) return self; parsePath(filePath, fileDir, fileName); theStream=NXOpenMemory(NULL, 0, NX_WRITEONLY); cmdList=[tgif_matrix cellListIncludeAll:YES]; for(i=0;i<[cmdList count];i++) NXPrintf(theStream, "%s", [[cmdList objectAt:i] emitCmd]); NXFlush(theStream); NXSaveToFile(theStream, filePath); NXClose(theStream); return self; } - addRowTo:newCell { int rc, cc; [tgif_matrix getNumRows:&rc numCols:&cc]; [tgif_matrix addRow]; [tgif_matrix putCell:newCell at:rc :0]; return self; } id curPoly; BOOL polyMode; - addActiveCmd:(char *)cmd { long arg1=-1, arg2=-1, arg3=-1; int cc=0, argnum=0; char *c[3]; c[0]=c[1]=c[2]=(char *)nil; while(cmd[cc]!='\0'){ if(cmd[cc]==' '){ cmd[cc]='\0'; c[argnum++]=&cmd[++cc]; } else cc++; } if(c[0]) arg1=atol(c[0]); if(c[1]) arg2=atol(c[1]); if(c[2]) arg3=atol(c[2]); if (polyMode){ // check for "endpoly" if(!strcmp(cmd, "endpoly") || !strcmp(cmd,"ep")){ [curPoly addCommand:[[CmdEndpoly alloc] initCmd]]; polyMode=FALSE; } //check for "vertex" else if(!strcmp(cmd, "vertex") || !strcmp(cmd,"v")) [curPoly addCommand:[[CmdVertex alloc] initCmd:arg1 :arg2]]; else fprintf(stderr, "Illegal token in PolyGon definition:%s %d %d %d\n", cmd, arg1, arg2, arg3); } else { // check for "move" if(!strcmp(cmd, "move") || !strcmp(cmd,"m")) [self addRowTo:[[CmdMove alloc] initCmd:arg1 :arg2]]; // check for "draw" else if(!strcmp(cmd, "draw") || !strcmp(cmd,"d")) [self addRowTo:[[CmdDraw alloc] initCmd:arg1 :arg2]]; // check for "circle" else if(!strcmp(cmd, "circle") || !strcmp(cmd,"c")) [self addRowTo:[[CmdCircle alloc] initCmd:arg1]]; //check for "fgcolor" else if(!strcmp(cmd, "fgcolor") || !strcmp(cmd,"fg")) [self addRowTo:[[CmdFgcolor alloc] initCmd:arg1 :arg2 :arg3]]; // check for "bgcolor" else if(!strcmp(cmd, "bgcolor") || !strcmp(cmd,"bg")) [self addRowTo:[[CmdBgcolor alloc] initCmd:arg1 :arg2 :arg3]]; // check for "bgnpoly" else if(!strcmp(cmd, "bgnpoly") || !strcmp(cmd,"bp")){ curPoly=[[AbsPoly alloc] init]; [self addRowTo:curPoly]; [curPoly addCommand:[[CmdBgnpoly alloc] initCmd]]; polyMode=TRUE; } // check for "newframe" else if(!strcmp(cmd, "newframe") || !strcmp(cmd,"n")) [self addRowTo:[[CmdNewframe alloc] initCmd]]; // check for "fps" else if(!strcmp(cmd, "fps")) [self addRowTo:[[CmdFps alloc] initCmd:arg1]]; // check for "hold" else if(!strcmp(cmd, "hold")) [self addRowTo:[[CmdHold alloc] initCmd:arg1]]; else fprintf(stderr, "Bad Token (ignore -1): %s %d %d %d\n", cmd, arg1, arg2, arg3); } return self; } - openFile { char path[MAXPATHLEN+1], cmd[2000]; char c; int rc, cc; NXStream *theStream; if (getOpenPath(path,"tgif",fileDir)) { [tgif_matrix getNumRows:&rc numCols:&cc]; for(cc=0;cc<rc;cc++) [tgif_matrix removeRowAt:cc andFree:YES]; theStream=NXMapFile(path, NX_READONLY); cc=0; while((c=NXGetc(theStream))!=EOF){ cmd[cc]=c; if(c=='\n'){ cmd[cc]='\0'; cc=0; if(cmd[0]=='#') { // this is a comment line [self addRowTo:[[CmdComment alloc] initComment:cmd]]; } else // this is really a command, process it as one [self addActiveCmd:cmd]; } else cc++; } NXClose(theStream); } [self displayMatrix:tgif_matrix]; strcpy(filePath, path); parsePath(filePath, fileDir, fileName); [tgif_window setTitleAsFilename:(const char*)filePath]; return self; } - newFile { char title[100]; int i, rc, cc; [tgif_matrix getNumRows:&rc numCols:&cc]; for(i=0;i<rc;i++) [tgif_matrix removeRowAt:0 andFree:YES]; [self displayMatrix:tgif_matrix]; sprintf(title,"UNTITLED.tgif"); [tgif_window setTitleAsFilename:(const char*)title]; NXPing(); sprintf(filePath,"~/"); sprintf(fileName,title); sprintf(fileDir,"~/"); return self; } - cmdMove:(int)x :(int)y { [self addRowTo:[[CmdMove alloc] initCmd:x :y]]; [self displayMatrix:tgif_matrix]; return self; } - cmdDraw:(int)x :(int)y { [self addRowTo:[[CmdDraw alloc] initCmd:x :y]]; [self displayMatrix:tgif_matrix]; return self; } -cmdNewFrame { [self addRowTo:[[CmdNewframe alloc] initCmd]]; [self displayMatrix:tgif_matrix]; return self; } - cmdForeColor:(NXColor)aColor { [self addRowTo:[[CmdFgcolor alloc] initCmdColor:aColor]]; [self displayMatrix:tgif_matrix]; return self; } - cmdBackColor:(NXColor)aColor { [self addRowTo:[[CmdBgcolor alloc] initCmdColor:aColor]]; [self displayMatrix:tgif_matrix]; return self; } - cmdComment:(char *)comment { char *tmp; tmp=(char *) malloc((strlen(comment)+3)*sizeof(char)); sprintf(tmp, "#%s\n", comment); [self addRowTo:[[CmdComment alloc] initComment:tmp]]; free(tmp); return self; } - cmdNewPoly { // create new polygon id aPoly=[[AbsPoly alloc] init]; // add polygon to our matrix [self addRowTo:aPoly]; [self displayMatrix:tgif_matrix]; // return polygon to caller for vertex addition return aPoly; } // through first responder - delete:sender { id cellList; int i, rc, cc; cellList=[tgif_matrix cellListIncludeAll:NO]; for(i=0;i<[cellList count];i++){ [tgif_matrix getRow:&rc andCol:&cc ofCell:[cellList objectAt:i]]; [tgif_matrix removeRowAt:rc andFree:NO]; } [cellList freeObjects]; [self displayMatrix:tgif_matrix]; return self; } - cut:sender { int i, rc, cc; if(pbList) [pbList free]; else pbList=[[List alloc] init]; pbList=[tgif_matrix cellListIncludeAll:NO]; for(i=0;i<[pbList count];i++){ [tgif_matrix getRow:&rc andCol:&cc ofCell:[[pbList objectAt:i] copy]]; [tgif_matrix removeRowAt:rc andFree:YES]; } [self displayMatrix:tgif_matrix]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.