home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1989-12-24 | 33.4 KB | 1,401 lines
#include:crt.g #include:util.g uint dwindsize=22; /* depth of record window */ uint windwidth=77; /* width of screen */ uint maxrecs=1000; /* max no. of records */ uint maxsels=20; /* max no. of selections */ uint maxfields=20; /* max fields per record */ uint maxfieldsize=200; /* max size field */ uint blocksize=256; /* size of a diskblock */ uint filenamelen=20; /* length of a filename */ uint namesize=80; /* size of a selection name */ uint fieldnamesize=8; /* size of a field name */ uint maxtot=maxfields*maxfieldsize; /*store for one record */ uint maxmess=maxfieldsize+15 ; /* maxstringsize */ /* ************************* NOTE ************************* array declaration [x] type gives an array with x elements numbered 0..x-1 ! what is more draco does no range checking so if you think there is an xth element and assign to it you will succeed but create all sorts of strange side effects (corrupted data , crashes, etc) YOU HAVE BEEN WARNED .... j.d */ type string=[maxmess+1] char; /* normal string */ type totstore=[maxtot+1] char; /*storage for one complete record */ type indexfield=struct { [namesize+1] char indexname; [maxrecs+1] bool map; uint numonlev; }; /* info for one level in index name contains op that was performed at that level map the selection map that resulted numonlev the number recs on that level */ type index=struct{ [maxsels+1] indexfield level; uint curlev; uint currecnum; uint maxrecnum; uint numdeletes; }; /* complete index for the database level has maps fro each level curlev the current level in the database currecnum the current record number maxrecnum the max record number in use level 1 is the global level */ type defnfield=struct{ uint tlx,tly; uint brx,bry; uint size; [fieldnamesize+1] char fieldname; }; /* tlx,tly,brx,bry are co-ords of fields on screen box size is total size of field name the fields name a size of 0 means not used */ type definition=struct{ [maxfields+1] defnfield spec; uint totsize; uint blkfac; }; /* complete definition of database spec holds definition info for each field totsize the complete size of one record blkfac the computed disk blocking factor */ type datafield=string; /* run time storage for one record */ type datarecord=[maxfields+1] datafield; /* run time store for one record */ type diskblock=[blocksize+1] char; /* disk input output record */ /* variable declarations */ string filnm; /* name for database file */ [windwidth+1,dwindsize+1] char scrbuf; /* screen output buffer */ file () outfile; /* output dump file */ channel output text outfilout; bool filopnd; /* file opened flag */ bool quit; /* end flag */ char response; /* general input */ string fnm; /* fieldname for searches */ string ptrn; /* pattern for searches */ string lstr,tstr; /* status line display */ string rstr,nstr; /* status line display */ index dataindex; /* the working index */ definition dbasedefn; /* the working definition */ datarecord currec; /* current record in mem */ file () curdatfil; channel output binary curdatfilout; channel input binary curdatfilin; file () curdeffil; channel output binary curdeffilout; channel input binary curdeffilin; file () curindxfil; channel output binary curindxfilout; channel input binary curindxfilin; string rootname; /* base part of database filename */ totstore store; /* scratch i/o storage */ channel output text crtout; /* crt access channel */ proc initscreen() void: /* open screen */ /* MACHINE SPECIFIC */ CRT_Initialize("File-it 1.0/ns",dwindsize+3,windwidth); open(crtout,CRT_PutChar); CRT_AbortDisable(); corp; proc closescreen() void: /* close screen */ /* MACHINE SPECIFIC */ close(crtout); CRT_Terminate(); corp; proc gotoxy(uint x,y) void: /* locate cursor at x,y */ /* cursor co-ords 1,1 80,25 */ /* MACHINE SPECIFIC */ CRT_Move(y-1,x-1); corp; proc printchr(char c) void: /* print a char and advance cursor */ /* MACHINE SPECIFIC */ CRT_PutChar(c); corp; proc getchr() char: /* gets a character from keyboard .. no echo */ /* MACHINE SPECIFIC */ char tc; tc:=CRT_ReadChar(); tc corp; proc clearrecwind() void: /* clear record display window */ /* MACHINE SPECIFIC */ CRT_ClearLines(0,dwindsize); corp; proc clearscr() void: /* clear entire screen */ /* MACHINE SPECIFIC */ CRT_ClearScreen(); corp; proc clearcmdwind() void: /* clear command window */ /* MACHINE SPECIFIC */ CRT_ClearToEnd(dwindsize+1); corp; proc clearstatwind() void: /* clear status window */ /* MACHINE SPECIFIC */ CRT_ClearLine(dwindsize); corp; proc movecursor(*uint x,y) void: /* allow user to move cursor around until RET pressed */ /* returns co-ords where ret pressed */ /* co-ords are ranged 1..windwidth 1..dwindsize */ /* MACHINE SPECIFIC */ char c; uint a,b; CRT_Move(0,0); a:=1; b:=1; c:=' '; while c~='\r' do c:=CRT_ReadChar(); if c='\(155)' then c:=CRT_ReadChar(); if c='D' then if a>1 then a:=a-1; CRT_Move(b-1,a-1); fi; elif c='C' then if a<windwidth then a:=a+1; CRT_Move(b-1,a-1); fi; elif c='A' then if b>1 then b:=b-1; CRT_Move(b-1,a-1); fi; elif c='B' then if b<dwindsize then b:=b+1; CRT_Move(b-1,a-1); fi; fi; fi; od; x*:=a; y*:=b; corp; proc readstr(*char str;uint maxlen) void: /* read a string at the current cursor pos */ /* upto size limit of maxlen chars */ /* obey CR & BS only */ /* MACHINE SPECIFIC */ char c; uint a; string s; if not CRT_Read(str,maxlen+1,false,false,"",pretend(&s,*char)) then CharsCopy(str,""); fi; corp; proc printstrbox(uint x1,y1,x2,y2;*char s) void: /* prints a string in a box on screen */ uint a,b,c; *char str; gotoxy(x1,y1); str:=s; a:=x1; b:=y1; c:=0; while (str* ~= '\e' and b <= y2) do if a>x2 then a:=x1; b:=b+1; gotoxy(a,b); fi; if b<=y2 then printchr(str*); str:=str+1; a:=a+1; fi; od; corp; proc editstrbox(uint etlx,etly,ebrx,ebry,skip;* char s) void: /* edits the string on screen inside box */ /* note indents skip chars on first line */ /* doesnt do initial display of field */ /* MACHINE SPECIFIC */ char c; uint i,j; uint pos; *char t; pos:=1; i:=etlx+(skip % (ebrx-etlx+1)); j:=etly+(skip / (ebrx-etlx+1)); gotoxy(i,j); c:=' '; while c~='\r' do c:=CRT_ReadChar(); if c='\(155)' then c:=CRT_ReadChar(); if c='D' then if pos>1 then pos:=pos-1; i:=i-1; if i<etlx then i:=ebrx; j:=j-1; fi; gotoxy(i,j); fi; elif c='C' then if (pos<CharsLen(s) and (i<=ebrx) and (j<=ebry)) then pos:=pos+1; i:=i+1; if i>ebrx then i:=etlx; j:=j+1; fi; gotoxy(i,j); fi; elif c='A' then if (pos>(ebrx-etlx+1)) then pos:=pos-(ebrx-etlx+1); j:=j-1; gotoxy(i,j); fi; elif c='B' then if j<ebry then pos:=pos+(ebrx-etlx+1); j:=j+1; gotoxy(i,j); fi; fi; else if (pos<=CharsLen(s)) and (i<=ebrx) and (j<=ebry) and (c>=' ') and (c<'\(127)') then t:=s+pos-1; t*:=c; gotoxy(i,j); printchr(c); pos:=pos+1; i:=i+1; if (i>ebrx) then i:=etlx; j:=j+1; fi; fi; fi; od; corp; proc doerror(* char s) void: /* write string on error status line and wait */ char d; clearstatwind(); printstrbox(1,dwindsize+1,windwidth,dwindsize+1,s); d:=getchr(); clearstatwind(); corp; proc savedefn() void: /* save definition to disk */ /* MACHINE SPECIFIC */ string sdts; CharsCopy(pretend(&sdts,*char),pretend(&rootname,*char)); CharsConcat(pretend(&sdts,*char),".def"); pretend(FileCreate(pretend(&sdts,*char)),void); open(curdeffilout,curdeffil,pretend(&sdts,*char)); write(curdeffilout;dbasedefn); close(curdeffilout); corp; proc loaddefn() void: /*load in definition from disk */ /*MACHINE SPECIFIC */ string ldts; CharsCopy(pretend(&ldts,*char),pretend(&rootname,*char)); CharsConcat(pretend(&ldts,*char),".def"); open(curdeffilin,curdeffil,pretend(&ldts,*char)); read(curdeffilin;dbasedefn); close(curdeffilin); corp; proc saveindx() void: /* save index to disk */ /* MACHINE SPECIFIC */ string sits; CharsCopy(pretend(&sits,*char),pretend(&rootname,*char)); CharsConcat(pretend(&sits,*char),".idx"); pretend(FileCreate(pretend(&sits,*char)),void); open(curindxfilout,curindxfil,pretend(&sits,*char)); write(curindxfilout;dataindex); close(curindxfilout); corp; proc loadindx() void: /* load index from disk */ /* MACHINE SPECIFIC */ string lits; CharsCopy(pretend(&lits,*char),pretend(&rootname,*char)); CharsConcat(pretend(&lits,*char),".idx"); open(curindxfilin,curindxfil,pretend(&lits,*char)); read(curindxfilin;dataindex); close(curindxfilin); corp; proc createdbase() void: /* create and initialize index and data files */ /* MACHINE SPECIFIC */ uint a; string crts; CharsCopy(pretend(&crts,*char),pretend(&rootname,*char)); CharsConcat(pretend(&crts,*char),".dat"); pretend(FileCreate(pretend(&crts,*char)),void); for a from 1 by 1 upto maxrecs do dataindex.level[1].map[a]:=false; od; CharsCopy(pretend(&dataindex.level[1].indexname,*char),"top level"); dataindex.level[1].numonlev:=0; dataindex.currecnum:=1; dataindex.maxrecnum:=0; dataindex.curlev:=1; dataindex.numdeletes:=0; saveindx(); corp; proc getcoords(* uint gx1,gy1,gx2,gy2) void: uint tx1,tx2,ty1,ty2,tt; clearcmdwind(); printstrbox(1,dwindsize+2,windwidth,dwindsize+2,"move cursor to first corner and press enter "); printstrbox(1,dwindsize+3,windwidth,dwindsize+3,"Use cursor keys"); movecursor(&tx1,&ty1); printstrbox(1,dwindsize+2,windwidth,dwindsize+2,"move cursor to second corner and press enter "); movecursor(&tx2,&ty2); if (tx2<tx1) then tt:=tx1; tx1:=tx2; tx2:=tt; fi; if (ty2<ty1) then tt:=ty1; ty1:=ty2; ty2:=tt; fi; gx1*:=tx1; gx2*:=tx2; gy1*:=ty1; gy2*:=ty2; corp; proc setupdefn () void: /* allow user to set up record structure */ bool doneflag,errflag; uint x1,y1,x2,y2,t; string s,fillstr,clrstr; uint p; CharsCopy(pretend(&fillstr,*char),""); CharsCopy(pretend(&clrstr,*char),""); for p from 1 by 1 upto maxfieldsize do CharsConcat(pretend(&fillstr,*char),"*"); CharsConcat(pretend(&clrstr,*char)," "); od; doneflag:=false; errflag:=true; p:=1; clearscr(); while (p<=maxfields) and (doneflag=false) do clearcmdwind(); printstrbox(1,dwindsize+2,windwidth,dwindsize+2,"Enter name of field or ENTER to finish"); gotoxy(42,dwindsize+2); readstr(pretend(&s,*char),fieldnamesize); if CharsLen(pretend(&s,*char))=0 then doneflag:=true; else CharsConcat(pretend(&s,*char)," "); CharsCopyN(pretend(&dbasedefn.spec[p].fieldname,*char),pretend(&s,*char),fieldnamesize); while getcoords(&x1,&y1,&x2,&y2); dbasedefn.spec[p].tlx:=x1; dbasedefn.spec[p].tly:=y1; dbasedefn.spec[p].brx:=x2; dbasedefn.spec[p].bry:=y2; dbasedefn.spec[p].size:=(x2-x1+1)*(y2-y1+1); if (dbasedefn.spec[p].size>maxfieldsize) or (dbasedefn.spec[p].size<fieldnamesize+1) then errflag:=true; else errflag:=false; fi; errflag=true do; od; CharsCopy(pretend(&s,*char),pretend(&dbasedefn.spec[p].fieldname,*char)); CharsConcat(pretend(&s,*char),pretend(&fillstr,*char)); CharsCopyN(pretend(&s,*char),pretend(&s,*char),dbasedefn.spec[p].size); printstrbox(x1,y1,x2,y2,pretend(&s,*char)); clearcmdwind(); printstrbox(1,dwindsize+2,windwidth,dwindsize+2,"is this ok (y/n) : "); while gotoxy(22,dwindsize+2); readstr(pretend(&s,*char),1); s[0]~='y' and s[0]~='Y' and s[0]~='n' and s[0]~='N' do od; if (s[0]='y') or (s[0]='Y') then p:=p+1; else printstrbox(x1,y1,x2,y2,pretend(&clrstr,*char)); fi; fi; od; for t from p by 1 upto maxfields do dbasedefn.spec[t].tlx:=1; dbasedefn.spec[t].tly:=1; dbasedefn.spec[t].brx:=1; dbasedefn.spec[t].bry:=1; dbasedefn.spec[t].size:=0; CharsCopyN(pretend(&dbasedefn.spec[t].fieldname,*char),"EMPTY ",8); od; dbasedefn.totsize:=0; for p from 1 by 1 upto maxfields do dbasedefn.totsize:=dbasedefn.totsize+dbasedefn.spec[p].size; od; dbasedefn.blkfac:=dbasedefn.totsize/blocksize+1; savedefn(); createdbase(); clearscr(); corp; proc initfiles() void: /*open all files ready for use */ /*assumes rootname already set */ /* MACHINE SPECIFIC */ string is; CharsCopy(pretend(&is,*char),pretend(&rootname,*char)); CharsConcat(pretend(&is,*char),".dat"); loadindx(); loaddefn(); open(curdatfilin,curdatfil,pretend(&is,*char)); ReOpen(curdatfilin,curdatfilout); corp; proc getrecord(uint i) void: /* getrecord no i from disk and put in currec */ /* MACHINE SPECIFIC */ uint a,b,c; *char gtp; diskblock gtemp; pretend(SeekIn(curdatfilin,(i-1)*dbasedefn.blkfac*sizeof(diskblock)),void); c:=1; for a from 1 by 1 upto dbasedefn.blkfac do read(curdatfilin;gtemp); BlockMove(pretend(&store[c-1],*byte),pretend(>emp[0],*byte),blocksize); c:=c+blocksize; od; c:=1; for a from 1 by 1 upto maxfields do if dbasedefn.spec[a].size>0 then BlockMove(pretend(&currec[a],*byte),pretend(&store[c-1],*byte),dbasedefn.spec[a].size); gtp:=pretend(&currec[a],*char)+dbasedefn.spec[a].size; gtp*:='\e'; c:=c+dbasedefn.spec[a].size; fi; od; corp; proc putrecord(uint i) void: /* put record in currec to disk record i */ /* MACHINE SPECIFIC */ diskblock ptemp; uint a,b,c; pretend(SeekOut(curdatfilout,(i-1)*dbasedefn.blkfac*sizeof(diskblock)),void); c:=1; for a from 1 by 1 upto maxfields do if dbasedefn.spec[a].size>0 then BlockMove(pretend(&store[c-1],*byte),pretend(&currec[a],*byte),dbasedefn.spec[a].size); c:=c+dbasedefn.spec[a].size; fi; od; c:=1; for a from 1 by 1 upto dbasedefn.blkfac do BlockMove(pretend(&ptemp[0],*byte),pretend(&store[c-1],*byte),blocksize); c:=c+blocksize; write(curdatfilout;ptemp); od; corp; proc gotonextrecord() void: /* moves currecnum to the next record on the cur lev and gets it */ if dataindex.level[dataindex.curlev].numonlev=0 then doerror("error gotonextrecord ... this level is empty!"); else while dataindex.currecnum:=dataindex.currecnum+1; if dataindex.currecnum>dataindex.maxrecnum then dataindex.currecnum:=1; fi; dataindex.level[dataindex.curlev].map[dataindex.currecnum]=false do od; getrecord(dataindex.currecnum); fi; corp; proc gotoprevrecord() void: /* moves currecnum to the previous record and gets it */ if dataindex.level[dataindex.curlev].numonlev=0 then doerror("error gotoprevrecord ... this level is empty!"); else while dataindex.currecnum:=dataindex.currecnum-1; if dataindex.currecnum=0 then dataindex.currecnum:=dataindex.maxrecnum; fi; dataindex.level[dataindex.curlev].map[dataindex.currecnum]=false do od; getrecord(dataindex.currecnum); fi; corp; proc gotofirst() void: /* movces currecnum to the first rec on level and gets it */ if dataindex.level[dataindex.curlev].numonlev=0 then doerror("error gotofirst ... this level is empty!"); else dataindex.currecnum:=1; if dataindex.level[dataindex.curlev].map[dataindex.currecnum]=false then gotonextrecord(); else getrecord(dataindex.currecnum); fi; fi; corp; proc gotolast() void: /* goto last record on current level and get it */ if dataindex.level[dataindex.curlev].numonlev=0 then doerror("error gotolast ... this level is empty"); else dataindex.currecnum:=dataindex.maxrecnum; if dataindex.level[dataindex.curlev].map[dataindex.currecnum]=false then gotoprevrecord(); else getrecord(dataindex.currecnum); fi; fi; corp; proc dumpstrbox(uint x1,y1,x2,y2;*char ds) void: /* dump string into image buffer */ uint gx,gy,a,b,c; string str; CharsCopy(pretend(&str,*char),ds); gx:=x1; gy:=y1; a:=x1; b:=y1; c:=1; while (c<=CharsLen(pretend(&str,*char))) and (b<=y2) do if a>x2 then a:=x1; b:=b+1; gx:=a; gy:=b; fi; if b<=y2 then scrbuf[gx,gy]:=str[c-1]; gx:=gx+1; c:=c+1; a:=a+1; fi; od; corp; proc outlevel(*char fn) void: /*dump current level to disk file as ascii */ /* MACHINE SPECIFIC */ uint x,y,c; string dts; if dataindex.level[dataindex.curlev].numonlev=0 then doerror("error dumplevel ... this level is empty!"); else if not FileCreate(fn) then doerror("dump filecreate failed"); fi; if not open(outfilout,outfile,fn) then doerror("dump file open failed"); fi; for y from 1 by 1 upto dwindsize do for x from 1 by 1 upto windwidth do scrbuf[x,y]:=' '; od; od; dataindex.currecnum:=1; while dataindex.currecnum<=dataindex.maxrecnum do if dataindex.level[dataindex.curlev].map[dataindex.currecnum]=true then getrecord(dataindex.currecnum); for c from 1 by 1 upto maxfields do if dbasedefn.spec[c].size>0 then CharsCopy(pretend(&dts,*char),pretend(&dbasedefn.spec[c].fieldname,*char)); CharsConcat(pretend(&dts,*char),pretend(&currec[c],*char)); dumpstrbox(dbasedefn.spec[c].tlx, dbasedefn.spec[c].tly, dbasedefn.spec[c].brx, dbasedefn.spec[c].bry, pretend(&dts,*char) ); fi; od; for y from 1 by 1 upto dwindsize do for x from 1 by 1 upto windwidth do write(outfilout;scrbuf[x,y]); od; writeln(outfilout;); od; writeln(outfilout;); fi; dataindex.currecnum:=dataindex.currecnum+1; od; close(outfilout); gotofirst(); fi; corp; proc displayrec() void: /* display currec on screen */ uint za; string ts; for za from 1 by 1 upto maxfields do if dbasedefn.spec[za].size>0 then CharsCopy(pretend(&ts,*char),pretend(&dbasedefn.spec[za].fieldname,*char)); CharsConcat(pretend(&ts,*char),pretend(&currec[za],*char)); printstrbox(dbasedefn.spec[za].tlx, dbasedefn.spec[za].tly, dbasedefn.spec[za].brx, dbasedefn.spec[za].bry, pretend(&ts,*char)); fi; od; corp; proc addrecord() void: /* adds the current memory record to dbase and leaves currecnum pointing to it*/ /* NOTE at present unconditionally adds record to current selection */ uint a,b; if dataindex.numdeletes>0 then a:=1; while dataindex.level[1].map[a]=true do a:=a+1; od; dataindex.numdeletes:=dataindex.numdeletes-1; putrecord(a); dataindex.currecnum:=a; for b from 1 by 1 upto maxsels do dataindex.level[b].map[a]:=true; dataindex.level[b].numonlev:=dataindex.level[b].numonlev+1; od; elif dataindex.maxrecnum=maxrecs then doerror("error addrecord ... database is full, unable to add record"); gotolast(); else a:=dataindex.maxrecnum+1; putrecord(a); dataindex.maxrecnum:=a; dataindex.currecnum:=a; for b from 1 by 1 upto maxsels do dataindex.level[b].map[a]:=true; dataindex.level[b].numonlev:=dataindex.level[b].numonlev+1; od; fi; corp; proc deleterecord() void: /* deletes the current record from dbase and moves to next record */ uint a; if dataindex.currecnum=0 then doerror("error delete record ... database is empty"); else for a from 1 by 1 upto maxsels do dataindex.level[a].map[dataindex.currecnum]:=false; dataindex.level[a].numonlev:=dataindex.level[a].numonlev-1; od; dataindex.numdeletes:=dataindex.numdeletes+1; gotonextrecord(); fi; corp; proc editrecord() void: /* display and edit currec on screen */ char c; uint p,i; string ts; clearscr(); displayrec(); p:=1; while CharsCopy(pretend(&ts,*char),pretend(&dbasedefn.spec[p].fieldname,*char)); CharsConcat(pretend(&ts,*char)," Edit Previous Next Done ( E P N D )"); printstrbox(1,dwindsize+2,windwidth,dwindsize+2,pretend(&ts,*char)); while gotoxy(46,dwindsize+2); c:=getchr(); not ((c='n') or (c='N') or (c='p') or (c='P') or (c='e') or (c='E') or (c='d') or (c='D')) do od; if (c='p') or (c='P') then p:=p-1; if p=0 then p:=maxfields; while dbasedefn.spec[p].size=0 do p:=p-1; od; fi; fi; if (c='n') or (c='N') then p:=p+1; if dbasedefn.spec[p].size=0 then p:=1; fi; fi; if (c='e') or (c='E') then printstrbox(1,dwindsize+3,windwidth,dwindsize+3,"Cursor keys-move, Enter-finish"); editstrbox(dbasedefn.spec[p].tlx, dbasedefn.spec[p].tly, dbasedefn.spec[p].brx, dbasedefn.spec[p].bry, fieldnamesize, pretend(&currec[p],*char)); printstrbox(1,dwindsize+3,windwidth,dwindsize+3," "); p:=p+1; if dbasedefn.spec[p].size=0 then p:=1; fi; fi; not((c='d') or (c='D')) do od; clearscr(); corp; proc upper(*char s) void: /* force string to upper case */ while s*~='\e' do s*:=pretend(pretend(s*,byte)|32,char); s:=s+1; od; corp; proc getnchar(*char s;uint n) char: /* return nth char of s n=1.. */ *char t; t:=s+n-1; t* corp; proc match(*char mpat,mss) bool: /* checks if ss matches on pat using wildcards */ uint i,j; bool done,matchd; string t1,t2; char tc; string p,s; *char pat,ss; pat:=pretend(&p,*char); ss:=pretend(&s,*char); CharsCopy(pat,mpat); CharsCopy(ss,mss); if getnchar(pat,1)='*' then if CharsLen(pat)=1 then matchd:=true; else i:=2; while i<=CharsLen(pat) and getnchar(pat,i)='?' do i:=i+1; od; if i>CharsLen(pat) then matchd:=true; else t1[0]:=getnchar(pat,i); t1[1]:='\e'; j:=CharsIndex(ss,pretend(&t1,*char))+1; if j=0 then matchd:=false; done:=true; else CharsCopy(pretend(&t1,*char),pat+i-1); CharsCopy(pretend(&t2,*char),ss+j-1); if match(pretend(&t1,*char),pretend(&t2,*char)) then matchd:=true; done:=true; else CharsCopy(ss,ss+j+1-1); fi; fi; fi; fi; else i:=1; done:=false; matchd:=true; while not done do if getnchar(pat,i)='*' then done:=true; elif getnchar(pat,i)~='?' then if getnchar(pat,i)~=getnchar(ss,i) then matchd:=false; done:=true; fi; fi; i:=i+1; if not done then if i>CharsLen(pat) and i>CharsLen(ss) then done:=true; elif i>CharsLen(pat) or i>CharsLen(ss) then done:=true; matchd:=false; fi; fi; od; fi; matchd corp; proc find(*char fpattern,fstr) bool: /* searches fstr for any occurence of pattern, matching on blank separated words. Search is non-case-sensitive. In pattern ? means match any single char and may occur anywhere in pattern. * means match any run of chars and may only be first or last element of patter */ *char pattern,str; string p,s; uint i,j; string ws; string ts; bool done,found; pattern:=pretend(&p,*char); str:=pretend(&s,*char); CharsCopy(pattern,fpattern); CharsCopy(str,fstr); upper(pattern); upper(str); if CharsIndex(pattern,"*")=-1 and CharsIndex(pattern,"?")=-1 then CharsCopy(pretend(&ws,*char)," "); CharsConcat(pretend(&ws,*char),pattern); CharsConcat(pretend(&ws,*char)," "); CharsCopy(pretend(&ts,*char)," "); CharsConcat(pretend(&ts,*char),str); CharsConcat(pretend(&ts,*char)," "); if CharsIndex(pretend(&ts,*char),pretend(&ws,*char))=-1 then found:=false; else found:=true; fi; else i:=1; j:=1; while getnchar(str,j)=' ' and j<=CharsLen(str) do j:=j+1; od; found:=false; done:=false; while j<=CharsLen(str) and not done do ws[i-1]:=getnchar(str,j); i:=i+1; j:=j+1; if getnchar(str,j)=' ' or j>CharsLen(str) then ws[i-1]:='\e'; if match(pattern,pretend(&ws,*char)) then done:=true; found:=true; fi; while getnchar(str,j)=' ' and j<=CharsLen(str) do j:=j+1; od; i:=1; fi; od; fi; found corp; proc select(*char f,p) void: /* carries out select op on database */ bool err,matchd; uint i,fieldnum,nummatchd; string tempstr,sfieldname,pattern; CharsCopy(pretend(&sfieldname,*char),f); CharsCopy(pretend(&pattern,*char),p); err:=false; matchd:=false; if CharsLen(pretend(&pattern,*char))>1 then for i from 2 by 1 upto CharsLen(pretend(&pattern,*char))-1 do if pattern[i-1]='*' then doerror("illegal pattern specifier"); err:=true; fi; od; fi; for i from 1 by 1 upto maxfields do if dbasedefn.spec[i].size>0 then CharsCopy(pretend(&tempstr,*char),pretend(&dbasedefn.spec[i].fieldname,*char)); if find(pretend(&sfieldname,*char),pretend(&tempstr,*char)) then matchd:=true; fieldnum:=i; fi; fi; od; if not matchd then doerror("bad fieldname"); err:=true; fi; if dataindex.curlev=maxsels then doerror("selection levels full, select abandoned"); err:=true; fi; if not err then nummatchd:=0; for i from 1 by 1 upto dataindex.maxrecnum do if dataindex.level[dataindex.curlev].map[i]=false then dataindex.level[dataindex.curlev+1].map[i]:=false; else getrecord(i); CharsCopy(pretend(&tempstr,*char),pretend(&currec[fieldnum],*char)); if find(pretend(&pattern,*char),pretend(&tempstr,*char)) then dataindex.level[dataindex.curlev+1].map[i]:=true; nummatchd:=nummatchd+1; else dataindex.level[dataindex.curlev+1].map[i]:=false; fi; fi; od; dataindex.curlev:=dataindex.curlev+1; CharsCopy(pretend(&tempstr,*char),"select "); CharsConcat(pretend(&tempstr,*char),pretend(&pattern,*char)); CharsConcat(pretend(&tempstr,*char)," on "); CharsConcat(pretend(&tempstr,*char),pretend(&sfieldname,*char)); CharsCopy(pretend(&dataindex.level[dataindex.curlev].indexname,*char),pretend(&tempstr,*char)); dataindex.level[dataindex.curlev].numonlev:=nummatchd; if nummatchd=0 then doerror("level empty ... select abandoned"); dataindex.curlev:=dataindex.curlev-1; else gotofirst(); fi; fi; corp; proc exclude(*char f,p) void: /* carries out exclude op on database */ bool err,matchd; uint i,fieldnum,nummatchd; string tempstr,sfieldname,pattern; CharsCopy(pretend(&sfieldname,*char),f); CharsCopy(pretend(&pattern,*char),p); err:=false; matchd:=false; if CharsLen(pretend(&pattern,*char))>1 then for i from 2 by 1 upto CharsLen(pretend(&pattern,*char))-1 do if pattern[i-1]='*' then doerror("illegal pattern specifier"); err:=true; fi; od; fi; for i from 1 by 1 upto maxfields do if dbasedefn.spec[i].size>0 then CharsCopy(pretend(&tempstr,*char),pretend(&dbasedefn.spec[i].fieldname,*char)); if find(pretend(&sfieldname,*char),pretend(&tempstr,*char)) then matchd:=true; fieldnum:=i; fi; fi; od; if not matchd then doerror("bad fieldname"); err:=true; fi; if dataindex.curlev=maxsels then doerror("selection levels full, select abandoned"); err:=true; fi; if not err then nummatchd:=0; for i from 1 by 1 upto dataindex.maxrecnum do if dataindex.level[dataindex.curlev].map[i]=false then dataindex.level[dataindex.curlev+1].map[i]:=false; else getrecord(i); CharsCopy(pretend(&tempstr,*char),pretend(&currec[fieldnum],*char)); if not find(pretend(&pattern,*char),pretend(&tempstr,*char)) then dataindex.level[dataindex.curlev+1].map[i]:=true; nummatchd:=nummatchd+1; else dataindex.level[dataindex.curlev+1].map[i]:=false; fi; fi; od; dataindex.curlev:=dataindex.curlev+1; CharsCopy(pretend(&tempstr,*char),"exclude "); CharsConcat(pretend(&tempstr,*char),pretend(&pattern,*char)); CharsConcat(pretend(&tempstr,*char)," on "); CharsConcat(pretend(&tempstr,*char),pretend(&sfieldname,*char)); CharsCopy(pretend(&dataindex.level[dataindex.curlev].indexname,*char),pretend(&tempstr,*char)); dataindex.level[dataindex.curlev].numonlev:=nummatchd; if nummatchd=0 then doerror("level empty ... exclude abandoned"); dataindex.curlev:=dataindex.curlev-1; else gotofirst(); fi; fi; corp; proc include(*char f,p) void: /* carries out include op on database */ bool err,matchd; uint i,fieldnum,nummatchd; string tempstr,sfieldname,pattern; CharsCopy(pretend(&sfieldname,*char),f); CharsCopy(pretend(&pattern,*char),p); err:=false; matchd:=false; if CharsLen(pretend(&pattern,*char))>1 then for i from 2 by 1 upto CharsLen(pretend(&pattern,*char))-1 do if pattern[i-1]='*' then doerror("illegal pattern specifier"); err:=true; fi; od; fi; for i from 1 by 1 upto maxfields do if dbasedefn.spec[i].size>0 then CharsCopy(pretend(&tempstr,*char),pretend(&dbasedefn.spec[i].fieldname,*char)); if find(pretend(&sfieldname,*char),pretend(&tempstr,*char)) then matchd:=true; fieldnum:=i; fi; fi; od; if not matchd then doerror("bad fieldname"); err:=true; fi; if dataindex.curlev=maxsels then doerror("selection levels full, select abandoned"); err:=true; fi; if not err then nummatchd:=0; for i from 1 by 1 upto dataindex.maxrecnum do if dataindex.level[dataindex.curlev].map[i]=true then dataindex.level[dataindex.curlev+1].map[i]:=true; nummatchd:=nummatchd+1; else getrecord(i); CharsCopy(pretend(&tempstr,*char),pretend(&currec[fieldnum],*char)); if find(pretend(&pattern,*char),pretend(&tempstr,*char)) then dataindex.level[dataindex.curlev+1].map[i]:=true; nummatchd:=nummatchd+1; else dataindex.level[dataindex.curlev+1].map[i]:=false; fi; fi; od; dataindex.curlev:=dataindex.curlev+1; CharsCopy(pretend(&tempstr,*char),"include "); CharsConcat(pretend(&tempstr,*char),pretend(&pattern,*char)); CharsConcat(pretend(&tempstr,*char)," on "); CharsConcat(pretend(&tempstr,*char),pretend(&sfieldname,*char)); CharsCopy(pretend(&dataindex.level[dataindex.curlev].indexname,*char),pretend(&tempstr,*char)); dataindex.level[dataindex.curlev].numonlev:=nummatchd; if nummatchd=0 then doerror("level empty ... include abandoned"); dataindex.curlev:=dataindex.curlev-1; else gotofirst(); fi; fi; corp; proc clear() void: /*clear selections back to global level*/ dataindex.curlev:=1; gotofirst(); corp; proc back() void: /* moves backup one level, cant move past global level */ if dataindex.curlev>1 then dataindex.curlev:=dataindex.curlev-1; fi; gotofirst(); corp; proc history() void: /* display curreent selection history on screen */ uint i,j; string s; clearrecwind(); i:=1; j:=1; while i<=dataindex.curlev do gotoxy(1,j); writeln(crtout;"Level ",i," ",dataindex.level[i].indexname); i:=i+1; j:=j+1; if j>dwindsize then doerror("press a key to continue"); clearrecwind(); j:=1; fi; od; doerror("press a key to continue"); clearrecwind(); corp; proc setupdumm(*char s,fill) void: /* setup a blank record with s at beginning each field and filler fill*/ uint a,b; string t; CharsCopy(pretend(&t,*char),s); for a from 1 by 1 upto maxfields do CharsCopy(pretend(&currec[a],*char),pretend(&t,*char)); for b from CharsLen(pretend(&currec[a],*char))+1 by 1 upto dbasedefn.spec[a].size do CharsConcat(pretend(&currec[a],*char),fill); od; od; corp; proc main() void: /* front end */ initscreen(); quit:=false; filopnd:=false; clearscr(); printstrbox(27,1,80,1," File-It v1.0"); printstrbox(27,3,80,3,"A personal filing system"); printstrbox(27,5,80,5," Written by J Davis"); printstrbox(27,7,80,7," John Davis"); printstrbox(27,9,80,9," 1988"); while printstrbox(1,dwindsize+2,80,dwindsize+2,"Options --- (Q)uit (C)reate (U)use :"); response:=getchr(); if response='q' or response='Q' then quit:=true fi; if response='c' or response='C' then clearcmdwind(); printstrbox(1,dwindsize+2,80,dwindsize+2,"Enter database name :"); readstr(pretend(&rootname,*char),filenamelen); setupdefn(); initfiles(); filopnd:=true; fi; if response='u' or response='U' then clearcmdwind(); printstrbox(1,dwindsize+2,80,dwindsize+2,"Enter database name :"); readstr(pretend(&rootname,*char),filenamelen); initfiles(); filopnd:=true; gotofirst(); fi; not(quit or filopnd) do od; clearscr(); while not quit do clearcmdwind(); clearstatwind(); if dataindex.level[dataindex.curlev].map[dataindex.currecnum] then displayrec(); fi; gotoxy(1,dwindsize+1); writeln(crtout;"Record=",dataindex.currecnum," Level=",dataindex.curlev," ",dataindex.level[dataindex.curlev].numonlev," records selected out of ",dataindex.maxrecnum-dataindex.numdeletes); printstrbox(1,dwindsize+2,80,dwindsize+2,"OPTIONS :- (Q)uit (M)odify (D)elete (A)dd (N)ext (P)revious (F)irst (O)utput"); printstrbox(1,dwindsize+3,80,dwindsize+3," (L)ast (S)elect (I)nclude (E)xclude (H)istory (B)ack (T)oplevel "); response:=getchr(); if response='q' or response='Q' then saveindx(); close(curdatfilout); close(curdatfilin); quit:=true; fi; if response='m' or response='M' then if dataindex.level[dataindex.curlev].map[dataindex.currecnum] then editrecord(); putrecord(dataindex.currecnum); else doerror("error .. no records selected, cant modify"); fi; fi; if response='d' or response='D' then if dataindex.level[dataindex.curlev].map[dataindex.currecnum] then deleterecord(); else doerror("error delete ... no records selected"); fi; fi; if response='a' or response='A' then setupdumm(""," "); editrecord(); addrecord(); fi; if response='n' or response='N' then gotonextrecord(); fi; if response='p' or response='P' then gotoprevrecord(); fi; if response='f' or response='F' then gotofirst(); fi; if response='L' or response='l' then gotolast(); fi; if response='s' or response='S' then clearcmdwind(); printstrbox(1,dwindsize+2,80,dwindsize+2,"SELECT .. enter fieldname : "); readstr(pretend(&fnm,*char),fieldnamesize); printstrbox(1,dwindsize+3,80,dwindsize+3," enter pattern : "); readstr(pretend(&ptrn,*char),40); select(pretend(&fnm,*char),pretend(&ptrn,*char)); fi; if response='i' or response='I' then clearcmdwind(); printstrbox(1,dwindsize+2,80,dwindsize+2,"INCLUDE .. enter fieldname : "); readstr(pretend(&fnm,*char),fieldnamesize); printstrbox(1,dwindsize+3,80,dwindsize+3," enter pattern : "); readstr(pretend(&ptrn,*char),40); include(pretend(&fnm,*char),pretend(&ptrn,*char)); fi; if response='e' or response='E' then clearcmdwind(); printstrbox(1,dwindsize+2,80,dwindsize+2,"EXCLUDE .. enter fieldname : "); readstr(pretend(&fnm,*char),fieldnamesize); printstrbox(1,dwindsize+3,80,dwindsize+3," enter pattern : "); readstr(pretend(&ptrn,*char),40); exclude(pretend(&fnm,*char),pretend(&ptrn,*char)); fi; if response='h' or response='H' then history(); fi; if response='b' or response='B' then back(); fi; if response='t' or response='T' then clear(); fi; if response='o' or response='O' then clearcmdwind(); printstrbox(1,dwindsize+2,80,dwindsize+2,"enter name of output file : "); readstr(pretend(&filnm,*char),filenamelen); outlevel(pretend(&filnm,*char)); fi; od; closescreen(); corp;