next up previous
Next: Some applications of REC-R Up: REC-R for Second Order Previous: RECView.h Header Listing

RECView.m Program Listing

The part of REC-R which is strictly REC is contained in the C program rec-sero.c, but it is embedded in the NeXTSTEP method RECView.m and its header, RECView.h so as to get the advantage of the whole user interface and operating system. Consequently RECView.m consists mainly of boiler plate operating the text files, the browser, copying Views hither and yon and printing them, and so on. Nevertheless it is included to give a complete definition of REC-R. Of course, certain vestiges of its subservience to SERO still remain, but are not elaborated.

#import "rec.h"
#import "RECView.h"
#import <string.h>

# define CLEN 1000		/* buffer length for rec source       */
# define PLEN 3000		/* buffer length for rec object       */
# define XLEN	   128		/* buffer length for rec predefined   */
# define NY	    25		/* number of demonstrations	      */

# define PI 3.14159

int    showRECBack=YES;
int    stillUnused=YES;

int    isErrm=(int)FALSE;
char   errm[50];

char   cstr[CLEN];	/* console rec program     */
Inst   rprg[PLEN];	/* rec program array       */
Inst   xprg [10][XLEN];
char   idef [1] [30] = {"(z((!100!0r:;)1r2r(0r:;);) a"};
extern struct fptbl dtbl[];

int    phil;		/* length of cstr	   */

@implementation RECView

/* =  =  =  =  =  =  =  =  =   R E C / S E R O   =  =  =  =  =  =  =  =  = */

- loadRECPanel:sender {
  if (RECPanel==nil) {
    if (![NXApp loadNibSection: "rec.nib" owner: self withNames: NO]) 
	{return nil;}
    [browser setEmptySelectionEnabled: YES];
    [browser setMultipleSelectionEnabled: NO];
    [browser getTitleFromPreviousColumn: NO];
    [browser setTitle: "components" ofColumn: 0];
    stillUnused=YES;
    }
  [RECPanel orderFront: nil];
  [RECMatrix setEmptySelectionEnabled: YES];
  [RECMatrix selectCellAt: -1: 0];
  [self loadRECSource: RECOButn];
  return self;
  }

/* - - - - - - - - - - - -  c o p y   v i e w s  - - - - - - - - - - - - - */

- print:sender {[sourceWindow smartPrintPSCode: self]; return self;}

- windowDidBecomeKey:sender {
	sourceWindow=sender;
    if (sourceWindow==solutionWindow) sourceView=solutionView;
    if (sourceWindow==phaseWindow)    sourceView=phaseView;
    if (sourceWindow==controlWindow)  sourceView=[controlWindow contentView];
      else sourceView=NULL;
	[menuCopy setTarget: self];
	[menuCopy setAction: @selector(copy:)];
	[menuCopy setEnabled: YES];
	[menuPrint setTarget: self];
	[menuPrint setAction: @selector(print:)];
	[menuPrint setEnabled: YES];
return self;
}

- windowDidResignKey:sender {
	[menuCopy setEnabled: NO];
	[menuPrint setEnabled: NO];
return self;
}

- copy:sender {
    showRECBack=NO;
    if (sourceWindow==solutionWindow) [self copySomeView: solutionView];
    if (sourceWindow==phaseWindow)  [self copySomeView: phaseView];
    if (sourceWindow==RECPanel) [self copySomeView: [RECPanel contentView]];
    if (sourceWindow==controlWindow) 
			[self copySomeView: [controlWindow contentView]];
    showRECBack=YES;
return self;
}

- copySomeView:theView {
NXRect zbounds;
id     pBoard;
  showRECBack=NO;
  pBoard = [Pasteboard new];
  [pBoard declareTypes: &NXPostScriptPboardType num: 1 owner: self];
  [theView getBounds: &zbounds];
  [theView writePSCodeInside: &zbounds to: pBoard]; 
  showRECBack=YES;
return self;
}

/* - - - - S P E C I A L   R U L E   B O X   M A N A G E M E N T - - - - */

- loadRECSource:sender {
  if   ([[sender selectedCell] state])  [self loadLowerPanel: intBox];
  else					[self loadLowerPanel: extBox];
return self;
}

- loadLowerPanel:thisBox {
  NXRect bxRect, loRect;
  id cv;
cv=[thisBox contentView];
// printf("number of subviews = %d\n",[[cv subviews] count]);
//  [lilBox setContentView: cv];
  [bigBox setContentView: cv];
//  [bigBox getFrame: &bxRect];
//  [lilBox getFrame: &loRect];
//  loRect.origin.x=bxRect.origin.x+
//	(bxRect.size.width-loRect.size.width)/2.0;
//  loRect.origin.y=bxRect.origin.y+
//	(bxRect.size.height-loRect.size.height)/2.0;
//  [lilBox setFrame: &loRect];
  [bigBox display];
//  [lilBox display];
return self;
}

/*---------------- B R O W S E R  D E L E G A T E -------------------*/

- (int)browser:sender fillMatrix: matrix inColumn: (int)col {int  i, n;
    n=0;
    printf("browser\n");
     switch(col) {
        case 0: 
          for(i=0; i<5; i++) {
            [matrix addRow];
            [[matrix cellAt: i: 0]  setLeaf : NO ];     
            [[matrix cellAt: i: 0]  setLoaded : YES ];   
            [[matrix cellAt: i: 0]  setEnabled : YES ];
           }
           [[matrix cellAt: 0: 0]  setStringValue: "graph solutions"];     
           [[matrix cellAt: 1: 0]  setStringValue: "phase plane"];     
           [[matrix cellAt: 2: 0]  setStringValue: "stability diagram"];
	   [[matrix cellAt: 3: 0]  setStringValue: "asymptotic values"];
	   [[matrix cellAt: 4: 0]  setStringValue: "just definitions"];
           n=5;
           break;
        case 1:
          if(strcmp([[sender selectedCell] stringValue],
		 "graph solutions") == 0) {
//          for(i=0; i<NY; i++) {
//            [matrix addRow];
//            [[matrix cellAt: i: 0]  setStringValue: recrule[i]];
//            [[matrix cellAt: i: 0]  setLeaf : YES ];     
//            [[matrix cellAt: i: 0]  setLoaded : YES ];   
//            [[matrix cellAt: i: 0]  setEnabled : YES ];
//           }
          n=NY;}
          if(strcmp([[sender selectedCell] stringValue],
		 "predefined") == 0) {
          for(i=0; i<1; i++) {
            [matrix addRow];
            [[matrix cellAt: i: 0]  setStringValue: idef[i]];
            [[matrix cellAt: i: 0]  setLeaf : YES ];     
            [[matrix cellAt: i: 0]  setLoaded : YES ];   
            [[matrix cellAt: i: 0]  setEnabled : YES ];
           }
          n=1;}

          if(strcmp([[sender selectedCell] stringValue],
		 "just definitions") == 0) {
          for(i=0; i<95; i++) {
            [matrix addRow];
            [[matrix cellAt: i: 0]  setStringValue: dtbl[i].r_cmnt];
            [[matrix cellAt: i: 0]  setLeaf : YES ];     
            [[matrix cellAt: i: 0]  setLoaded : YES ];   
            [[matrix cellAt: i: 0]  setEnabled : YES ];
           }
          n=95;}

        default: n=0; break; }
      return n;
    }

/* to distract the single click in a browser double click */
- nhul: sender {return self;}

/* - - - - - - -   F I L E   A N D   D I R E C T O R Y   - - - - - - - */

- setFilename:(const char *)aFilename {
  if (filename) free(filename);
  filename = malloc(strlen(aFilename)+1);
  strcpy(filename, aFilename);
  [window setTitleAsFilename:aFilename];
  return self;
}

- load:(const char*)filename {
  int      i, fd;
  NXStream *theStream;
    [self loadRECPanel: self];
    [bigBox setContentView: [extBox contentView]];
    [self setFilename: filename];
    fd = open(filename, O_RDONLY, 06666);
    theStream = NXOpenFile(fd, NX_READONLY);
//      NXScanf(theStream,"%s",cstr);
      i=0;
      while (NXScanf(theStream,"%c",&cstr[i])!=EOF) i++;
      phil=strlen(cstr);
    NXClose(theStream);
    close(fd);
    [RECPanel setTitleAsFilename: filename];
    [RECPanel setDocEdited:NO];
  [execWin setSel: 0: [execWin textLength]];
  [execWin replaceSel: cstr];
  [execWin scrollSelToVisible];
  [execWin display];

return self;
}

- open:sender {
  char *types[3] = {"rec","rec-r",0};
  int  i, fd;
  NXStream *theStream;

  [[OpenPanel new] allowMultipleFiles: NO];
  [[OpenPanel new] chooseDirectories: NO];

  if ([ [OpenPanel new] runModalForTypes: types]) {
    [self setFilename: [[OpenPanel new] filename]];
    fd = open(filename, O_RDONLY, 06666);
    theStream = NXOpenFile(fd, NX_READONLY);
//      NXScanf(theStream,"%s",cstr);
      i=0;
      while (NXScanf(theStream,"%c",&cstr[i])!=EOF) i++;
      phil=strlen(cstr);
    NXClose(theStream);
    close(fd);
    [RECPanel setTitleAsFilename: filename];
    [RECPanel setDocEdited:NO];
  [execWin setSel: 0: [execWin textLength]];
  [execWin replaceSel: cstr];
  [execWin scrollSelToVisible];
  [execWin display];
    }

return self;
}

- saveAs:sender {
  id panel;
  const char *dir;
  char *file;

/* prompt user for the file name and save to that file */

  if (filename==0) {
    /* no filename; set up defaults */ 
    dir  = NXHomeDirectory();
    file = (char *)[RECPanel title];
    } else {
    file=rindex(filename,'/');
    if (file) {
      dir   = filename;
      *file = 0;
      file++;
      } else {
      dir  = filename;
      file = (char *)[RECPanel title];
      }
    }
  panel = [SavePanel new]; 
  [panel setRequiredFileType: "rec-r"];
  if ([panel runModalForDirectory: dir file: file]) {
    [self setFilename: [panel filename]];
    return [self save: sender];
    }
    return nil;  /* didn't save */
  }
    
- save:sender {
  int      fd;
  NXStream *theStream;

  if (filename==0) return [self saveAs: sender];
  [RECPanel setTitle: "Saving ..."];

  fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 06666);
  if (fd < 0) {
    NXRunAlertPanel(0, "Cannot save file: %s",0,0,0,strerror(errno));
    return self;
    }
  theStream = NXOpenFile(fd, NX_WRITEONLY);
  [execWin writeText: theStream];
  NXClose(theStream);
  close(fd);
  [RECPanel setTitleAsFilename: filename];
  [RECPanel setDocEdited:NO];
  return self;
}

- close:sender {const char *fname;
int         q;
  if ([RECPanel isDocEdited])
//    fname=filename ? filename : [sender title];
//    if (rindex(fname,'/')) fname = rindex(fname,'/') + 1;
    q = NXRunAlertPanel(
      "Save",
      "Save changes to %s?",
      "Save",
      "Don't Save",
      "Cancel",
      filename);
    if (q==1) {if (![self save:nil]) return nil;}
    if(q==-1) return nil;
//  [sender setDelegate: nil];
//  [proc free];
//  [self free];
  return self;
}

- windowWillClose:sender {
[self close: self];
printf("windowWillClose\n");
return self;
}

/* = = = = = = = = =   P r o g r a m   E d i t o r   = = = = = = = = = */

- recMatrix:sender {int i, j;
  i=[sender selectedRow];
  j=[sender selectedCol];
  [comment setStringValue: dtbl[i*32+j].r_cmnt];
return self;
}

- ascii:sender {int i;
  if ([sender selectedRow]==0) i='A'-' '; else i='a'-' ';
  dtbl[i+[sender selectedCol]].xfun();
return self;
}

/* - - - - - - -  R E C   L I N E   C O N F I G U R A T I O N  - - - - */
 
- run:sender {[self display]; return self;}

- runPhase:sender {
	stillUnused=YES;
	[phaseWindow makeKeyAndOrderFront: sender];
	stillUnused=NO;
	[phaseView display];
return self;
}

- runSolution:sender {
	stillUnused=YES;
	[solutionWindow makeKeyAndOrderFront: sender];
	stillUnused=NO;
	[solutionView display];
return self;
}

- recompile:sender {
  [execWin getSubstring: cstr start: 0 length: [execWin textLength]];
  [RECPanel setDocEdited:YES];
return self;
}

- useRECLine:sender {
  [RECPanel makeKeyAndOrderFront: sender];
  [RECValue setStringValue: " "];
 return self;
}

- runRECOffLine:sender {
  [RECValue setStringValue: "*"];
  if (rec([sender stringValue])) {
     [RECValue setStringValue: "T"];
     }
  else
    [RECValue setStringValue: "F"];
  return self;
}

- copyREC:sender {
   if ([sender selectedColumn] == [sender lastColumn]) {
   if(strcmp([sender titleOfColumn: [sender lastColumn]],"graph solutions") 
	== 0) {
     [RECValue setStringValue: " "];
     [RECLine setStringValue: [[sender selectedCell] stringValue]];
     }}
   return self;
  }

int rec(z) char *z; {if (rec_c(z,rprg,PLEN,dtbl)==1) rec_x(rprg);}

/* = = = = = = = = = = =     R E C V I E W     = = = = = = = = = = = = = */

- initFrame:(const NXRect *)frameRect
/*
 * Initializes the new RECView object. First, an initFrame: message is sent 
 * to super to initialize RECView as a View. Next, the RECView sets its own 
 * state -- opaque and that the origin of its coordinate system lies 
 * in the center of its area. It then creates and initializes its associated 
 * objects, a Storage object, an NXCursor, and a Cell. Finally, it loads into 
 * the Window Server some PostScript procedures that it will use in drawing 
 * itself. 
 */
{
    [super initFrame: frameRect];
    [self translate:floor(frame.size.width/2) :floor(frame.size.height/2)];
    [self setOpaque:YES];
    return self;
}

- drawSelf:(const NXRect *)rects :(int)rectCount
/*
 * Draws the RECView's background and axes.  If there are any points,
 * these are drawn too.
 *
 * (Note:  For simplicity, although RECView only repaints the background 
 * of the update region, it redraws the entire axes. For better performance, 
 * only those parts of the axes that fall within the update region should 
 * be redrawn.)   
 */
{
	NXPoint		*aPoint;
	
	if (rects == NULL) return self;
	if (stillUnused)   return self;

	/* paint visible area white then draw axes */
	PSsetgray(NX_WHITE);
	if (showRECBack) NXRectFill(&rects[0]);
	PSsetgray(NX_DKGRAY);

printf("drawing self %s\n",cstr);

	  isErrm=FALSE;
	  [RECValue setStringValue: "*"];
	  if (rec(cstr)) [RECValue setStringValue: "t"];
		    else [RECValue setStringValue: "f"];
	  if (isErrm) {[comment setStringValue: errm]; isErrm=FALSE;}
	  PSstroke();

return self;
}

- sizeTo:(NXCoord)width :(NXCoord)height
/*
 * Ensures that whenever the RECView is resized, the origin of its 
 * coordinate system is repositioned to the center of its area.
 */
{
	[super sizeTo: width: height];
	[self setDrawOrigin: -floor(width/2): -floor(height/2)]; 
	return self;
}

@end

/* end RECView.m */



Microcomputadoras
2001-01-10