home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-08-31 | 53.5 KB | 1,997 lines |
- OPT OSVERSION=37,LARGE
-
- MODULE 'dos/var', 'utility/tagitem' , 'icon', 'intuition/intuition'
- MODULE 'dos/datetime', 'workbench/startup', 'reqtools' , 'dos/dosasl'
- MODULE 'dos/dos', 'workbench/workbench', 'dos/rdargs', 'dos/dostags'
- MODULE 'libraries/reqtools'
-
- ENUM IN_FILE=0, OUT_FILE, LIST_IN_FILE, LIST_OUT_FILE, QUIPDELAY,
- FPREFIX, FSUFFIX, FFORMAT, MIDDLE, FMIDDLE,
- PREFIX, SUFFIX, LIST_PREFIX, LIST_SUFFIX, LIST_SCRIPT,
- HOWMANY, RANDOM, SERIAL, WHICHQUIP, FORMAT, QRESET, QREQ,
- LIST_FORMAT, MAKETABLE, DISPLAY, MAKE_QUIPS, BADCOMMAND,
- DONOTHING, GOTO, LIST_GOTO, SCRIPT, CHANCE, LIST_CHANCE,
- UPDATE, LIST_ERROR, ERROR, BADCOMWRITE, LIST_RUN, RUN,
- LIST_FSUFFIX, LIST_FPREFIX, LIST_FFORMAT,
- LIST_FMIDDLE, LIST_MIDDLE, FINISHED
- ENUM QTAG_INFILENAME=0, QTAG_OUTFILENAME, QTAG_NUMQUIPS,
- QTAG_RANDOM, QTAG_SERIAL, QTAG_RUN, QTAG_FPREFIX, QTAG_FSUFFIX,
- QTAG_PREFIX, QTAG_SUFFIX, QTAG_REQUSE, QTAG_DELAY,
- QTAG_WHICHQUIP, QTAG_FORMAT, QTAG_FFORMAT, QTAG_GENQTABLE,
- QTAG_END, QTAG_DISPLAY, QTAG_VERSION, QTAG_RESET,
- QTAG_UPDATE, QTAG_STDOUT, QTAG_STDERR, QTAG_MIDDLE, QTAG_FMIDDLE
- ENUM QERR_BADFILE=1, QERR_BADIFILE, QERR_RUNERR, QERR_FPREFIX,
- QERR_FSUFFIX, QERR_FMIDDLE, QERR_FFORMAT,
- QERR_BADOFILE, QERR_BADTFILE, QERR_BADSFILE
- ENUM ARG_VERSION=0, ARG_MOO, ARG_COL, ARG_DATAFILE, ARG_TABLE, ARG_RUN,
- ARG_FFORMAT, ARG_FORMAT, ARG_PRE, ARG_FPRE, ARG_SUF, ARG_FSUF, ARG_WHERE, ARG_RANDOM,
- ARG_ERROR, ARG_MIDDLE, ARG_FMIDDLE, ARG_STDIO,
- ARG_REQ, ARG_DELAY, ARG_NUM, ARG_UPDATE, ARG_FILES, ARG_SCRIPT,
- ARG_MAX
-
- RAISE "MEM" IF New()=NIL, /* set common exceptions: */
- "MEM" IF String()=NIL, /* every call to these functions will be */
- "MEM" IF List()=NIL, /* automatically checked against NIL, */
- "^C" IF CtrlC()=TRUE /* and the exception "MEM" is raised */
-
- DEF efilename=0,estate=0,efile=0 /* nasty nasty global vars. I hate 'em */
-
- /* openerr()
- *
- * This proc opens up an alternative file, appending error messages to it.
- * Just in case really CLEAN quips are wanted. If no filename is specified,
- * or an error occurs, openerr returns stdout. It's up to the calling function
- * to close efile (testing that efile isn't stdout first)
- */
-
- PROC openerr()
- DEF dt:datetime
- IF efile THEN RETURN
- IF efilename
- DateStamp(dt.stamp)
- dt.format:=FORMAT_DOS /* set datetime options */
- dt.flags:=0
- dt.strday:=String(11)
- dt.strdate:=String(11)
- dt.strtime:=String(11)
- DateToStr(dt) /* make into string */
- IF efile:=Open(efilename,MODE_READWRITE)
- Seek(efile,0,OFFSET_END)
- ENDIF
- VfPrintf(efile,'\nQuip: \s | \s | \s\n\n',[dt.strday,dt.strdate,dt.strtime])
- Flush(efile)
- ELSEIF wbmessage /* if called from icon */
- WriteF('')
- efile:=stdout
- ELSE
- efile:=Open('CONSOLE:',NEWFILE) /* for stderr activity on CLI call */
- ENDIF
- IF efile=0
- efile:=stdout
- ENDIF
- ENDPROC
-
- /* fwriteerr()
- *
- * Here's a way to write errors without having to open a window until we
- * absolutely HAVE to.
- */
-
- PROC fwriteerr(format,items)
-
- IF efilename=0
- WriteF('') /* this opens a window for WB users */
- ENDIF
- openerr() /* make sure stderr is open */
- IF items
- VfPrintf(efile,format,items)
- Flush(efile)
- ELSE
- Fputs(efile,format)
- Flush(efile)
- ENDIF
- IF wbmessage
- estate:=1 /* to set "close window" text in main() */
- ENDIF
- ENDPROC
-
- /* getprogramicon()
- *
- * This fun little proc is supposed to return a diskobject so you can play
- * with the ToolTypes. It expects a WBPROJECT icon first, then a WBTOOL
- * icon next. It locks the icon's directory, unlocking it when it's done.
- * All-in-all, pretty cool. Mostly based on Term's icon handling, but
- * heavily modified to fit in with my own nefarious purposes (brew ha ha).
- */
-
- PROC getprogramicon(wbmessage)
- DEF diskob:PTR TO diskobject,tmp:PTR TO wbarg,newlock,
- wbmsg:PTR TO wbstartup
- diskob:=0; wbmsg:=0
- IF wbmessage
- wbmsg:=wbmessage
- IF tmp:=wbmsg.arglist
- IF tmp.name++
- newlock:=CurrentDir(tmp.lock) /* set the current directory to */
- IF diskob:=GetDiskObjectNew(tmp.name) /* the icon's directory, to read */
- IF diskob.type<>WBPROJECT /* the icon's tooltypes. */
- FreeDiskObject(diskob)
- diskob:=NIL
- ENDIF
- ELSE
- UnLock(tmp.lock)
- ENDIF
- IF diskob=NIL
- /* Move to the directory the
- * program was run from.
- */
- tmp.name--
- newlock:=CurrentDir(tmp.lock)
- IF diskob:=GetDiskObjectNew(tmp.name)
- IF diskob.type <> WBTOOL
- FreeDiskObject(diskob)
- diskob:=NIL
- ENDIF
- ELSE
- UnLock(tmp.lock)
- ENDIF
-
- IF diskob=0
- IF diskob:=GetDiskObjectNew('quip')
- IF diskob.type<>WBTOOL
- FreeDiskObject(diskob)
- diskob := NIL
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDIF
-
- /* Still no success. */
-
- IF diskob=0
- /* Use the default names. */
- IF diskob:=GetDiskObjectNew('Quip')
- IF diskob.type<>WBTOOL
- FreeDiskObject(diskob)
- diskob := NIL
- ENDIF
- ENDIF
-
- IF diskob=0
- IF diskob:=GetDiskObjectNew('PROGDIR:Quip')
- IF diskob.type<>WBTOOL
- FreeDiskObject(diskob)
- diskob := NIL
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- ENDPROC diskob
-
- /* stayrandom()
- *
- * I hate random number generators. They always need some kind of seed,
- * and generally that seed has to be some gigantic value or something.
- * Because of the way Quip works, if you try to use standard methods for
- * seeding random numbers (read: the clock) you'll wind up with a very
- * non-random set of quips popping up. Quite ugly. Especially for BBS
- * sysops. I figure I can create a four-byte seed value and chuck it in
- * the ENV: directory and nobody would be too concerned.
- */
-
- PROC stayrandom()
-
- DEF file,i,ds:datestamp,filename
-
- filename:='ENV:rnd'
- file:=Open(filename,OLDFILE)
- IF file=0
- DateStamp(ds)
- Rnd(-(VbeamPos()*7))
- i:=$A6F87EC1+(VbeamPos()*3)
- ELSE
- Seek(file,0,OFFSET_BEGINNING)
- Fread(file,{i},4,1)
- Close(file)
- Rnd(-(Abs(i)+VbeamPos()))
- i:=RndQ(i)
- ENDIF
- file:=Open(filename,NEWFILE)
- Seek(file,0,OFFSET_BEGINNING)
- Fwrite(file,{i},4,1)
- Close(file)
- ENDPROC
-
- /* fileend()
- *
- * I wanted a nice, consistent, easy way to handle changing the extention of
- * a filename (eg, quip.dat to quip.tab, etc.). This is it.
- */
-
- PROC fileend(filename,fappend) HANDLE
-
- DEF fname=0,f=0,found=0
-
- WHILE f<>-1
- f:=InStr(filename,'.',fname+1)
- IF f<>-1
- fname:=f
- found:=1
- ENDIF
- ENDWHILE
- IF found=1
- fname := fname + 1
- f:=String(fname+StrLen(fappend))
- StrCopy(f,filename,fname)
- StrAdd(f,fappend,ALL)
- ELSE
- f:=String(StrLen(fappend)+StrLen(filename)+1)
- StrAdd(f,filename,ALL)
- StrAdd(f,'.',ALL)
- StrAdd(f,fappend,ALL)
- ENDIF
- EXCEPT
- Raise(exception)
- ENDPROC f
-
- /* whichquip()
- *
- * This looks in a datafile and figures out which quip Quip is supposed to
- * pick up next.
- */
-
- PROC whichquip(filename) HANDLE
-
- DEF file,i,buff[13]:STRING
-
- IF (file := Open(filename,OLDFILE))=0
- Raise(QERR_BADIFILE)
- ENDIF
-
- IF (i := ReadStr(file,buff))=0
- Raise(QERR_BADIFILE)
- ENDIF
- i := Val(buff,0)
- Close (file)
- file:=0
-
- EXCEPT
-
- SELECT exception
- CASE QERR_BADIFILE
- i:=IoErr()
- fwriteerr('\n *** Couldn''t get WhichQuip number from datafile.\n',0)
- SetIoErr(i)
- ENDSELECT
-
- IF file THEN Close (file)
- i := 0
- Raise(exception)
- ENDPROC i
-
- /* bumpquip()
- *
- * Supposed to change the datafile's internal whichquip number.
- * Just a way to keep the quips serialized.
- */
-
- PROC bumpquip(filename,which) HANDLE
- DEF file
-
- IF (file := Open(filename,OLDFILE))=0
- Raise(QERR_BADIFILE)
- ENDIF
-
- IF (VfPrintf(file,'%-12ld',{which}))=-1
- Raise(QERR_BADIFILE)
- ENDIF
- Close (file)
-
- EXCEPT
-
- SELECT exception
- CASE QERR_BADIFILE
- IF file THEN Close(file)
- file:=IoErr()
- fwriteerr('\n *** Couldn''t change WhichQuip in "\s".\n',{filename})
- SetIoErr(file)
- file:=0
- ENDSELECT
-
- IF file THEN Close (file)
- Raise(exception)
- ENDPROC
-
- /* quiptable()
- *
- * Creates a new tablefile from scratch.
- */
-
- PROC quiptable(filename) HANDLE
-
- DEF hashname,dfile,hfile,foo,rpos,i=0
-
- hashname := fileend(filename,'tab')
- fwriteerr('\e[0 p\nCreating tablefile "\s".\n <- Quips in file\b',
- {hashname})
- IF (dfile := Open(filename,OLDFILE))=0
- Raise (QERR_BADIFILE)
- ENDIF
- IF (hfile := Open(hashname,NEWFILE))=0
- Raise(QERR_BADTFILE)
- ENDIF
- i:=i+1
- WHILE foo <> -1
- CtrlC()
- IF (foo:=FgetC(dfile))="@"
- rpos:=Seek(dfile,0,OFFSET_CURRENT)
- Fwrite(hfile,{rpos},4,1)
- fwriteerr('\b\d',{i})
- i:=i+1
- ENDIF
- ENDWHILE
- Close(hfile)
- Close(dfile)
- fwriteerr('\nFinished \s.\e[ p\n\n',{hashname})
-
- EXCEPT
- IF hfile THEN Close (hfile)
- IF dfile THEN Close (dfile)
- hfile:=IoErr()
- SELECT exception
- CASE QERR_BADTFILE; fwriteerr('\n\e[ p *** Couldn''t open tablefile.\n',0)
- CASE QERR_BADIFILE; fwriteerr('\n\e[ p *** Datafile won''t open to allow tablefile to be made.\n',0)
- ENDSELECT
- SetIoErr(hfile)
- Raise(exception)
- ENDPROC
-
- /* delimit()
- *
- * Searches through a datafile and finds a "@" character. It then returns
- * with the relative position of the character-1, or a -1 if it's at the end
- * of the file.
- */
-
- PROC delimit(ifile) HANDLE
-
- DEF k,t
- t:=Seek(ifile,0,OFFSET_CURRENT)
- WHILE k <> -1
- CtrlC()
- k:=FgetC(ifile)
- IF k="@"
- t:=Seek(ifile,0,OFFSET_CURRENT)-1
- RETURN t
- ELSE
- IF k=-1
- t:=-1
- RETURN t
- ENDIF
- ENDIF
- ENDWHILE
- EXCEPT
- Raise(exception)
- ENDPROC
-
- /* updatetable()
- *
- * It's really magic. This helps keep someone from having to sift through
- * all that maketable stuff from scratch. If given a zero, it'll start from
- * the last known quip in the tablefile, and update the datafile's tablefile
- * to include any new quips that might have been put in there.
- * It can also start from some other place, if someone happened to notice
- * that the quips were warped or something, and wanted a way to re-align
- * them. Very nice.. very new (tried to put this in my old Quip program
- * but had trouble... much more luck this time).
- */
-
- PROC updatetable(ifilename,num) HANDLE
- DEF tfile=0,ifile=0,size,rpos,i,tfilename=0,hold=0
-
- tfilename:=fileend(ifilename,'tab')
- size:=FileLength(tfilename)
- IF size=-1 THEN Raise(QERR_BADTFILE)
- i:=Div(size,4)
- IF (i<num) OR (num=0)
- num:=i
- ENDIF
- hold:=New((num*4)+1)
- tfile:=Open(tfilename,OLDFILE)
- IF tfile=0 THEN Raise(QERR_BADTFILE)
- Seek(tfile,0,OFFSET_BEGINNING)
- Fread(tfile,hold,num*4,1)
- Close(tfile)
- tfile:=Open(tfilename,NEWFILE)
- IF tfile=0 THEN Raise(QERR_BADTFILE)
- Fwrite(tfile,hold,num*4,1)
- Seek(tfile,-4,OFFSET_CURRENT)
- Fread(tfile,{rpos},4,1)
- ifile:=Open(ifilename,OLDFILE)
- IF ifile=0 THEN Raise(QERR_BADIFILE)
- Seek(ifile,rpos+1,OFFSET_BEGINNING)
- fwriteerr('\e[0 pUpdating \s:\n\d <- Quips in file\b',[tfilename,num])
- LOOP
- CtrlC()
- rpos:=delimit(ifile)
- IF rpos=-1 THEN Raise("OK")
- rpos:=rpos+1
- num:=num+1
- fwriteerr('\d\b',{num})
- Fwrite(tfile,{rpos},4,1)
- Seek(ifile,2,OFFSET_CURRENT)
- ENDLOOP
- EXCEPT
- IF ifile THEN Close(ifile)
- IF tfile THEN Close(tfile)
- IF hold THEN Dispose(hold)
- IF tfilename THEN Dispose(tfilename)
- ifile:=IoErr()
- SELECT exception
- CASE "OK"
- fwriteerr('\n\e[ pFinished.\n\n',0)
- RETURN
- CASE "^C"
- DEFAULT
- fwriteerr('\n¡Error while updating tablefile:',0)
- ENDSELECT
- fwriteerr('\n\e[ p',0)
- SetIoErr(ifile)
- Raise(exception)
- ENDPROC
-
- /* textfileget()
- *
- * This gets the text within a file and puts it in a string.
- */
-
- PROC textfileget(filename) HANDLE
- DEF file,text=0,i
-
- i:=FileLength(filename)
- file:=Open(filename,OLDFILE)
- IF file=0 THEN RETURN 0
- text:=String(i+1)
- IF Fread(file,text,i,1)<1
- Close(file)
- Dispose(text)
- RETURN 0
- ENDIF
- Close(file)
- EXCEPT
- Raise(exception)
- ENDPROC text
-
- /* findquip()
- *
- * This is a biggie...
- * This proc processes the tags given to it, handling various settings and
- * stuff (much like QuipScript, except with much fewer options <grin>).
- * This is the routine that actually FINDS the various quips. It takes all
- * the other procedures above and USES them to its advantage. This process
- * will eat your brain.
- */
-
- PROC findquip(tags) HANDLE
-
- DEF ofile=0,rnd=0,h,i,j,k,pre=0,suf=0,howmany=1,ofilename=0,ifilename,
- tagnum,qprompt=0,whichq=0,tfile=0,rndmax,squip,equip,quip,num[13]:STRING,
- display=0,programmer,version,ifile=0,reqtags,requse=0,dornd=0,
- hinfo:PTR TO rthandlerinfo,waitval=900000,runcom=0,middle=0
-
- programmer:='jvanriper@uncavx.unca.edu' /* set the programmer */
- version:='$VER: Quip 0.705 (1.9.93)'
- ifilename:='S:Quip.dat'
- /* A VERSION string! And to proper standards! Sorta..*/
-
- /* Now we're ready to process the tags...*/
- FOR i:=0 TO ListLen(tags)-1
- CtrlC()
- tagnum:=ListItem(tags,i)
- SELECT tagnum
-
- CASE QTAG_REQUSE /* if tag says we want to use reqtool.library...*/
- requse:=1
-
- CASE QTAG_INFILENAME /* What filename are we getting quips from? */
- i:=i+1
- ifilename:=ListItem(tags,i)
-
- CASE QTAG_RESET /* re-initialize all the data to default values */
- rnd:=0
- dornd:=0
- display:=0
- rndmax:=0
- howmany:=1
- ofilename:=0
- IF qprompt THEN Dispose(qprompt)
- qprompt:=0
- ifilename:=0
- IF pre THEN Dispose(pre)
- IF suf THEN Dispose(suf)
- pre:=0; suf:=0
- tfile:=0
- ofilename:=0
- ifilename:='S:Quip.dat'
- whichq:=0
- IF ifile THEN Close(ifile)
- IF ofile THEN Close(ofile)
- ifile:=0
- ofile:=0
- IF tfile THEN Close(tfile)
- tfile:=0
- requse:=0
- waitval:=900000
- runcom:=0
- IF middle THEN Dispose(middle)
-
- CASE QTAG_OUTFILENAME /* If tags says we have to make files...*/
- i:=i+1
- ofilename:=ListItem(tags,i)
-
- CASE QTAG_RUN
- i:=i+1
- runcom:=ListItem(tags,i)
- runcom:=addstrings(runcom,' env:quip.tmp')
-
- CASE QTAG_DELAY /* Sets the delay count for reqtools.library, and says requesters are needed */
- i:=i+1
- waitval:=ListItem(tags,i)
- requse:=1
-
- CASE QTAG_NUMQUIPS /* How many quips do we want? */
- i:=i+1
- howmany:=ListItem(tags,i)
-
- CASE QTAG_RANDOM /* Are we doing random quips? If so, do we have tablefile? */
- dornd:=1
- rndmax:=Div(FileLength(fileend(ifilename,'tab')),4)-1
- IF rndmax<0
- rndmax:=0
- rnd:=FileLength(ifilename)
- ELSE
- rnd:=Rnd(rndmax)+1
- ENDIF
-
- CASE QTAG_SERIAL /* Ixnay on the Andomray....*/
- rnd:=0
- rndmax:=0
-
- CASE QTAG_PREFIX /* We want a prefix */
- i:=i+1
- pre:=modformat(ListItem(tags,i))
-
- CASE QTAG_FPREFIX /* Get prefix from file */
- i:=i+1
- IF pre THEN Dispose(pre)
- pre:=textfileget(ListItem(tags,i))
- IF pre
- pre:=modformat(pre)
- ELSE
- pre:=IoErr()
- fwriteerr('¡Bad prefix file: "\s"!\n',[ListItem(tags,i)])
- SetIoErr(pre)
- pre:=0
- Raise(QERR_FPREFIX)
- ENDIF
-
- CASE QTAG_MIDDLE /* We want to stuff junk between numbered quips */
- i:=i+1
- middle:=modformat(ListItem(tags,i))
-
- CASE QTAG_FMIDDLE /* Get middle from file */
- i:=i+1
- IF middle THEN Dispose(middle)
- middle:=textfileget(ListItem(tags,i))
- IF middle
- middle:=modformat(middle)
- ELSE
- middle:=IoErr()
- fwriteerr('¡Bad middle file: "\s"!\n',[ListItem(tags,i)])
- SetIoErr(middle)
- middle:=0
- Raise(QERR_FMIDDLE)
- ENDIF
-
- CASE QTAG_STDOUT
- i:=i+1
- WriteF(ListItem(tags,i))
- Dispose(ListItem(tags,i))
-
- CASE QTAG_STDERR
- i:=i+1
- fwriteerr(ListItem(tags,i),0)
- Dispose(ListItem(tags,i))
-
- CASE QTAG_SUFFIX /* We want a suffix file */
- i:=i+1
- suf:=modformat(ListItem(tags,i))
-
- CASE QTAG_FSUFFIX /* Get suffix from file */
- i:=i+1
- IF suf THEN Dispose(suf)
- suf:=textfileget(ListItem(tags,i))
- IF suf
- suf:=modformat(suf)
- ELSE
- suf:=IoErr()
- fwriteerr('¡Bad suffix file: "\s"!\n',[ListItem(tags,i)])
- SetIoErr(suf)
- suf:=0
- Raise(QERR_FSUFFIX)
- ENDIF
-
- CASE QTAG_UPDATE /* We want to update our tablefile */
- i:=i+1
- updatetable(ifilename,ListItem(tags,i))
-
- CASE QTAG_WHICHQUIP /* Which quip do we want to start from? */
- i:=i+1
- whichq:=ListItem(tags,i)
-
- CASE QTAG_FFORMAT /* Get format from file */
- i:=i+1
- qprompt:=textfileget(ListItem(tags,i))
- IF qprompt
- qprompt:=modformat(qprompt)
- ELSE
- qprompt:=IoErr()
- fwriteerr('¡Bad format file: "\s"!\n',[ListItem(tags,i)])
- SetIoErr(qprompt)
- qprompt:=0
- Raise(QERR_FFORMAT)
- ENDIF
-
-
- CASE QTAG_FORMAT /* The quip will be preceded with some formatted stuff */
- i:=i+1
- qprompt:=modformat(ListItem(tags,i))
-
- CASE QTAG_GENQTABLE /* make a tablefile from scratch */
- quiptable(ifilename)
-
- CASE QTAG_END /* The monster. Now we must make quips.*/
- IF (dornd=0) AND (whichq=0) THEN whichq:=whichquip(ifilename)
- /* If we aren't doing this randomly, and we haven't picked a quip,
- * we need to decide which quip we want to show.
- */
- IF howmany=0 THEN howmany:=1 /* just in case...*/
- tfile:=Open(fileend(ifilename,'tab'),OLDFILE)
- IF tfile<>0 /* we have tablefile.. now let's get the rpos of a quip! */
- IF (dornd) AND (whichq=0) /* make sure random stuff works on first one */
- whichq:=Rnd(rndmax)+1
- ENDIF
- IF Div(FileLength(fileend(ifilename,'tab')),4)<(whichq)
- whichq:=Div(FileLength(fileend(ifilename,'tab')),4)
- ENDIF
- Seek(tfile,(whichq-1)*4,OFFSET_BEGINNING)
- Fread(tfile,{squip},4,1)
- Seek(tfile,0,OFFSET_BEGINNING)
- ELSEIF (dornd) AND (whichq=0) /* no tablefile, random. */
- k:=-1
- ifile:=Open(ifilename,OLDFILE)
- IF ifile=0 THEN Raise(QERR_BADIFILE)
- WHILE k=-1
- CtrlC()
- Seek(ifile,Rnd(FileLength(ifilename)),OFFSET_BEGINNING)
- k:=delimit(ifile)
- ENDWHILE
- squip:=k+1
- Seek(ifile,2,OFFSET_CURRENT)
- ELSE /* no tablefile, and serial... phew */
- ifile:=Open(ifilename,MODE_OLDFILE)
- fwriteerr('\e[0 pFound Quip #:\n',0) /* turn off the cursor */
- FOR j:=1 TO whichq
- CtrlC()
- k:=delimit(ifile)
- IF k<>-1
- fwriteerr('\d\b',{j})
- squip:=k+1
- ELSE
- j:=whichq
- whichq:=1
- Seek(ifile,0,OFFSET_BEGINNING)
- k:=delimit(ifile)
- IF k<>-1
- fwriteerr('1\b',0)
- squip:=k+1
- ELSE
- Raise(QERR_BADIFILE)
- ENDIF
- ENDIF
- ENDFOR
- fwriteerr('\e[ p\n',0) /* turn on the cursor */
- ENDIF
- IF ifile=0 /* If, after all the above, we somehow managed to get away
- without opening the incoming file...*/
- ifile:=Open(ifilename,MODE_OLDFILE)
- IF ifile=0 THEN Raise(QERR_BADIFILE)
- Seek(ifile,squip+1,OFFSET_BEGINNING)
- ENDIF
- equip:=delimit(ifile) /* we've already found the start, where's the end?*/
- FOR j:=1 TO howmany /* Now we process quips until NUM is satisfied. */
- CtrlC()
- IF equip=-1 THEN equip:=FileLength(ifilename) /* the end goes to EOF, so..*/
- quip:=New(equip-squip+1)
- Seek(ifile,squip,OFFSET_BEGINNING) /*find quip..*/
- h:=Fread(ifile,quip,equip-squip,1) /*get quip..*/
- IF h<1 THEN Raise(QERR_BADIFILE)
- IF ofilename /* if writing to files...*/
- StringF(num,'\d',j-1)
- IF (ofile:=Open(fileend(ofilename,num),NEWFILE))=0
- Raise (QERR_BADOFILE)
- ENDIF
- IF pre<>0 THEN Fputs(ofile,pre)
- IF qprompt<>0 THEN VfPrintf(ofile,qprompt,{whichq})
- Fputs(ofile,quip)
- IF suf<>0 THEN Fputs(ofile,suf)
- Close(ofile)
- ofile:=0
- ENDIF
- IF runcom /* if we're running a command.. */
- requse:=0
- IF pre THEN requse:=addstrings(requse,pre)
- IF qprompt
- h:=String(StrLen(qprompt)+13)
- StringF(h,qprompt,whichq)
- requse:=addstrings(requse,h)
- Dispose(h)
- ENDIF
- requse:=addstrings(requse,quip)
- IF suf THEN requse:=addstrings(requse,suf)
- ofile:=Open('env:quip.tmp',NEWFILE)
- IF ofile
- Fputs(ofile,requse)
- Close(ofile)
- Dispose(requse)
- ofile:=0
- requse:=0
- IF wbmessage
- requse:=Open('CON:',NEWFILE)
- ofile:=SystemTagList(runcom,[SYS_INPUT,requse,SYS_OUTPUT,requse])
- Close(requse)
- requse:=0
- ELSE
- ofile:=SystemTagList(runcom,[SYS_USERSHELL])
- ENDIF
- DeleteFile('env:quip.tmp')
- IF ofile
- ofile:=0
- Raise(QERR_RUNERR)
- ENDIF
- requse:=0
- ELSE
- fwriteerr('Quip: unable to open tmp file\n',0)
- ENDIF
- ELSEIF (display AND (requse=0)) OR ((ofilename=0) AND (requse=0))
- IF pre<>0 THEN WriteF(pre); Flush(stdout)
- IF qprompt<>0 THEN WriteF(qprompt,whichq); Flush(stdout)
- WriteF(quip)
- IF suf<>0 THEN WriteF(suf)
- ELSEIF requse AND (ofilename=0) /* well, maybe requesters, then*/
- requse:=0 /* we're going to use requse for stuff*/
- requse:=addstrings(requse,pre) /* here we have to put the quip*/
- requse:=addstrings(requse,quip)
- requse:=addstrings(requse,suf) /* in one string..*/
- IF qprompt
- h:=String(StrLen(qprompt)+13)
- StringF(h,qprompt,whichq)
- ELSE
- h:='Quip'
- ENDIF
- reqtoolsbase:=OpenLibrary('reqtools.library',0) /* opening library */
- IF reqtoolsbase /* Note: putting FORMAT in title of requester*/
- reqtags:=[RTEZ_REQTITLE,h,RT_REQHANDLER,{hinfo},TAG_DONE]
- /* reqtools.library stuff... needed for asynchronous info-reqs */
- ofile:=requse
- requse:=RtEZRequestA(ofile,'Ok',0,0,reqtags) /* asynch reqs*/
- IF requse=CALL_HANDLER /* so, CALL_H.*/
- k:=0
- WHILE (requse=CALL_HANDLER)
- Delay(5) /*1/10th second*/
- requse:=RtReqHandlerA(hinfo,i,[TAG_DONE])
- IF k++=waitval /*done yet?*/
- requse:=RtReqHandlerA(hinfo,i,[RTRH_ENDREQUEST,TAG_DONE])
- IF StrCmp(h,'Quip',ALL)=FALSE /* Dispose of FORMAT (be neat) */
- Dispose(h)
- ENDIF
- ENDIF
- ENDWHILE
- ELSE
- fwriteerr('Couldn''t asynchronously open reqtools.library.\n\n',0)
- WriteF(ofilename)
- ENDIF
- CloseLibrary(reqtoolsbase)
- ELSE
- fwriteerr('Couldn''t open reqtools.library.\n',0)
- ENDIF
- requse:=1 /* since we used requse, we must reset it*/
- Dispose(ofile) /* more cleanup*/
- ofile:=0
- ENDIF
- Dispose(quip) /* now we must find next quip */
- quip:=0
- IF middle AND (j<>howmany) /* oh yeah. We need to write the middle */
- WriteF('\s',middle)
- ENDIF
- IF (dornd) AND (tfile)/* if we're random with tablefiles..*/
- whichq:=Rnd(rndmax)+1
- Seek(tfile,(whichq-1)*4,OFFSET_BEGINNING)
- Fread(tfile,{squip},4,1)
- Seek(ifile,squip,OFFSET_BEGINNING)
- ELSEIF (dornd) AND (tfile=0) /* random, but no tablefiles... */
- k:=-1
- whichq:=0 /* Nullify whichq, since it has no purpose*/
- WHILE k=-1
- CtrlC()
- Seek(ifile,Rnd(FileLength(ifilename)),OFFSET_BEGINNING)
- k:=delimit(ifile)
- ENDWHILE
- squip:=k+1
- ELSE
- squip:=equip+1
- whichq:=whichq+1
- IF squip>=FileLength(ifilename)
- Seek(ifile,0,OFFSET_BEGINNING)
- squip:=delimit(ifile)
- whichq:=1
- ENDIF
- equip:=delimit(ifile)
- ENDIF /* now let's find end of quip */
- equip:=delimit(ifile)
- ENDFOR /* process next quip, or quit */
- IF quip <> 0 /* QTAG_END is finished.. need to cleanup*/
- Dispose(quip)
- quip:=0
- ENDIF
- IF ifile <> 0
- Close(ifile)
- ifile:=0
- ENDIF
- IF tfile <> 0
- Close(tfile)
- tfile:=0
- ENDIF
- IF ofile <> 0
- Close(ofile)
- ofile:=0
- ENDIF
- IF dornd=0 /* if serially handling quips, update whichquip count */
- bumpquip(ifilename,whichq)
- ENDIF
-
- CASE QTAG_DISPLAY /* quips are to be displayed */
- display:=1
-
- CASE QTAG_VERSION /* show the version string */
- WriteF('\n')
- WriteF(version)
- WriteF('\n')
-
- DEFAULT /* this should never happen, but if you make a mistake..*/
- IF ifile THEN Close(ifile)
- ifile:=ListItem(tags,i)
- fwriteerr('\n¡Internal Error: findquip()!\n',0)
- ifile:=0
-
- ENDSELECT
- ENDFOR
-
- EXCEPT /* errors? */
- IF ifile THEN Close(ifile)
- IF ofile THEN Close(ofile)
- IF tfile THEN Close(tfile)
- IF reqtoolsbase THEN CloseLibrary(reqtoolsbase)
- ifile:=IoErr()
- SELECT exception
- CASE QERR_BADIFILE
- fwriteerr('\nBad datafile: "\s"\n',{ifilename})
- CASE QERR_BADTFILE
- ofile:=fileend(ifilename,'tab')
- fwriteerr('\nBad tablefile: "\s"\n',{ofile})
- CASE QERR_BADOFILE
- fwriteerr('\nBad outfile: "\s"\n', {ofilename})
- CASE QERR_RUNERR
- fwriteerr('\nCommand returned with error: "\s"\n',{runcom})
- ENDSELECT
- SetIoErr(ifile)
- Raise(exception)
- ENDPROC
-
- /* updatetags()
- *
- * This proc adds new items to a list.
- */
-
- PROC updatetags(tag,it) HANDLE
- DEF tmp=0
- IF tag<>0
- tmp:=List(ListLen(tag)+ListLen(it)+1)
- ListAdd(tmp,tag,ALL)
- DisposeLink(tag)
- ELSE
- tmp:=List(ListLen(it))
- ENDIF
- ListAdd(tmp,it,ALL)
- EXCEPT
- Raise(exception)
- ENDPROC tmp
-
- /* addstrings()
- *
- * This allows the second string to be added to the end of another string
- * without worrying about memory problems and truncation.
- */
-
- PROC addstrings(a,b) HANDLE
- DEF tmp=0
-
- IF a /* talk about anal retention...*/
- IF b
- tmp:=String(StrLen(a)+StrLen(b))
- ELSE
- tmp:=String(StrLen(a))
- ENDIF
- ELSEIF b
- tmp:=String(StrLen(b))
- ENDIF
- IF a
- StrAdd(tmp,a,ALL)
- Dispose(a)
- ENDIF
- IF b
- StrAdd(tmp,b,ALL)
- ENDIF
- RETURN tmp
-
- EXCEPT
- Raise(exception)
- ENDPROC tmp
-
- /* addchar()
- *
- * This really sucks... I had to create some way to add a character to the
- * end of a string. This should do it (I hope).
- */
-
- PROC addchar(line,in)
- DEF tmp=0,i
-
- IF in
- tmp:=String(StrLen(line)+2)
- StrAdd(tmp,line,ALL)
- i:=StrLen(tmp)
- tmp[i]:=in
- SetStr(tmp,i+20)
- Dispose(line)
- RETURN tmp
- ELSE
- tmp:=line
- ENDIF
- ENDPROC tmp
-
- /* modformat()
- *
- * This does some simple formatting for pre/suf/format texts. Actually,
- * the formatting isn't all THAT simple, as it allows for environment
- * variables, time and date insertion, and other stuff. Really nice.
- * I need to make it handle larger texts, though. Limited to about 200
- * chars.
- */
-
- PROC modformat(line) HANDLE
- DEF i,j,k,c,tmp,dt:datetime,ch,st
-
- tmp:=String(StrLen(line))
- FOR i:=0 TO StrLen(line)
- CtrlC()
- ch:=line[i]
- SELECT ch
- CASE "{" /* if we have a {} construct...*/
- DateStamp(dt.stamp) /* get the date/time */
- dt.format:=FORMAT_DOS /* set datetime options */
- dt.flags:=0
- dt.strday:=String(11)
- dt.strdate:=String(11)
- dt.strtime:=String(11)
- DateToStr(dt) /* make into string */
- st:=String(StrLen(tmp))
- c:=String(81)
- st:=addstrings(st,tmp)
- j:=i+1
- k:=InStr(line,'}',j) /* can we find a '}' character?*/
- IF k=-1 /* nope.. best use EOS (sorta) */
- k:=StrLen(line)-1
- ENDIF
- MidStr(c,line,j,k-j)
- i:=i+StrLen(c)+1
- j:=StrLen(tmp)
- IF StrCmp(c,'day',ALL) /* determining {} value */
- addstrings(st,dt.strday)
- ELSEIF StrCmp(c,'date',ALL)
- st:=addstrings(st,dt.strdate)
- ELSEIF StrCmp(c,'idate',ALL)
- dt.format:=FORMAT_INT
- DateToStr(dt)
- st:=addstrings(st,dt.strdate)
- ELSEIF StrCmp(c,'adate',ALL)
- dt.format:=FORMAT_USA
- DateToStr(dt)
- st:=addstrings(st,dt.strdate)
- ELSEIF StrCmp(c,'cdate',ALL)
- dt.format:=FORMAT_CDN
- DateToStr(dt)
- st:=addstrings(st,dt.strdate)
- ELSEIF StrCmp(c,'time',ALL)
- st:=addstrings(st,dt.strtime)
- ELSEIF StrCmp(c,'quip',ALL)
- st:=addstrings(st,'\d')
- ELSEIF StrCmp(c,'{',ALL)
- st:=addstrings(st,'{')
- ELSE /* none of the special formats, so it's maybe environment variable*/
- j:=String(81)
- k:=GetVar(c,j,80,0)
- IF k<>-1 /* environment variable? */
- k:=IoErr()
- Dispose(j)
- j:=String(k)
- GetVar(c,j,k+1,0)
- st:=addstrings(st,j)
- Dispose(j)
- ELSE /* nope */
- fwriteerr('\nEnvironment variable "\s" not defined.\n',{c})
- Dispose(j)
- ENDIF
- ENDIF
- Dispose(tmp)
- tmp:=st
- CASE "\" /* maybe it's a formatting character */
- i:=i+1
- j:=line[i]
- SELECT j /* choose the formatting character..*/
- CASE "\"
- tmp:=addchar(tmp,"\")
- CASE "r"
- tmp:=addchar(tmp,13)
- CASE "n"
- tmp:=addchar(tmp,10)
- CASE "e"
- tmp:=addchar(tmp,27)
- CASE "g"
- tmp:=addchar(tmp,7)
- CASE "b"
- tmp:=addchar(tmp,8)
- CASE "f"
- tmp:=addchar(tmp,12)
- CASE "t"
- tmp:=addchar(tmp,9)
- DEFAULT /* don't know it.. tell user */
- fwriteerr('\n¡Can''t handle "\\\c" in format!\n',{j})
- ENDSELECT
- DEFAULT /* none of the formatting characters, so straight text */
- tmp:=addchar(tmp,ch)
- ENDSELECT
- ENDFOR
- EXCEPT
- Raise(exception)
- ENDPROC tmp
-
- /* dorandom()
- *
- * This is for readscript.. it randomly selects which line to take as an
- * option for whatever keyword is supposed to be handled randomly.
- * It returns with that line.
- */
-
- PROC dorandom(file,col) HANDLE
- DEF tag=0,buf,i=0,c,j,firstline,nextline
-
- buf:=String(col)
- firstline:=Seek(file,0,OFFSET_CURRENT) /* where ARE we? */
- LOOP
- CtrlC()
- nextline:=Seek(file,0,OFFSET_CURRENT) /* where are we now? */
- i:=i+1
- Fgets(file,buf,col) /* read in line, to be sure not end*/
- IF buf[0]=" "
- tag:=updatetags(tag,[nextline]) /* it's cool.. store nextline in list*/
- ELSEIF buf[0]="#" /* ah.. end of list! */
- Dispose(buf)
- c:=Rnd(i-1) /* select which line from list*/
- buf:=ListItem(tag,c) /* get line position, and go there*/
- Seek(file,buf,OFFSET_BEGINNING)
- c:=String(col) /* make room for line */
- Fgets(file,c,col) /* get the line */
- j:=StrLen(c)
- c[j-1]:=0 /* get rid of trailing \n */
- Seek(file,firstline,OFFSET_BEGINNING) /* now set to top, and find end */
- LOOP
- CtrlC()
- j:=FgetC(file)
- IF j=10
- j:=FgetC(file)
- IF j="#"
- FgetC(file)
- RETURN c /* found end.. return */
- ENDIF
- IF j=-1 THEN RETURN c /* hmm.. eof instead.. return */
- ENDIF
- ENDLOOP
- ELSE /* hmm.. probably bad formatting of RND list */
- fwriteerr('Warning: RND list in script may be corrupt.\n',0)
- ENDIF
- ENDLOOP
- EXCEPT
- Raise(exception)
- ENDPROC c
-
- /* doserial()
- *
- * This is for readscript.. it parses through a list of options, and
- * sequentially selects which option to choose from.
- * It does this by checking the '*' character at the beginning of a line.
- * It'll move that '*' character down the list, moving back to the top
- * when it reaches the bottom. Pretty cool, really. Returns with the
- * option that had the "*" character, or the first line (if no "*" character
- * was found).
- */
-
- PROC doserial(file,col) HANDLE
- DEF buf,c,firstline,lastline,j
-
- buf:=String(col)
- firstline:=Seek(file,0,OFFSET_CURRENT) /* where are we, for the first line? */
- LOOP
- CtrlC()
- lastline:=Seek(file,0,OFFSET_CURRENT) /* where are we again? */
- Fgets(file,buf,col) /* get buffer */
- SetStr(buf,j) /* make sure it's a String*/
- IF buf[0]="#" /* Hmm... it's the end of the list*/
- IF firstline=lastline THEN RETURN 0 /** bad list */
- Seek(file,firstline,OFFSET_BEGINNING) /** Since end of list, but not found*/
- FputC(file,"*") /* "*", we must place "*" in the right*/
- Flush(file) /* spot. */
- Seek(file,firstline,OFFSET_BEGINNING)
- Fgets(file,buf,col)
- SetStr(buf,j)
- Seek(file,lastline+2,OFFSET_BEGINNING)
- RETURN buf
- ENDIF
- IF buf[0]="*" /* found "*", get string and set new "*"*/
- c:=Seek(file,0,OFFSET_CURRENT)
- j:=String(col)
- Fgets(file,j,col)
- IF j[0]="#" /* next line end-of-list, so put * at top*/
- Seek(file,lastline,OFFSET_BEGINNING)
- FputC(file," ")
- Seek(file,lastline+1,OFFSET_BEGINNING)
- Seek(file,firstline,OFFSET_BEGINNING)
- FputC(file,"*")
- LOOP /* everything's done, so go to end of list*/
- CtrlC()
- c:=Fgets(file,j,col)
- IF c=-1 OR j[0]="#"
- Seek(file,1,OFFSET_CURRENT)
- RETURN buf
- ENDIF
- ENDLOOP
- ENDIF
- Seek(file,c,OFFSET_BEGINNING)
- FputC(file,"*")
- Seek(file,lastline,OFFSET_BEGINNING)
- FputC(file," ")
- LOOP
- CtrlC()
- c:=Fgets(file,j,col)
- IF j[0]="#" OR c=-1
- RETURN buf
- ENDIF
- ENDLOOP
- ENDIF
- ENDLOOP
- EXCEPT
- Raise(exception)
- ENDPROC
-
- /* goto()
- *
- * This searches for the appropriate LABEL keyword in a script.
- */
-
- PROC goto(file,name,col) HANDLE
-
- DEF line,i
-
- line:=String(col)
- Seek(file,0,OFFSET_BEGINNING)
- WHILE i<>-1
- CtrlC()
- i:=Fgets(file,line,col)
- IF i=-1 THEN RETURN
- IF line[0]="#"
- IF InStr(line,'LABEL',0)<>-1
- i:=Fgets(file,line,col)
- IF InStr(line,name,0)<>-1 THEN RETURN
- ENDIF
- ENDIF
- ENDWHILE
- EXCEPT
- Raise (exception)
- ENDPROC
-
- /* addscript()
- *
- * Phew.. this closes the current script, saving rpos and filename to
- * the list, then opening the new filename. If it can't open the new one,
- * it'll reopen the old one, and let you know the new one couldn't open.
- */
-
- PROC addscript(scripttag,file,filename,col) HANDLE
- DEF rpos,name
-
- name:=String(col)
- rpos:=Seek(^file,0,OFFSET_CURRENT)-1
- NameFromFH(^file,name,col)
- scripttag:=updatetags(scripttag,[name,rpos])
- Close(^file)
- ^file:=Open(filename,MODE_OLDFILE)
- IF ^file=0
- ^file:=String(100)
- Fault(IoErr(),'QuipScript',^file,100)
- fwriteerr('¡Unable to script "\s"!\n',{filename})
- Dispose(^file)
- ^file:=0
- scripttag:=scriptback(scripttag,file)
- RETURN scripttag
- ENDIF
- EXCEPT
- Raise(exception)
- ENDPROC scripttag
-
- /* scriptback()
- *
- * This backs out of a script file, back to an older script file (if existing).
- */
-
- PROC scriptback(scripttag,file) HANDLE
- DEF i,filename,fpos
-
- i:=ListLen(scripttag)
- IF scripttag=0
- IF ^file<>0
- Close(^file)
- ^file:=0
- ENDIF
- RETURN 0
- ENDIF
- IF i=2
- filename:=ListItem(scripttag,0)
- fpos:=ListItem(scripttag,1)
- IF ^file<>0
- Close(^file)
- ENDIF
- ^file:=Open(filename,MODE_OLDFILE)
- IF ^file=0
- ^file:=String(100)
- Fault(IoErr(),'QuipScript',^file,100)
- fwriteerr('¡Can''t open original scriptfile:\n\s\n\s\n',[filename,^file])
- Dispose(^file)
- ^file:=0
- RETURN 0
- ENDIF
- Seek(^file,fpos,OFFSET_BEGINNING)
- RETURN 0
- ENDIF
- filename:=ListItem(scripttag,i-2)
- fpos:=ListItem(scripttag,i-1)
- ^file:=Open(filename,MODE_OLDFILE)
- IF ^file=0
- ^file:=String(100)
- Fault(IoErr(),'QuipScript',^file,100)
- fwriteerr('¡Unable to reopen "\s"!\n',[filename,^file])
- Dispose(^file)
- ^file:=0
- scripttag:=scriptback(scripttag,file)
- RETURN scripttag
- ENDIF
- Seek(^file,fpos,OFFSET_BEGINNING)
- SetList(scripttag,i-2)
- EXCEPT
- Raise(exception)
- ENDPROC scripttag
-
- /* dochance()
- *
- * This handles the 'CHANCE' keyword in a script. It checks to see if
- * the next statement is a list, and zips past it, if it should.
- */
-
- PROC dochance(file,col,cmp) HANDLE
- DEF line
-
- line:=String(col)
- IF Rnd(1000)<cmp
- RETURN
- ENDIF
- LOOP
- CtrlC()
- IF Fgets(^file,line,col)=-1 THEN RETURN
- IF line[0]="#"
- IF (InStr(line,'RND',0)<>-1) OR (InStr(line,'SEQ',0)<>-1)
- LOOP
- CtrlC()
- IF Fgets(^file,line,col)=-1 THEN RETURN
- IF line[0]="#"
- Seek(^file,-1,OFFSET_CURRENT)
- RETURN
- ENDIF
- ENDLOOP
- ENDIF
- Seek(^file,1,OFFSET_CURRENT)
- RETURN
- ENDIF
- ENDLOOP
- EXCEPT
- Raise(exception)
- ENDPROC
-
- /* listwhichcom()
- *
- * This figures out which command Quip should do (should help reduce code
- * size exponentially, and make updates easier).
- */
-
- PROC listwhichcom(line)
- DEF whichdo=0
- IF InStr(line,'IN_FILE',0)<>-1
- whichdo:=LIST_IN_FILE
- ELSEIF InStr(line,'OUT_FILE',0)<>-1
- whichdo:=LIST_OUT_FILE
- ELSEIF InStr(line,'FILE_FORMAT',0)<>-1
- whichdo:=LIST_FFORMAT
- ELSEIF InStr(line,'FILE_PREFIX',0)<>-1
- whichdo:=LIST_FPREFIX
- ELSEIF InStr(line,'FILE_SUFFIX',0)<>-1
- whichdo:=LIST_FSUFFIX
- ELSEIF InStr(line,'FILE_MIDDLE',0)<>-1
- whichdo:=LIST_FMIDDLE
- ELSEIF InStr(line,'FORMAT',0)<>-1
- whichdo:=LIST_FORMAT
- ELSEIF InStr(line,'PREFIX',0)<>-1
- whichdo:=LIST_PREFIX
- ELSEIF InStr(line,'SUFFIX',0)<>-1
- whichdo:=LIST_SUFFIX
- ELSEIF InStr(line,'MIDDLE',0)<>-1
- whichdo:=LIST_MIDDLE
- ELSEIF InStr(line,'GOTO',0)<>-1
- whichdo:=LIST_GOTO
- ELSEIF InStr(line,'SCRIPT',0)<>-1
- whichdo:=LIST_SCRIPT
- ELSEIF InStr(line,'CHANCE',0)<>-1
- whichdo:=LIST_CHANCE
- ELSEIF InStr(line,'ERROR',0)<>-1
- whichdo:=LIST_ERROR
- ELSEIF InStr(line,'RUN',0)<>-1
- whichdo:=LIST_RUN
- ELSE
- whichdo:=BADCOMMAND
- ENDIF
- ENDPROC whichdo
-
- /* readscript()
- *
- * This is another monster... this handles reading scriptfiles, and
- * properly interpreting the results within. It builds a taglist which
- * is supposed to be passed to findquips() later.
- */
-
- PROC readscript(filename,col) HANDLE
- DEF tag=0,file=0,c=0,line,check,filelist,whichdo,scripttag=0,comwrite=1
- IF col=0 THEN col:=80
- line:=String(col)
-
- file:=Open(filename,MODE_OLDFILE)
- IF file=0
- file:=String(100)
- Fault(IoErr(),'QuipScript',file,100)
- fwriteerr('¡Can''t open "\s" for scripting!\n\s\n',[filename,file])
- Dispose(file)
- file:=0
- RETURN 0
- ENDIF
- WHILE (c<>"@") AND (c<>-1) /* keep hacking away until EOF, or a quip is found */
- CtrlC()
- c:=FgetC(file)
- WHILE c=10 /* a newline character! */
- CtrlC()
- c:=FgetC(file)
- IF c="#" /* we have a command! (maybe) */
- check:=Fgets(file,line,col) /* get the line */
- IF check=0 THEN RETURN tag /* no line..EOF? very bad */
- IF InStr(line,'RND',0)<>-1 /* Is this a RND list? */
- filelist:=dorandom(file,col)
- whichdo:=listwhichcom(line)
- ELSEIF InStr(line,'SEQ',0)<>-1 /* is this a SEQ list?*/
- filelist:=doserial(file,col)
- whichdo:=listwhichcom(line)
- ELSEIF InStr(line,'IN_FILE',0)<>-1 /* oh.. it's just a command */
- whichdo:=IN_FILE
- ELSEIF InStr(line,'OUT_FILE',0)<>-1
- whichdo:=OUT_FILE
- ELSEIF InStr(line,'FILE_FORMAT',0)<>-1
- whichdo:=FFORMAT
- ELSEIF InStr(line,'FILE_PREFIX',0)<>-1
- whichdo:=FPREFIX
- ELSEIF InStr(line,'FILE_SUFFIX',0)<>-1
- whichdo:=FSUFFIX
- ELSEIF InStr(line,'FILE_MIDDLE',0)<>-1
- whichdo:=FMIDDLE
- ELSEIF InStr(line,'FORMAT',0)<>-1
- whichdo:=FORMAT
- ELSEIF InStr(line,'PREFIX',0)<>-1
- whichdo:=PREFIX
- ELSEIF InStr(line,'SUFFIX',0)<>-1
- whichdo:=SUFFIX
- ELSEIF InStr(line,'MIDDLE',0)<>-1
- whichdo:=MIDDLE
- ELSEIF InStr(line,'MAKETABLE',0)<>-1
- whichdo:=MAKETABLE
- ELSEIF InStr(line,'DISPLAY',0)<>-1
- whichdo:=DISPLAY
- ELSEIF InStr(line,'MAKE_QUIPS',0)<>-1
- whichdo:=MAKE_QUIPS
- ELSEIF InStr(line,'HOWMANY',0)<>-1
- whichdo:=HOWMANY
- ELSEIF InStr(line,'RANDOM',0)<>-1
- whichdo:=RANDOM
- ELSEIF InStr(line,'SERIAL',0)<>-1
- whichdo:=SERIAL
- ELSEIF InStr(line,'CHANCE',0)<>-1
- whichdo:=CHANCE
- ELSEIF InStr(line,'WHICHQUIP',0)<>-1
- whichdo:=WHICHQUIP
- ELSEIF InStr(line,'GOTO',0)<>-1
- whichdo:=GOTO
- ELSEIF InStr(line,'LABEL',0)<>-1
- whichdo:=DONOTHING
- ELSEIF InStr(line,'SCRIPT',0)<>-1
- whichdo:=SCRIPT
- ELSEIF InStr(line,'REQ',0)<>-1
- whichdo:=QREQ
- ELSEIF InStr(line,'DELAY',0)<>-1
- whichdo:=QUIPDELAY
- ELSEIF InStr(line,'RESET',0)<>-1
- whichdo:=QRESET
- ELSEIF InStr(line,'UPDATE',0)<>-1
- whichdo:=UPDATE
- ELSEIF InStr(line,'ERROR',0)<>-1
- whichdo:=ERROR
- ELSEIF InStr(line,'OTHER_ECHO',0)<>-1
- whichdo:=BADCOMWRITE
- ELSEIF InStr(line,'RUN',0)<>-1
- whichdo:=RUN
- ELSEIF InStr(line,'FINISHED',0)<>-1
- whichdo:=FINISHED
- ELSE
- whichdo:=BADCOMMAND
- ENDIF
- SELECT whichdo /* we know what it says.. so let's do it*/
- CASE LIST_IN_FILE
- tag:=updatetags(tag,[QTAG_INFILENAME,filelist+1])
- CASE LIST_OUT_FILE
- tag:=updatetags(tag,[QTAG_OUTFILENAME,filelist+1])
- CASE LIST_FORMAT
- filelist:=modformat(filelist+1)
- tag:=updatetags(tag,[QTAG_FORMAT,filelist])
- CASE LIST_PREFIX
- tag:=updatetags(tag,[QTAG_PREFIX,filelist+1])
- CASE LIST_FPREFIX
- tag:=updatetags(tag,[QTAG_FPREFIX,filelist])
- CASE LIST_SUFFIX
- tag:=updatetags(tag,[QTAG_SUFFIX,filelist+1])
- CASE LIST_FSUFFIX
- tag:=updatetags(tag,[QTAG_FSUFFIX,filelist])
- CASE LIST_MIDDLE
- tag:=updatetags(tag,[QTAG_MIDDLE,filelist+1])
- CASE LIST_FMIDDLE
- tag:=updatetags(tag,[QTAG_FMIDDLE,filelist])
- CASE LIST_GOTO
- goto(file,filelist+1,col)
- CASE LIST_SCRIPT
- scripttag:=addscript(scripttag,{file},filelist+1,col)
- CASE LIST_CHANCE
- dochance({file},col,Val(filelist+1,0))
- CASE LIST_ERROR
- efilename:=filelist+1
- CASE LIST_RUN
- tag:=updatetags(tag,[QTAG_RUN,filelist+1])
- CASE IN_FILE
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- tag:=updatetags(tag,[QTAG_INFILENAME,line])
- line:=String(col)
- CASE OUT_FILE
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- tag:=updatetags(tag,[QTAG_OUTFILENAME,line])
- line:=String(col)
- CASE RUN
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- tag:=updatetags(tag,[QTAG_RUN,line])
- line:=String(col)
- CASE QREQ
- tag:=updatetags(tag,[QTAG_REQUSE])
- CASE QUIPDELAY
- Fgets(file,line,col)
- tag:=updatetags(tag,[QTAG_DELAY,Val(line,0)])
- CASE QRESET
- tag:=updatetags(tag,[QTAG_RESET])
- CASE UPDATE
- Fgets(file,line,col)
- tag:=updatetags(tag,[QTAG_UPDATE,Val(line,0)])
- CASE FORMAT
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- filelist:=modformat(line+1)
- IF filelist<>0
- tag:=updatetags(tag,[QTAG_FORMAT,filelist])
- ENDIF
- CASE FFORMAT
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- tag:=updatetags(tag,[QTAG_FFORMAT,filelist])
- line:=String(col)
- CASE PREFIX
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- tag:=updatetags(tag,[QTAG_PREFIX,line])
- line:=String(col)
- CASE FPREFIX
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- tag:=updatetags(tag,[QTAG_FPREFIX,line+1])
- line:=String(col)
- CASE SUFFIX
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- tag:=updatetags(tag,[QTAG_SUFFIX,line])
- line:=String(col)
- CASE FSUFFIX
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- tag:=updatetags(tag,[QTAG_FSUFFIX,line+1])
- line:=String(col)
- CASE MIDDLE
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- tag:=updatetags(tag,[QTAG_MIDDLE,line])
- line:=String(col)
- CASE FMIDDLE
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- tag:=updatetags(tag,[QTAG_FMIDDLE,line+1])
- line:=String(col)
- CASE MAKETABLE
- tag:=updatetags(tag,[QTAG_GENQTABLE])
- CASE DISPLAY
- tag:=updatetags(tag,[QTAG_DISPLAY])
- CASE MAKE_QUIPS
- tag:=updatetags(tag,[QTAG_END])
- CASE HOWMANY
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- tag:=updatetags(tag,[QTAG_NUMQUIPS,Val(line,0)])
- line:=String(col)
- CASE RANDOM
- tag:=updatetags(tag,[QTAG_RANDOM])
- CASE SERIAL
- tag:=updatetags(tag,[QTAG_SERIAL])
- CASE WHICHQUIP
- Fgets(file,line,col)
- tag:=updatetags(tag,[QTAG_WHICHQUIP,Val(line,0)])
- CASE BADCOMMAND
- IF comwrite
- tag:=updatetags(tag,[QTAG_STDOUT,line])
- ELSE
- tag:=updatetags(tag,[QTAG_STDERR,line])
- ENDIF
- line:=String(col)
- CASE GOTO
- Fgets(file,line,col)
- goto(file,line,col)
- CASE BADCOMWRITE
- IF comwrite=0
- comwrite:=1
- ELSE
- comwrite:=0
- ENDIF
- CASE SCRIPT
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- scripttag:=addscript(scripttag,{file},line,col)
- line:=String(col)
- CASE CHANCE
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- check:=Val(line,0)
- line:=line-1
- dochance({file},col,check)
- CASE ERROR
- Fgets(file,line,col)
- check:=StrLen(line)-1
- line[check]:=0
- line:=line+1
- efilename:=line
- line:=String(col)
- CASE FINISHED
- Seek(file,0,OFFSET_END) /* yeah yeah, I know.. ugly */
- CASE DONOTHING
- DEFAULT
- fwriteerr('\n¡Internal Error: readscript()!\n',0)
- ENDSELECT
- Seek(file,-2,OFFSET_CURRENT) /* need to back to enough to catch \n char */
- ELSEIF (c="@") OR (c=-1) /* hmm. eof or a quip*/
- IF file AND (scripttag=0)
- Close(file)
- RETURN tag
- ELSEIF scripttag AND file
- scripttag:=scriptback(scripttag,{file})
- IF (scripttag=0) AND (file=0)
- RETURN tag
- ELSE
- c:="4" /* make c equal ANYTHING but anything important*/
- Seek(file,-1,OFFSET_CURRENT)
- ENDIF
- ELSEIF (scripttag=0) AND (file=0)
- RETURN tag
- ENDIF
- ENDIF
- ENDWHILE
- ENDWHILE
- IF file<>0 THEN Close(file)
- EXCEPT
- IF file<>0 THEN Close(file)
- Raise(exception)
- ENDPROC tag
-
- /* main()
- *
- * Well, gee, it'd be funny to run a program without MAIN!
- *
- * Main mostly handles arguments.. but it has to take into account tooltypes or
- * arguments. It also has to take into account how to manage certain things,
- * in case some argument is used that should make Quip quit (before doing
- * anything else, eg. running a SCRIPT ignores most of the other tooltypes).
- * I also implemented the exthelp part of the ReadArgs, in order to avail
- * myself of THAT convention <grin>. More people should.
- */
-
- PROC main() HANDLE
-
- DEF tag=0,args[ARG_MAX]:LIST,templ,myarg:PTR TO rdargs,rdarg=0,i,
- diskob:PTR TO diskobject, tmptag=0,
- tools, tooltype1, col=81, arg_format, wbargs,
- arghelp, infiledefault, moo
-
- myarg:=0
- arg_format := 'V=VERSION/S,M=MOO/S,C=COL/N,D=DATA/K,T=TABLE/S,RUN/K,' +
- 'FFM=FFORMAT/K,FM=FORMAT/K,P=PRE/K,FP=FPRE/K,S=SUF/K,' +
- 'FS=FSUF/K,W=WHICH/N,R=RANDOM/S,E=ERROR/K,' +
- 'MID=MIDDLE/K,FMID=FMIDDLE/K,O=DISPLAY/S,REQ/S,DE=DELAY/N,' +
- 'N=NUM/N,U=UPDATE/N,' +
- 'F=FILES/K,SC=SCRIPT/K'
-
- wbargs:=['VERSION','MOO','COL','DATA','TABLE','RUN','FFORMAT','FORMAT','PRE',
- 'FPRE','SUF','FSUF',
- 'WHICH','RANDOM','ERROR','MIDDLE','FMIDDLE','DISPLAY','REQ',
- 'DELAY','NUM',
- 'UPDATE','FILES','SCRIPT']
-
- arghelp := 'Usage: Quip [DATA <File>] [PRE <File>] [SUF <File>] [SCRIPT <File>]\n' +
- ' [WHICH <Number>] [RANDOM] [STDIO] [TABLE] [FORMAT]\n' +
- ' [NUM <Number>] [COL] [FILES <Outgoing File>] [REQ]\n' +
- ' [DELAY] <Number> [UPDATE] <Number> [VERSION] [ERROR] <File>\n\n' +
- ' Data = Which file to use for processing a quip\n' +
- ' Pre = A file holding text you''d like to preface your quip[s] with\n' +
- ' Suf = A file holding text you''d like to suffix your quip[s] with\n' +
- ' Script = A file with a script of stuff you want Quip to do\n' +
- ' Which = Which quip (by number) from the datafile you want to start from\n' +
- ' Random = Randomly select a quip\n' +
- ' Stdio = Write quips to standard IO (useful when used with Table)\n' +
- ' Table = Create a tablefile for the datafile\n' +
- ' Format = From CLI, specifies a file from which to create formatted text\n' +
- ' appearing before the quip, but after the prefix file.\n' +
- ' From WB, specifies text to format.\n' +
- ' Num = Number of quips to generate (defaults to 1)\n' +
- ' Col = Number of columns in a scriptfile (defaults to 80 characters)\n' +
- ' Req = Have a reqtools.library requester display the quip.\n' +
- ' Delay = Same as above, but turn off the requester after <num> 10thsecs.\n' +
- ' Update = Update a tablefile from a specific quip, or the last known quip.\n' +
- ' Version = Displays which version of Quip per $VER string.\n' +
- ' Error = Filename you want errors & junk to be sent to.\n' +
- ' Files = Write Num quips to the file specified\n'
-
- moo := ' Moo. (___) \e[4mQuip\e[24m\n' +
- ' \\ _|oo |_______,\n' +
- ' `\\__, ( ( )\\. \e[2mC\e[0mheese\n' +
- ' \\_ `(__) | | \e[2mO\e[0mlfactory\n' +
- ' ||-||____|| ` \e[2mW\e[0morkshop\n' +
- ' \\|/ || || ||| \\|/ \e[1mProduction\e[0m\n' +
- ' `'' `'' ``''\n\n' +
- 'So! You chose the MOO parameter. Well, what are you doing experimenting\n' +
- 'with undocumented commands? You ought to be ashamed of yourselves. You\n' +
- 'could have hurt Bessie, or even worse, yourself.\n\n' +
- '"I can''t believe the *ABSOLUTE* pomposity."\n' +
- ' - Piouhgd\n\n' +
- '"So who''s this Hue, Jr. guy, anyway?"\n' +
- ' - Someone Evil\n\n' +
- '"This possibility exists."\n' +
- ' - Machine\n'
-
- infiledefault := 'S:quip.dat'
- diskob:=0
-
- stayrandom()
-
- IF wbmessage=NIL /* IF called from CLI, get ReadArgs ready */
- FOR i:=0 TO ARG_MAX
- args[i]:=0
- ENDFOR
- myarg:=AllocDosObject(DOS_RDARGS, TAG_DONE)
- myarg.exthelp := arghelp
- templ:=arg_format
- rdarg:=ReadArgs(templ,args,myarg)
- IF rdarg=NIL THEN Raise("ARG")
- ELSE /* IF called from Icon, get ToolTypes ready */
- IF (iconbase:=OpenLibrary('icon.library',37))=0 THEN Raise("LIB")
-
- diskob:=getprogramicon(wbmessage)
-
- IF diskob<>0
- tools:=diskob.tooltypes
- ELSE
- Raise("ICON")
- ENDIF
- ENDIF
- FOR i:=0 TO ARG_MAX-1
- CtrlC()
- IF wbmessage<>NIL /* IF from Icon, get arguments from icon tooltypes */
- tooltype1:=FindToolType(tools,ListItem(wbargs,i))
- ELSE /* IF from CLI, get arguments from arguments */
- tooltype1:=args[i]
- ENDIF
- SELECT i
- CASE ARG_VERSION
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_VERSION])
- ENDIF
- CASE ARG_MOO
- IF tooltype1<>0
- WriteF(moo)
- Raise(0)
- ENDIF
- CASE ARG_COL
- IF tooltype1<>0
- IF wbmessage<>NIL
- col:=Val(tooltype1,0)
- ELSE
- col:=^tooltype1
- ENDIF
- ENDIF
- CASE ARG_RUN
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_RUN,tooltype1])
- ENDIF
- CASE ARG_SCRIPT
- IF tooltype1<>0
- IF StrCmp(tooltype1,'NIL:',ALL)=FALSE
- tmptag:=readscript(tooltype1,col)
- IF tmptag
- tag:=updatetags(tag,tmptag)
- IF tag<>0
- findquip(tag)
- ENDIF
- Raise(0)
- ELSE
- Raise(QERR_BADSFILE)
- ENDIF
- ENDIF
- ELSE
- IF FileLength('s:quip.script')>0 /*if default script exists*/
- tmptag:=readscript('s:quip.script',col)
- IF tmptag
- tag:=updatetags(tag,tmptag)
- findquip(tag)
- Raise(0)
- ELSE
- Raise(QERR_BADSFILE)
- ENDIF
- ENDIF
- ENDIF
- CASE ARG_DATAFILE
- IF tooltype1=0
- tag:=updatetags(tag,[QTAG_INFILENAME,infiledefault])
- ELSE
- tag:=updatetags(tag,[QTAG_INFILENAME,tooltype1])
- ENDIF
- CASE ARG_TABLE
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_GENQTABLE])
- findquip(tag)
- Raise(0)
- ENDIF
- CASE ARG_ERROR
- IF tooltype1<>0
- efilename:=tooltype1
- ELSE
- efilename:=0
- ENDIF
- CASE ARG_FFORMAT
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_FFORMAT,tooltype1])
- ENDIF
- CASE ARG_FORMAT
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_FORMAT,tooltype1])
- ENDIF
- CASE ARG_FPRE
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_FPREFIX,tooltype1])
- ENDIF
- CASE ARG_PRE
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_PREFIX,tooltype1])
- ENDIF
- CASE ARG_FSUF
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_FSUFFIX,tooltype1])
- ENDIF
- CASE ARG_SUF
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_SUFFIX,tooltype1])
- ENDIF
- CASE ARG_FMIDDLE
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_FMIDDLE,tooltype1])
- ENDIF
- CASE ARG_MIDDLE
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_MIDDLE,tooltype1])
- ENDIF
- CASE ARG_WHERE
- IF tooltype1<>0
- IF wbmessage<>NIL
- tag:=updatetags(tag,[QTAG_WHICHQUIP,Val(tooltype1,0)])
- ELSE
- tag:=updatetags(tag,[QTAG_WHICHQUIP,^tooltype1])
- ENDIF
- ENDIF
- CASE ARG_RANDOM
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_RANDOM])
- ENDIF
- CASE ARG_STDIO
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_DISPLAY])
- ENDIF
- CASE ARG_NUM
- IF tooltype1<>0
- IF wbmessage<>NIL
- tag:=updatetags(tag,[QTAG_NUMQUIPS,Val(tooltype1,0)])
- ELSE
- tag:=updatetags(tag,[QTAG_NUMQUIPS,^tooltype1])
- ENDIF
- ENDIF
- CASE ARG_UPDATE
- IF tooltype1<>0
- IF wbmessage<>NIL
- tag:=updatetags(tag,[QTAG_UPDATE,Val(tooltype1,0)])
- ELSE
- tag:=updatetags(tag,[QTAG_UPDATE,^tooltype1])
- ENDIF
- findquip(tag)
- Raise(0)
- ENDIF
- CASE ARG_REQ
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_REQUSE])
- ENDIF
- CASE ARG_DELAY
- IF tooltype1<>0
- IF wbmessage<>NIL
- tag:=updatetags(tag,[QTAG_DELAY,Val(tooltype1,0)])
- ELSE
- tag:=updatetags(tag,[QTAG_DELAY,^tooltype1])
- ENDIF
- ENDIF
- CASE ARG_FILES
- IF tooltype1<>0
- tag:=updatetags(tag,[QTAG_OUTFILENAME,tooltype1])
- ENDIF
- DEFAULT
- fwriteerr('¡Internal error: PROC main()!\n',0)
- ENDSELECT
- ENDFOR
- IF tag<>0
- tag:=updatetags(tag,[QTAG_END])
- ELSE
- tag:=updatetags(tag,[QTAG_VERSION])
- findquip(tag)
- WriteF(arghelp)
- Raise(0)
- ENDIF
- findquip(tag)
- Raise(0)
- EXCEPT
- IF myarg THEN FreeDosObject(DOS_RDARGS,myarg)
- IF rdarg THEN FreeArgs(rdarg)
- IF iconbase THEN CloseLibrary(iconbase)
- IF diskob THEN FreeDiskObject(diskob)
- IF reqtoolsbase THEN CloseLibrary(reqtoolsbase)
- myarg:=IoErr()
- SELECT exception
- CASE 0
- tag:=0
- CASE "ARG"
- tag:=10
- CASE "^C"
- SetIoErr(ERROR_BREAK)
- tag:=10
- CASE "MEM"
- fwriteerr('Quip: unable to allocate memory\n',0)
- SetIoErr(myarg)
- tag:=10
- CASE "LIB"
- fwriteerr('Quip: unable to open icon.library version 37 or better\n',0)
- SetIoErr(myarg)
- tag:=10
- CASE "ICON"
- fwriteerr('Quip: bad icon\n',0)
- SetIoErr(myarg)
- tag:=10
- DEFAULT
- tag:=10
- ENDSELECT
- IF tag=10
- tag:=IoErr()
- IF (((tag>102) AND (tag<243)) OR ((tag>303) AND (tag<305))) AND (exception<>QERR_BADSFILE)
- tag:=String(100)
- Fault(IoErr(),'Quip',tag,100)
- fwriteerr('\s\n',{tag})
- Dispose(tag)
- ENDIF
- tag:=10
- ENDIF
- IF efile<>stdout
- Close(efile)
- ENDIF
- IF estate THEN fwriteerr('\nPress RETURN to close window',0)
- CleanUp(tag)
- ENDPROC
-