This is StereoView.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import <appkit/appkit.h> #import "StereoView.h" #import "CubeView.h" #import "StoreData.h" #import "JoyStick.h" #import "stdio.h" #import <libc.h> // for chdir, getwd #define equal(s,w) (strcmp(s,w) == 0) #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) #undef max #define max(a,b) ((a) > (b) ? (a) : (b)) #define ctrl(c) ((c) - 'A' + 1) /* control character mapping */ #define plural(n) ((n) == 1 ? "" : "s") #define thest(n) ((n) == 1 ? "-st" : ((n) == 2 ? "-nd" : ((n) == 3 ? "-rd" \ : "-th"))) #define lastch(s) s[strlen(s)-1] #define no_ret(s) { register int xyz; /* varname is for lint */ \ for (xyz=strlen(s)-1; xyz >= 0 && \ (s[xyz] == '\r' || s[xyz] == '\n'); ) \ s[xyz--] = '\0'; \ } #define first_word(s,w) (strncmp(s,w, strlen(w)) == 0) #define whitespace(c) ((c) == ' ' || (c) == '\t') #define ok_char(c) (isalnum(c) || (c) == '-' || (c) == '_' || (c) == '.') #define quote(c) ((c) == '"' || (c) == '\'') #define onoff(n) (n == 0 ? "OFF" : "ON") /* find tab stops preceding or following a given column position 'a', where * the column position starts counting from 1, NOT 0! * The external integer "tabspacing" must be declared to use this. */ #define prev_tab(a,tb) (((((a-1)/(tb)))*(tb))+1) #define next_tab(a,tb) (((((a-1)/(tb))+1)*(tb))+1) #define EYE 2.9/57.3 #define rad_to_deg (180./M_PI) #define MAXLINE 15000 #define MAXNUM 15000 #define MAXALLOC 200 /* #define TRUE -1 #define FALSE !TRUE */ @implementation StereoView - initFrame:(const NXRect *)frameRect { textDidChange = 0; textNeedsSaving = 0; dataList = [[List alloc] init]; max_path = 200; path = (float *) calloc(2*max_path, sizeof(float)); eyeOffset = EYE; openReq = [OpenPanel new]; saveReq = [SavePanel new]; [super initFrame:frameRect]; bcopy(frameRect,&left_Rect,sizeof(NXRect)); bcopy(frameRect,&right_Rect,sizeof(NXRect)); NXDivideRect(&left_Rect,&right_Rect,NX_WIDTH(frameRect)/2.,2); leftView = [[CubeView alloc] initFrame:&left_Rect]; rightView = [[CubeView alloc] initFrame:&right_Rect]; [self setDrawOrigin:(NXCoord) NX_X(frameRect):(NXCoord) NX_Y(frameRect)]; [self addSubview:leftView]; [self addSubview:rightView]; [self addSubview:joyStick]; [self setAutoresizeSubviews:TRUE]; fileNAME = (char *) calloc(1,256); strcpy(fileNAME,"Untitled"); [self S_Reset:self]; return self; } static char angle_buffer[20]; - setDelegate:anObject { delegate = anObject; return self; } - copy:sender /* code contributed by Dan McCreary of NeXT */ { id pb = [Pasteboard new]; /* global Pasteboard object */ NXStream *st; /* stream to collect data in */ char *data; /* actual data buffer */ int length; /* length of data */ int maxLength; /* (not used here) */ /* To see how to use the pasteboard */ /* see page 10-33 of the SysRefMan */ [self prtCopy]; /* declare that we will supply a */ /* single type of data: PostScript */ [pb declareTypes:&NXPostScriptPboard num:1 owner:self]; /* get a stream which writes to memory */ st = NXOpenMemory( NULL, 0, NX_WRITEONLY ); /* write PostScript code for this view into the stream */ [self copyPSCodeInside:NULL to:st]; /* get actual data buffer from stream */ NXGetMemoryBuffer( st, &data, &length, &maxLength ); /* write PostScript data to pasteboard */ [pb writeType:NXPostScriptPboard data:data length:length]; /* deallocate stream, including its buffer */ NXCloseMemory( st, NX_FREEBUFFER ); [self display]; return self; } -(BOOL)acceptsFirstResponder { /* make this view accept first */ return YES; /* responder so it will understand copy */ } /* -resignFirstResponder { return self; } */ - showError:(char *)errorMessage { NXRunAlertPanel("Error", errorMessage, "OK", NULL, NULL); return self; } - prtCopy { [leftView printPSCode:leftView]; [rightView printPSCode:rightView]; [self display]; return self; } - printPSCode:sender { [leftView printPSCode:leftView]; [rightView printPSCode:rightView]; [self display]; [super printPSCode:self]; [self display]; return self; } - textChanged:sender { textDidChange = 1; return self; } - textEdited:sender { textNeedsSaving = 1; return self; } - plot:sender { NXStream *stream; if (textDidChange == 1) { if (delegate && [delegate respondsTo:@selector(stereoView:providePoints:)]) [delegate stereoView:self providePoints:&stream]; textDidChange = 0; [self readData:(NXStream *)stream]; [leftView getStruct:dataList]; [rightView getStruct:dataList]; [leftView reScale:self]; [rightView reScale:self]; } [self set_Theta:self]; [self set_Phi:self]; [self set_dist:self]; [self display]; return self; } - clear:sender { /* release existing data */ if ([dataList count] != 0) [dataList freeObjects]; [leftView getStruct:dataList]; [rightView getStruct:dataList]; // [leftView clear:self]; // [rightView clear:self]; // [self set_Theta:self]; // [self set_Phi:self]; // [self set_dist:self]; [self S_Reset:self]; [self textChanged:self]; [self display]; return self; } - S_Reset:sender { float floatValue; NXPoint theLocation; [leftView getStruct:dataList]; [rightView getStruct:dataList]; theLocation.x = 0.; theLocation.y = 0.; [joyStick reSet]; [self setPhiTheta:self]; floatValue = 2.0; [showDist setFloatValue:floatValue]; [DistanceSlider setFloatValue:floatValue]; [leftView Reset:leftView]; [rightView Reset:rightView]; [leftView setTheta:-eyeOffset]; [rightView setTheta:+eyeOffset]; [[self window] setTitle:fileNAME]; [self display]; return self; } - setPhiTheta:sender { float phi, theta; phi = 2*[joyStick getYVal:self]*90.; theta = 2*[joyStick getXVal:self]*180.; [showPhi setFloatValue:phi]; [showTheta setFloatValue:theta]; [self set_Theta:self]; [self set_Phi:self]; return self; } - set_Theta:sender { float floatValue; floatValue = [showTheta floatValue]/rad_to_deg; [leftView setTheta:floatValue-eyeOffset]; [rightView setTheta:floatValue+eyeOffset]; [self display]; return self; } - set_Phi:sender { float floatValue; floatValue = [showPhi floatValue]/rad_to_deg; [leftView setPhi:floatValue]; [rightView setPhi:floatValue]; [self display]; return self; } - set_dist:sender { float floatValue; floatValue = [DistanceSlider floatValue]; sprintf(angle_buffer, "%6.2f", floatValue); [showDist setStringValue:angle_buffer]; [leftView setdist:floatValue]; [rightView setdist:floatValue]; [self display]; return self; } - setAxes:(int) intVal { [AxesButton setState:intVal]; [leftView setAxes:intVal]; [rightView setAxes:intVal]; [self display]; return self; } - (int)getAxes { return [AxesButton state]; } - toggle_Axes:sender { [leftView toggleAxes:self]; [rightView toggleAxes:self]; [self display]; return self; } - setCube:(int) intVal { [CubeButton setState:intVal]; [leftView setCube:intVal]; [rightView setCube:intVal]; [self display]; return self; } - (int)getCube { return [CubeButton state]; } - toggle_Cube:sender { [leftView toggleCube:self]; [rightView toggleCube:self]; [self display]; return self; } - setEyeOffset:(float) floatVal { int eye; eyeOffset = floatVal; if (floatVal < 0.)eye = NO; else eye = YES; [EyeButton setState:eye]; [self set_Theta:self]; [self display]; return self; } - (float) getEyeOffset { return eyeOffset; } - toggle_Eyes:sender { [self setEyeOffset: - eyeOffset]; return self; } - sizeTo:(NXCoord)width :(NXCoord)height { NXRect frameRect; [super sizeTo:width :height]; [self getFrame:&frameRect]; bcopy(&frameRect,&left_Rect,sizeof(NXRect)); bcopy(&frameRect,&right_Rect,sizeof(NXRect)); NXDivideRect(&left_Rect,&right_Rect,NX_WIDTH(&frameRect)/2.,2); [leftView setFrame:&left_Rect]; [leftView initialize]; [rightView setFrame:&right_Rect]; [rightView initialize]; [self setDrawOrigin:(NXCoord) NX_X(&frameRect):(NXCoord) NX_Y(&frameRect)]; [self S_Reset:self]; return self; } - windowDidResize:sender { /* This is not received since the controller handles it */ printf("windowDidResize for StereoView\n"); return self; } - windowWillResize:sender toSize:(NXSize *)aSize { /* This is not received since the controller handles it */ printf("windowWillResize for StereoView\n"); return self; } - openData:sender { const char *const ext[5] = {"dat", "data", "3d", "S3d", NULL}; if (textNeedsSaving) [self saveInRequest:sender]; if([openReq runModalForTypes:ext] && (fileNAME = (char *)[openReq filename])) { [self readSData:fileNAME]; } else [self showError:"No file chosen or could not open file"]; return self; } // saveRequest: saves the current window under its default name (found in // the title bar). Note that if the title bar is empty or the default title // is "Untitled" then saveRequest: will put up a save panel, giving the user // a chance to specify a real title. - saveRequest:sender { const char *fileName; const char *const types[2] = {"S3d", NULL}; id curWin = [self window]; if (textNeedsSaving) [self saveInRequest:sender]; [saveReq setRequiredFileType:types[0]]; if (curWin == nil) [self showError:"errorOnSaveRequest"]; else { // Check to see if the current window is titled and the title is not // "Untitled". If so, save the file, else put up a save panel... fileName = [curWin title]; if (strcmp (fileName, "Untitled")) [self saveText:curWin inPath:fileName]; else [self saveInRequest:sender]; } textNeedsSaving = 0; return self; } // saveInRequest: gives the user a chance to save the current window // under a new name. - saveInRequest:sender { const char *fileName; const char *const types[2] = {"S3d", NULL}; id curWin; curWin = [self window]; [saveReq setRequiredFileType:types[0]]; if (curWin == nil) [self showError:"errorOnSaveIn"]; else { // Get a file name from the user; use title of the window as default. if (([saveReq runModalForDirectory:"." file:[curWin title]]) && (fileName = [saveReq filename])) [self saveText:curWin inPath:fileName]; } textNeedsSaving = 0; return self; } // saveWindow writes a window out the archive file whose name is specified // by the second argument. The title of the current window is also set // accordingly. - saveText:(id)win inPath:(const char *)name { FILE *output; char thisline[MAXLINE]; NXStream *stream; BOOL s_gets(); if((output = fopen(name, "w")) == NULL) { sprintf(thisline, "Unable to open file %s", name); [self showError:thisline]; return NULL; } if (delegate && [delegate respondsTo:@selector(stereoView:providePoints:)]) [delegate stereoView:self providePoints:&stream]; s_gets(thisline, MAXLINE, stream); while (!NXAtEOS(stream)) { fprintf(output,"%s",thisline); s_gets(thisline, MAXLINE, stream); } fclose(output); [win setTitle:name]; return self; } // closeRequest closes the current window by simulating a click on the // closebutton. A check should probably be added to give the user the // option of saving the window before closing - closeRequest:sender { if (textNeedsSaving) [self saveInRequest:sender]; if (delegate && [delegate respondsTo:@selector(stereoView:clearText:)]) [delegate stereoView:self clearText:fileNAME]; strcpy(fileNAME,"Untitled"); [self clear:self]; [self S_Reset:self]; textNeedsSaving = 0; return self; } - readSData:(char *)fileName { if (!strcmp(fileName,"")) { /* [self set_Theta:self]; [self set_Phi:self]; [self set_dist:self]; strcpy(fileNAME,"Untitled"); [[self window] setTitle:fileName]; [self display]; */ [self clear:self]; } else { if ([self readFile:fileName] != NULL) { [self clear:self]; [[self window] setTitle:fileName]; [self textChanged:self]; [self plot:self]; } } return self; } - drawSelf:(const NXRect *)rects :(int)rectCount { NXDrawWhiteBezel(rects,rects); return self; } - readFile:(char *)fileName { FILE *input; char thisline[MAXLINE], *cpt, *trimmer; if((input = fopen(fileName, "r")) == NULL) { sprintf(thisline, "Unable to open file %s", fileName); [self showError:thisline]; return NULL; } if (delegate && [delegate respondsTo:@selector(stereoView:clearText:)]) [delegate stereoView:self clearText:fileName]; fgets(thisline, MAXLINE, input); while (!feof(input)) { trimmer = cpt = &thisline[0]; while(*trimmer++ != '\n'); trimmer--; while(*trimmer-- == ' '); trimmer++; if (*trimmer != '\n') *trimmer++ = '\n'; *trimmer = '\0'; if (delegate && [delegate respondsTo:@selector(stereoView:pointDidChange:)]) [delegate stereoView:self pointDidChange:cpt]; fgets(thisline, MAXLINE, input); } fclose(input); return self; } BOOL s_gets(thisline, max, stream) char thisline[]; int max; NXStream *stream; { int i; i = 0; while (!NXAtEOS(stream)) { thisline[i++] = NXGetc(stream); if (i > max) { return FALSE; } if (thisline[i-1] == '\n') { thisline[i] = '\0'; return TRUE; } } return(FALSE); } - (BOOL) readData:(NXStream *)stream { char line[128], thisline[128], *aPtr, *word(); char cmd; int nwords,i, words(), tolower(), isalpha(); float x[3], *fpt, argv[6]; long pts_read; scratch = (float *) calloc(MAXNUM, sizeof(float)); /* release existing data */ if ([dataList count] != 0) [dataList freeObjects]; pts_read = 0; cmd = 'p'; argv[0] = 0.; argv[1] = NX_BLACK; nwords = 0; fpt = scratch; pts_read = 0; while(s_gets(line,128,stream)) { if(lastch(line) == '\n') lastch(line) = '\0'; if(isalpha(line[0])) { if (pts_read != 0) { [self store_pts:cmd:argv]; [dataList addObject:myStorage]; } cmd = tolower(line[0]); nwords = min(words(line),5); for(i=1;i<6;i++) argv[i] = 0; for(i=1;i<=nwords;i++) { if((aPtr = word(i,line)) != NULL) { sscanf(aPtr,"%f",&argv[i]); } } switch (cmd) { case 'n': break; case 'l': argv[1] = (nwords < 1)?0.:argv[1]; /* width */ argv[2] = (nwords < 2)?NX_BLACK:argv[2]; /* shade */ // Add rgb here and in p and implement in Cubeview.m and psfcns (dim argv) for (i=3;i<6;i++) argv[i] = (nwords < i)?0.:argv[i]; /* color */ break; case 'p': argv[1] = (nwords < 1 )?0.:argv[1]; /* radius */ argv[2] = (nwords < 2)?NX_BLACK:argv[2]; /* shade */ for (i=3;i<6;i++) argv[i] = (nwords < i)?0.:argv[i]; /* color */ break; case 'b': break; default: sprintf(thisline, "Unknown Data Type"); [self showError:thisline]; return NO; break; } fpt = scratch; pts_read = 0; nlines = 0; continue; } sscanf(line,"%f %f %f",&x[0], &x[1], &x[2]); nlines++; if (pts_read + 3 > MAXNUM) { sprintf(thisline, "Number of points exceeds %d\n", MAXNUM); [self showError:thisline]; free(scratch); return NO; } for(i=0;i<3;i++) { *fpt++ = x[i]; } pts_read += 3; } if (pts_read != 0) { [self store_pts:cmd:argv]; [dataList addObject:myStorage]; } // [self debug]; free(scratch); // [self display]; return YES; } - debug /* Debuggin output */ { int i, j, k, nitems, type, ntypes; float *xx, *gpt, **displayed; // char thisline[128]; ntypes = [dataList count]; printf("There are %d types in dataList\n",ntypes); for(j=0;j<ntypes;j++) { myStorage = [dataList objectAt:j]; nitems = [myStorage howMany]; printf("Type # %d has %d points\n",j,nitems); xx = [myStorage args]; type = [myStorage dataType]; gpt = [myStorage array]; printf("Type = %d, argv is %10.6f, %10.6f, %10.6f\n", type,xx[1],xx[2],xx[3]); for(i=0;i<nitems/3;i++) { printf("%d) ",i); for (k=0;k<3;k++) printf(" %10.6f",gpt[i+k*nitems/3]); printf("\n"); } displayed = [myStorage displayed]; printf(" Show same data via displayed array\n"); for(i=0;i<nitems/3;i++) { printf("%d) ",i); for (k=0;k<3;k++) printf(" %10.6f",displayed[k][i]); printf("\n"); } } return self; } - (BOOL)store_pts:(char)cmd:(float *)argv { int type = NEITHER; /* create the datapoints structure and store the values */ switch(cmd) { case 'n': type = NEITHER; break; case 'l': type = LINES; break; case 'p': type = POINTS; /* * Store radius, shade, label here in thesedata->radius, etc. */ break; case 'b': type = BOTH; break; } myStorage = [[StoreData alloc] init:type:3*nlines:scratch:argv]; return YES; } int words(str) char *str; { int isalnum(), count=0; while(*str != '\0') { while(ok_char(*str)) str++; /* skip characters */ while(whitespace(*str)) str++; /* skip whitespace */ if(ok_char(*str)) count++; } return count; } char *word(i,str) int i; char *str; { int isalnum(), count=0; if(i > words(str)) return NULL; while(*str != '\0') { while(ok_char(*str)) str++; /* skip characters */ while(whitespace(*str)) str++; /* skip whitespace */ if(ok_char(*str)) if(++count == i) return str; } return NULL; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.