00001 & ! PPPPP H H OOO N N EEEEE BBBB AAA SSSSS & ! P P H H O O NN N E B B A A S & ! PPPPP HHHHH O O N N N EEEE BBBB AAAAA SSSSS & ! P H H O O N NN E B B A A S & ! P H H OOO N N EEEEE :: BBBB A A SSSSS & & & ! ============================================================= & ! From: The Instructional Computing Center & ! Snygg Hall & ! S.U.N.Y. Oswego & ! Oswego, New York 13126 & ! ============================================================= & ! PROGRAM: PHONE.BAS & ! VERSION: 1.0 & ! PROGRAMMER: ANDREW K. PFIFFER & ! DATE: SUMMER 1984 & ! & ! VERSION: 2.1 & ! PROGRAMMER: Edward F. Beadel, Jr. & ! DATE: October 1988 & ! & ! fixed bug in fnCALL% at line 650 & ! revised for RSTS/E V9.5+ Job Table resturcturing & ! in line 240 & ! made detached KBs show up as "Det" rather than "KB255:" & ! in line 300 & ! changed all open statements that referr to the "KB:" to & ! open "KB:" as file #10%, mode 16384% & ! to deal with the problems concerning 7-bit & ! escape sequences when the terminal is in 8-bit & ! mode. This also meant that all simple "print" & ! statements had to be changed to a "print #10%, "& ! type of format. & ! & ! ============================================================= & ! & ! G E N E R A L D E S C R I P T I O N & ! & ! PHONE is a simulation of the utility provided under & ! the VMS operating system. Communication between users is & ! simultaneous, allowing both users to see all characters & ! as they are typed. PHONE calls can be recorded and played & ! back at a later date. Each user owns their own directory & ! of names and account numbers of others on the system. & ! ============================================================= & ! & ! O P E R A T I N G I N S T R U C T I O N S & ! & ! INSTALLATION: & ! & ! a) Edit line 00010 of PHONE.BAS to indicate what & ! account the help files and the compiled version & ! will be in. & ! & ! b) From a privileged account, execute the following & ! command sequence, substituting the account noted & ! in step "a" for all occurrences of "IN" below: & ! & ! OLD IN:PHONE & ! COMPILE IN:<232> & ! DEFINE/COMMAND/SYSTEM PH-ONE IN:PHONE.*;0 & ! DEFINE/COMMAND/SYSTEM AN-SWER IN:PHONE.*;0 & ! & ! All done! The ANSWER CCL is optional and need & ! not be included in your installation. & ! & ! OPERATION: & ! & ! Type PHONE and use the HELP command. & ! Release V2.1 of PHONE should work on all & ! terminals that support ansii escape sequences, & ! wheather operated in 7-bit or 8-bit mode. It & ! has been tested on VT100 clones (PCs running & ! Kermit in VT100 mode and Zenith Z-29s) and & ! real VT220s. & ! & ! ============================================================= & ! 00002 ! ============================================================= & ! COPYRIGHT (c) 1981, 1982, 1983, and 1984 & ! V 1.0 & ! COPYRIGHT (c) 1981, 1982, 1983, and 1984 & ! V 2.1 & ! BY & ! Instructional Computing Center & ! State University of New York at Oswego & ! Oswego, NY 13126 & ! & ! contact: Edward F. Beadel, Jr. & ! Assistant Director & ! phone: 315/341-3055 & ! & ! & ! This software is furnished in an as-is condition, & ! with no committments of support or updates. This & ! software or any other copies thereof may NOT be & ! sold for profit nor can it be included in any & ! package to be sold for profit without the written & ! consent of the author and the coppyright owner. & ! This software may be used and copied only in ac- & ! cordance with the terms set forth above and with & ! the inclusion of the above copyright notice. & ! & ! The information in this software is subject & ! to change without notice and should not be con- & ! strued as a commitment by The State University of & ! New York, The Instructional Computing Center, the & ! author(s) or maintainer(s) of this software. & ! & ! The State University of New York, The & ! Instructional Computing Center, the author(s), and & ! the maintainer(s) of this software collectively & ! and individually assume no responsibility for the & ! use or reliability of this software. & ! ============================================================= & ! 00003 ! & & ! I / O C H A N N E L S & & & ! CHANNEL # USED FOR & ! ================================================ & ! one keyboard & & ! four phone directory, & ! playback & & ! five recording, & ! help files & & ! ten keyboard & !& ! 00005 ! F U N C T I O N D E S C R I P T I O N & ! ============================================== & ! fnGET$ Returns a buffer of characters & ! from the pre-recorded tape, or & ! from the KB: in binary mode. & ! fnPUT$ Binary output of a string to the KB: & ! fnFORCE% Forces a string to a keyboard. & ! fnBROADCAST% Broadcasts a string to a keyboard. & ! fnON% Gets job statistics for a given job. & & ! fnLEFTPAD$, Returns a string altered in a way & ! fnRIGHTPAD$, indicated by their names. & ! fnCENTER$ & & ! fnNICK.NAME$ Returns, if found, the aliased name & ! of a [project, programmer]. & ! fnMATCH.NAME% Returns, if found, ppn% of an & ! aliased name. & & ! fnMAKE.PPN$, Make pleasing and consistently sized & ! fnMAKE.KB$ strings for keyboards and [p,pn]'s & & ! fnINSERT% Inserts a name and [p,pn] into the & ! user's directory. & ! fnALIAS% Pre-processor for fnINSERT% & & ! fnWHO% Displays a fast(er) list of current & ! jobs on the system. & ! fnDIR% Displays a list of current attached & ! userss with aliased names. & & ! fnCALL% Call a user. & ! fnLIST% List the user's directory. & ! fnSORT% Crude, but effective, directory sort. & ! fnHELP% Processes help commands. & ! fnEXIT% Graceful exit from PHONE. & ! fnJOB% Returns the job number, if on, of & ! an aliased name. & ! fnANSR% Answers a ringing PHONE. & ! fnRING% Rings a user's PHONE. & ! fnBUSY% Returns true if a PHONE is busy. & & ! fnHOOK.OFF%, Puts a PHONE off or on the hook. & ! fnHOOK.ON% & & ! fnCONVERSE% Converse with someone. & ! fnRECORDING% Record a conversation. & ! fnPLAY% Play a recorded conversation. & ! 00006 ! ====================================================== & ! & ! & ! I N I T I A L I Z A T I O N & ! & ! & ! ====================================================== & ! 00010 on error goto 30000 & \ open "KB:" as file #10%, mode 16384% & \ in$ = "phone:" ! <== Edit this to suit. & \ hdr$ = 'Phone V2.1 - ' & \ max.entry% = 255% & \ dim #4%, alias$(255%)=16% & ! Set the error trap & ! Define where we are and where to look for the help files & ! Set the maximum number of directory entries & ! Dimension the virtual array for the directory. & ! 00011 ! ====================================================== & ! & ! Some VT-100/VT-200 and ANSI 7-bit escape codes for & ! nifty terminal stuff. & ! & ! ====================================================== & ! 00012 esc$ = chr$(27%) & \ fip$ = chr$(6%) & \ uu.sys$ = chr$(26%) & \ blank$ = string$(26%,0%) & \ i$ = sys(fip$+chr$(-7%)) !enable ctrl-c trap & \ ascchrset$ = esc$+'(B' & \ grfchrset$ = esc$+'(0' & \ altchrset$ = esc$+'(1' & \ altgrfset$ = esc$+'(2' & \ cursor.save$ = esc$+'7' & \ cursor.restore$ = esc$+'8' & \ cr$ = chr$(13%) & \ lf$ = chr$(10%) & \ cr.lf$ = cr$+lf$ & \ reset.terminal$ = esc$+'c' & \ erase.all$ = esc$+'[2J' & \ erase.line$ = esc$+'[2K' & \ bold$ = esc$+'[1m' & \ halfintensity$ = esc$ + '[2m' & \ underline$ = esc$+'[4m' & \ blink$ = esc$+'[5m' & \ reverse.video$ = esc$+'[7m' & \ reset.attributes$ = esc$+'[0m' & ! 00019 ! ====================================================== & ! & ! VT-100 functions: & ! & ! ====================================================== & ! 00020 def fnPOSITION$(x%,y%) = esc$+'['+num1$(y%)+';'+num1$(x%)+'H' & ! 00030 def fnERASELINE$(el.y%) = fnPOSITION$(1%,el.y%) + erase.line$ & ! 00040 def fnSCROLL.AREA$(rt%,rb%) = esc$+'['+num1$(rt%)+';'+num1$(rb%)+'r' & ! 00050 def fnH.LINE$(h.lx%, h.rx%, h.y%) & \ h.l$ = grfchrset$ + fnPOSITION$(h.lx%, h.y%) & \ h.l$ = h.l$ + string$(h.rx% - h.lx% + 1%, 113%) & \ fnH.LINE$ = h.l$ + ascchrset$ & \ fnend & ! 00060 def fnV.LINE$(v.uy%, v.ly%, v.x%) & \ v.l$ = grfchrset$ + fnPOSITION$(v.x%, v.uy%) & \ v.l$ = v.l$ + "x" + chr$(8%) + chr$(10%) for v.i% = v.uy% to v.ly% & \ fnV.LINE$ = v.l$ + ascchrset$ & \ fnend & ! & ! NOTE: & ! H.LINE and V.LINE aren't used but may be useful in altering & ! PHONE to work with other terminal types... & ! 00101 ! ====================================================== & ! & ! Start of function definitions & ! & ! fnGET$(get.x$) fnPUT$(put.x$) & ! & ! ====================================================== & ! 00200 def fnGET$(get.x$) & \ if playback% then field #4%, 512% as get.inp$ & \ get #4% & \ goto 00204 & ! If playing a recording, field the conversation from disk... & ! get the data... & ! and return it. & ! 00201 field #1%, 128% as get.inp$ & \ get #1% & ! LIVE conversation so get the input from the keyboard. & ! 00204 fnGET$ = left(get.inp$,recount) & \ fnend & ! 00205 def fnPUT$(put.x$) & \ field #1%, 128% as p.x$ & \ lset p.x$ = put.x$ & \ put #1%, record 16384%, count len(put.x$) & \ fnend & ! Make sure the channel buffer size is right for a KB:... & ! Throw the string in the buffer... & ! and write it (binarily, of course). & ! 00209 ! ====================================================== & ! & ! fnFORCE%(KeyBoardNumber, StringToForce) & ! & ! fnBROADCAST%(KeyBoardNumber, StringToBroadcast) & ! & ! ====================================================== & ! 00210 def fnFORCE%(force.kb%,force.x$) & ! 00215 force.i$ = sys(fip$+chr$(-4%)+chr$(force.kb%)+force.x$) & \ if recount <> 0% and recount <> len(force.x$) & then force.x$ = right(force.x$,len(force.x$) - recount + 1%) & \ goto 00215 & ! Call FIP to shovel the string... & ! resend what didn't get sent if FIP didn't finish. & ! 00220 fnend & ! 00230 def fnBROADCAST%(bcst.kb%,bcst.x$) & ! 00235 bcst.i$ = sys(fip$+chr$(-5%)+chr$(bcst.kb%)+bcst.x$) & \ if recount <> 0% and recount <> len(bcst.x$) & then bcst.x$ = right(bcst.x$,len(bcst.x$) - recount + 1%) & \ goto 00235 & ! Call FIP to send the string... & ! resend what didn't get sent if FIP didn't finish. & ! 00237 fnend & ! 00239 ! ====================================================== & ! fnON%(JobNumber): & ! & ! Sets some "global" variables and returns job info for & ! "JobNumber" if "JobNumber" is on the system. & ! & ! ====================================================== & ! 00240 def fnON%(on.job%) & \ p%, pn%, ppn%, kb% = 0% & \ what$ = "" & \ JDB% = peek(JOBTBL% + (on.job% * 2%)) ! get job's JDB & \ goto 00250 if JDB% <= 0% ! not on or end of table. & \ IOB% = peek(JDB%) ! get pointer to IOB% & \ DDB% = peek(IOB%) ! get pointer to device data block & \ atch% = ( (peek(DDB% + 2%) and 255%) = (on.job% * 2%) ! attached? & and (peek(DDB% + 6%) and 8192%) <> 0%) & \ a$ = sys(fip$ + uu.sys$ + chr$(on.job%) + chr$(0%) + blank$) & \ ppn% = swap%(cvt$%(mid(A$,21%,2%))) ! job's proj,prog # & \ p% = swap%(ppn%) and 255% ! job's project # & \ pn% = ppn% and 255% ! job's programmer # & \ kb% = ascii(mid(a$,4%,1%)) ! job's kb # & \ what$ = rad$(swap%(cvt$%(mid(a$,17%,2%)))) & + rad$(swap%(cvt$%(mid(a$,19%,2%)))) & ! get the name of what they are doing & ! 00250 fnON% = JDB% & \ fnend & ! 00259 ! ====================================================== & ! fnLEFTPAD$(ExpectedFieldWidth, String) & ! fnRIGHTPAD$(ExpectedFieldWidth, String) & ! fnCENTER$(ExpectedFieldWidth, String) & ! & ! String functions missing from BASIC+... & ! ====================================================== & ! 00260 def fnLEFTPAD$(lp.sp%,lp.x$) = space$(lp.sp% - len(lp.x$)) + lp.x$ & ! 00270 def fnRIGHTPAD$(rp.sp%,rp.x$) = left(rp.x$ + space$(rp.sp%),rp.sp%) & ! 00275 def fnCENTER$(c.sp%,c.x$) & \ c.x$ = cvt$$(c.x$,8% + 128%) & \ c.l% = (c.sp%/2%) - (len(c.x$)/2%) & \ c.x$ = space$(c.l%) + c.x$ & \ fnCENTER$ = c.x$ + space$(c.sp% - len(c.x$)) & \ fnend & ! 00279 ! ====================================================== & ! & ! fnNICK.NAME$(project, programmer) : & ! & ! Performs a binary search of the directory to find the & ! name associated with user number [p,pn]. & ! ====================================================== & ! 00280 def fnNICK.NAME$(nn.p%,nn.pn%) & \ nn.ppn = 256 * nn.p% + nn.pn% & \ lo% = 1% & \ open "DIRECT.PHN" for input as file 4% & \ hi% = cvt$%(alias$(0%)) & \ goto 00283 if hi% = 0% & \ nn$ = "" & ! Create our target [p,pn]. (Notice the use of reals!) & ! Initialize and open the directory. & ! Get the last valid element. & ! Get out if the directory is empty. & ! 00281 cntr% = (lo% + hi%) / 2% & \ entry$ = alias$(cntr%) & \ ppn% = cvt$%(right(entry$,15%)) & \ ppn = 256 * (swap%(ppn%) and 255%) + (ppn% and 255%) & \ a.name$ = left(entry$,14%) & \ nn$ = a.name$ if ppn = nn.ppn & \ goto 00283 if len(nn$) > 0% & \ hi% = cntr% - 1% if ppn > nn.ppn & \ lo% = cntr% + 1% if ppn < nn.ppn & \ goto 00283 if hi% < lo% & \ goto 00281 & ! Look at the center element. & ! and get what is there. & ! Compute the entry's [p,pn] & ! Assign the name if we found what we were lookin' for. & ! Adjust our indices until something happens. & ! 00283 close #4% & \ fnNICK.NAME$ = nn$ & \ fnend & ! 00284 ! ====================================================== & ! & ! fnMATCH.NAME$(TargetName) : & ! & ! Returns the ppn of the directory entry with the name & ! of "TargetName." Linear search. & ! ====================================================== & ! 00285 def fnMATCH.NAME%(m.name$) & \ open "DIRECT.PHN" for input as file 4% & \ m.ppn% = 0% & \ m.total% = cvt$%(alias$(0%)) & \ for m.i% = 1% to m.total% & \ m.entry$ = alias$(m.i%) & \ m.ppn% = cvt$%(right(m.entry$,15%)) if m.name$ = cvt$$(left(m.entry$,14%),128%) & \ m.i% = m.total% + 1% if m.ppn% & \ next m.i% & \ close #4% & \ fnMATCH.NAME% = m.ppn% & \ fnend & ! Open the directory... & ! Kick out when we find it -or- & ! keep going 'til we reach the bottom. & ! 00289 ! ====================================================== & ! fnMAKE.PPN$(p,pn) fnMAKE.KB$(kb#) & ! & ! These two functions return a string, nicely formed & ! from the numerical data input. Thats all, nothing & ! special. & ! ====================================================== & ! 00290 def fnMAKE.PPN$(m.p%,m.pn%) & \ m.ppn$ = '[' + fnLEFTPAD$(3%,num1$(m.p%)) & \ fnMAKE.PPN$ = m.ppn$ + ',' + fnRIGHTPAD$(3%,num1$(m.pn%)) + ']' & \ fnend & ! 00300 def fnMAKE.KB$(m.kb%) & \ if (m.kb% and 128%) <> 0% & then & fnMAKE.KB$ = 'Det' & else & fnMAKE.KB$ = 'KB' + fnLEFTPAD$(2%,num1$(m.kb%)) + ':' & ! 00305 fnend & ! 00309 ! ====================================================== & ! & ! fnINSERT%(name, p, pn) & ! & ! INSERT% will find the proper place to put the entry & ! in the directory, and copy all others back one. & ! ====================================================== & ! 00310 def fnINSERT%(i.name$,i.p%,i.pn%) & \ last.entry% = cvt$%(alias$(0%)) & \ print #10%, "Directory is full." if last.entry% = max.entry% & \ goto 00311 if last.entry% = max.entry% & \ i.ppn = 256 * i.p% + i.pn% & \ i.found% = 0% & \ for i% = 1% to last.entry% & \ ppn% = cvt$%(right(alias$(i%),15%)) & \ ppn = 256 * (swap%(ppn%) and 255%) + (ppn% and 255%) & \ i.found% = i% if ppn >= i.ppn & \ i% = last.entry% + 1% if i.found% & \ next i% & \ i.found% = last.entry% + 1% if i.found% = 0% & \ alias$(i%) = alias$(i% - 1%) for i% = (last.entry% + 1%) to i.found% step -1% & \ alias$(i.found%) = fnRIGHTPAD$(14%,i.name$) + cvt%$(swap%(i.p%) + i.pn%) & \ alias$(0%) = cvt%$(last.entry% + 1%) & ! Get the last element... & ! Get out if the directory is full... & ! Find out where it is supposed to go... & ! Make a hole for it by copying all larger elements back one... & ! Fill in the hole with 14 characters worth of name, and two... & ! for project, programmer number. & ! 00311 fnINSERT% = i.found% & \ fnend & ! 00499 ! ====================================================== & ! & ! fnALIAS%(AliasCommand) : & ! & ! ALIAS% will extract the information from the command & ! string to insert or delete an element from the list. & ! ====================================================== & ! 00500 def fnALIAS%(a.command$) & \ a.eq% = instr(1%,a.command$,"=") & \ alias.name$ = left(a.command$,a.eq% - 1%) & \ print #10%, "?Must have a name..." if len(alias.name$) = 0% & \ goto 00510 if len(alias.name$) = 0% & \ a.ppn$ = right(a.command$,a.eq% + 1%) & \ open "DIRECT.PHN" as file 4% & \ goto 00505 if len(a.ppn$) = 0% & \ a.lparen% = instr(a.eq%,a.command$,"(") & \ a.rparen% = instr(a.eq%,a.command$,")") & \ a.comma% = instr(a.eq%,a.command$,",") & \ a.p% = val(mid(a.command$,a.lparen%+1%,a.comma%-a.lparen%-1%)) & \ a.pn% = val(mid(a.command$,a.comma% +1%,a.rparen%-a.comma%-1%)) & \ a.found% = fnINSERT%(alias.name$,a.p%,a.pn%) & \ goto 00510 & ! Look for an equals sign... & ! Get the name from the left-hand side of the equals... & ! Get out if there is no name... & ! Try to find something like "[p,pn]"... & ! Delete the name if "[p,pn]" isn't there... & ! Get the project and programmer numbers... & ! And insert into the directory... & ! 00505 last.entry% = cvt$%(alias$(0%)) & \ a.found% = 0% & \ for a.i% = last.entry% to 1% step -1% & \ a.found% = a.i% if left(alias$(a.i%),14%) = fnRIGHTPAD$(14%,alias.name$) & \ a.i% = 0% if a.found% <> 0% & \ next a.i% & \ goto 00510 if a.found% = 0% & \ alias$(a.i%) = alias$(a.i% + 1%) for a.i% = a.found% to (last.entry% - 1%) & \ alias$(0%) = cvt%$(last.entry% - 1%) & ! Find the name that we are supposed to delete... & ! And move those below up one... & ! 00510 close #4% & \ command$ = " " & \ a.i% = fnLIST%("LIST " + num1$((a.found% - 1%)/36% + 1%)) & \ fnALIAS% = 1% & \ fnend & ! 00549 ! ====================================================== & ! & ! fnWHO%(SYStatOrWHo) & ! & ! Display a fast system status. Display unattached jobs & ! if the command is a "SYS" else only attached jobs. & ! ====================================================== & ! 00550 def fnWHO%(w.command$) & \ print #10%, fnERASELINE$(w.i%); for w.i% = 2% to 14% & \ print #10%, fnPOSITION$(1%,1%) + underline$ + halfintensity$ & \ print #10%, "Job Who What Where "; for w.i% = 1% to 3% & \ print #10%, reset.attributes$ + grfchrset$ + halfintensity$; & \ print #10%, fnPOSITION$(26%,w.y%)+'x'; for w.y% = 3% to 14% & \ print #10%, fnPOSITION$(52%,w.y%)+'x'; for w.y% = 3% to 14% & \ print #10%, reset.attributes$ + ascchrset$; & \ print #10%, fnSCROLL.AREA$(3%,14%); & \ print #10%, fnPOSITION$(1%,3%); & \ w.y% = 3% & \ w.x% = 1% & \ w.i% = 1% & ! Clear out the top half of the screen and get ready... & ! 00552 w.j% = fnON%(w.i%) & \ goto 00560 if w.j% = -1% & \ goto 00554 if len(what$) = 0% & \ goto 00554 if not atch% and left(w.command$,2%) = "WH" & \ print #10%, fnPOSITION$(w.x%,w.y%); & \ print #10%, fnLEFTPAD$(2%,num1$(w.i%));' ';fnMAKE.PPN$(p%,pn%); & \ print #10%, ' ';what$;' ';fnMAKE.KB$(kb%); & \ w.y% = w.y% + 1% & \ w.x% = w.x% + 26% if w.y% > 14% & \ w.y% = 3% if w.y% > 14% & ! Ask if a job is on... & ! Print out what we know... & ! 00554 w.i% = w.i% + 1% & \ goto 00552 & ! Increment our job number counter and continue... & ! 00560 print #10%, fnSCROLL.AREA$(17%,24%); & \ print #10%, fnPOSITION$(1%,23%) & \ fnWHO% = 1% & \ fnend & ! 00599 ! ====================================================== & ! & ! fnDIR% & ! & ! Display a system status of attached jobs with the & ! names listed in the directory. & ! ====================================================== & ! 00600 def fnDIR%(d.command$) & \ print #10%, fnERASELINE$(d.i%); for d.i% = 2% to 14% & \ print #10%, fnPOSITION$(1%,1%) + underline$ + halfintensity$ & \ print #10%, " Name Who What Where "; for d.i% = 1% to 2% & \ print #10%, reset.attributes$ + grfchrset$ + halfintensity$; & \ print #10%, fnPOSITION$(40%,d.i%) + "x"; for d.i% = 3% to 14% & \ print #10%, reset.attributes$ + ascchrset$; & \ d.xp% = 1% & \ d.yp% = 3% & \ d.job% = 1% & ! Clear out the top of the screen and get ready... & ! 00602 d.x% = fnON%(d.job%) & \ goto 00610 if d.x% = -1% & \ goto 00604 if len(what$) = 0% & \ goto 00604 if not atch% & \ d.name$ = fnNICK.NAME$(p%,pn%) & \ d.name$ = "#" + num1$(d.job%) if len(d.name$) = 0% & \ d.busy$ = " " & \ d.busy$ = "*" if fnBUSY%(d.job%,p%,pn%) & \ print #10%, fnPOSITION$(d.xp%,d.yp%); & \ print #10%, d.busy$;fnCENTER$(14%,d.name$);" "; & \ print #10%, fnMAKE.PPN$(p%,pn%);" ";what$;" ";fnMAKE.KB$(kb%) & \ d.yp% = d.yp% + 1% & \ d.xp% = 41% if d.yp% > 14% & \ d.yp% = 3% if d.yp% > 14% & ! Ask if a job is on... & ! Try to find out their name if they are on and attached... & ! Make their name their job number if they are "undefined" & ! See if their phone is busy... & ! Print out what we know... & ! 00604 d.job% = d.job% + 1% & \ goto 00602 & ! Increment our job number index and continue. & ! 00610 print #10%, fnSCROLL.AREA$(17%,24%); & \ print #10%, fnPOSITION$(1%,23%) & \ fnDIR% = 1% & \ fnend & ! 00649 ! ====================================================== & ! & ! fnCALL%(User) & ! & ! This function will try to call a user by ringing their & ! phone. A conversation will take place if they answer. & ! ====================================================== & ! 00650 def fnCALL%(c.command$) & \ c.rings% = 10% & \ c.name$ = cvt$$(right(c.command$,instr(3%,c.command$,' ')),8% + 128%) & \ c.job% = fnJOB%(c.name$) & \ print #10%, '"'; c.name$; '"'; " can't be called." if c.job% = -1% & \ goto 00660 if c.job% = -1% & ! Set the number of times their phone will ring... & ! Get the name of the person we are trying to call... & ! Find out their job number... & ! You can't call a person that is not on the system... & ! 00651 open "CALL" + num1$(my.job%) + ".PHN" for input as file 4% & \ close #4% & \ print #10%, "Not when your phone is ringing." & \ goto 00660 & ! You can't call somebody when your phone is ringing... & ! 00652 c.i% = fnON%(c.job%) & \ c.i% = fnBUSY%(c.job%,p%,pn%) & \ print #10%, c.name$;"'s phone is busy." if c.i% & \ goto 00660 if c.i% & ! You can't call someone if their phone is busy... & ! 00655 c.i% = fnRING%(c.job%,c.rings%) & \ print #10%, & \ print #10%, "No answer." if c.i% = 0% & \ goto 00660 if c.i% = 0% & \ c.i% = fnHOOK.OFF%("") & \ c.i% = fnCONVERSE%(c.job%) & \ c.i% = fnHOOK.ON%("") & ! Ring their phone... & ! They answered if fnRING% > 0% & ! Take your phone off the hook if they answered... & ! Talk to them... & ! Put your phone back on the hook when you're done talkin' & ! 00660 fnCALL% = 1% & \ fnend & ! 00699 ! ====================================================== & ! & ! fnLIST%(Page) & ! & ! Produce a display of what is in the user's directory. & ! Display the page indicated or implied by the command. & ! ====================================================== & ! 00700 def fnLIST%(l.command$) & \ print #10%, fnERASELINE$(l.i%); for l.i% = 2% to 14% & \ print #10%, fnSCROLL.AREA$(3%,14%); & \ open "DIRECT.PHN" for input as file 4% & \ last.entry% = cvt$%(alias$(0%)) & \ goto 00705 if last.entry% = 0% & \ max.page% = int((last.entry% - 1%)/36%) + 1% & \ list.page% = list.page% + 1% & \ list.page% = max.page% if instr(1%,l.command$,".") & \ list.page% = list.page% - 1% if instr(1%,l.command$,"0") & \ list.page% = list.page% - 2% if instr(1%,l.command$,"-") & \ for l.i% = 1% to 9% & \ list.page% = l.i% if instr(1%,l.command$,chr$(48% + l.i%)) & \ next l.i% & \ list.page% = 1% if list.page% < 1% & \ list.page% = max.page% if list.page% > max.page% & \ l.x% = 1% & \ l.y% = 3% & \ l.i% = 0% & \ l.index% = (list.page% - 1%) * 36% + 1% & \ print #10%, fnPOSITION$(1%,1%) + underline$ + halfintensity$ & \ print #10%, space$(80%) + fnPOSITION$(1%,2%); & \ print #10%, bold$ + my.header$ + reset.attributes$ + underline$ + halfintensity$; & \ print #10%, "'s directory:"; & \ l.page$ = "Page" + fnLEFTPAD$(3%,num1$(list.page%)) + " of" + fnLEFTPAD$(3%,num1$(max.page%)) & \ print #10%, fnPOSITION$(81% - len(l.page$),2%) + l.page$; & \ l.item$ = fnLEFTPAD$(3%,num1$(last.entry%)) + " Items" & \ print #10%, fnPOSITION$(40% - (len(l.item$)/2%),2%) + l.item$; & \ print #10%, reset.attributes$; & ! Clear out the top of the screen and get ready... & ! Get out if there is nothing the directory... & ! Find the total number of pages in the directory... & ! Figure out which page to list... & ! Print the headers... & ! 00701 goto 00705 if l.i% > 35% & \ goto 00705 if l.index% + l.i% > last.entry% & \ l.name$ = fnCENTER$(14%,left(alias$(l.index% + l.i%),14%)) & \ l.ppn% = cvt$%(right(alias$(l.index% + l.i%),15%)) & \ l.p% = swap%(l.ppn%) and 255% & \ l.pn% = l.ppn% and 255% & \ l.ppn$ = fnMAKE.PPN$(l.p%,l.pn%) & \ print #10%, fnPOSITION$(l.x%,l.y%) + l.name$ + "=" + l.ppn$; & \ l.y% = l.y% + 1% & \ l.x% = l.x% + 28% if l.y% > 14% & \ l.y% = 3% if l.y% > 14% & \ l.i% = l.i% + 1% & \ goto 00701 & ! Display this page... & ! 00705 close #4% & \ print #10%, fnSCROLL.AREA$(17%,24%); & \ print #10%, fnPOSITION$(1%,23%) & \ fnLIST% = 1% & \ fnend & ! 00724 ! ====================================================== & ! & ! fnSORT% & ! & ! A crude, but always effective bubble sort. This should & ! only be needed if an external program alters the dir. & ! ====================================================== & ! 00725 def fnSORT%(s.command$) & \ open "DIRECT.PHN" as file 4% & \ s.last% = cvt$%(alias$(0%)) & \ for s.j% = s.last% - 1% to 1% step -1% & \ for s.i% = 1% to s.j% & \ s.i$ = alias$(s.i%) & \ s.iplus$ = alias$(s.i% + 1%) & \ s.ippn% = cvt$%(right(s.i$,15%)) & \ s.ippn = 256 * (swap%(s.ippn%) and 255%) + (s.ippn% and 255%) & \ s.iplusppn% = cvt$%(right(s.iplus$,15%)) & \ s.iplusppn = 256 * (swap%(s.iplusppn%) and 255%) + (s.iplusppn% and 255%) & \ s.needswap% = (s.ippn > s.iplusppn) & \ s.t$ = alias$(s.i% + 1%) if s.needswap% & \ alias$(s.i% + 1%) = alias$(s.i%) if s.needswap% & \ alias$(s.i%) = s.t$ if s.needswap% & \ next s.i% & \ next s.j% & \ close #4% & \ fnSORT% = 1% & \ fnend & ! The Tried and True Bubble Sort & ! 00749 ! ====================================================== & ! & ! fnHELP%(HelpCommand) & ! & ! Extract the first two characters typed after the help & ! command and use them to find an appropriate file. & ! ====================================================== & ! 00750 def fnHELP%(h.command$) & \ print #10%, fnERASEline$(h.i%); for h.i% = 2% to 14% & \ print #10%, reset.attributes$ + grfchrset$ + halfintensity$; & \ print #10%, fnPOSITION$(40%,d.i%) + "x"; for d.i% = 3% to 14% & \ print #10%, reset.attributes$ + ascchrset$; & \ print #10%, fnPOSITION$(1%,1%) + halfintensity$ + underline$ + grfchrset$ & \ print #10%, dash$ + reset.attributes$ + ascchrset$ & \ h.command$ = cvt$$(h.command$,2%) & \ h.command$ = left(right(h.command$,5%),2%) & \ help.file$ = in$ + h.command$ + "HELP.PHN" & \ open help.file$ for input as file 5% & \ for h.i% = 3% to 14% & \ inputline #5%, h$ & \ print #10%, fnPOSITION$(1%,h.i%) + left(h$,39%); & \ next h.i% & \ for h.i% = 3% to 14% & \ inputline #5%, h$ & \ print #10%, fnPOSITION$(41%,h.i%) + left(h$,39%); & \ next h.i% & \ goto 00755 & ! Clear out the top of the screen... & ! Open the file... & ! print the left half of the screen... & ! Print the right half... & ! Go back where we came from... & ! 00751 print #10%, "No Help available on that topic." & \ print #10%, 'Type "HELP" for help.' & ! We arrive here if there is no help for some obscure or & ! incorrect command. & ! 00755 close #5% & \ print #10%, fnPOSITION$(1%,23%) & \ fnHELP% = 1% & \ fnend & ! 00799 ! ====================================================== & ! & ! fnEXIT% & ! & ! Get the user out of phone gracefully and make the & ! terminal fit for human use. & ! ====================================================== & ! 00800 def fnEXIT%(e.command$) & \ print #10%, fnSCROLL.AREA$(1%,24%); & \ print #10%, erase.all$; & \ close 1% & \ goto 32767 & \ fnEXIT% = 1% & \ fnend & ! Reset the scrolling area... & ! Clear the screen... & ! Close up shop... & ! All Done. & ! 00849 ! ====================================================== & ! & ! fnJOB%(NameOrNumber) & ! & ! Find the job number of the name or number indicated by & ! the string passed into the routine. & ! ====================================================== & ! 00850 def fnJOB%(j.name$) & \ j.lb% = instr(1%,j.name$,"#") & \ j.job% = val(right(j.name$,j.lb%+1%)) if j.lb% & \ goto 00858 if j.lb% & \ j.job% = 1% & ! Its easy if they said "#n"... & ! 00855 j.jdb% = fnON%(j.job%) & \ j.job% = -1% if j.jdb% = -1% & \ goto 00860 if j.jdb% = -1% & \ goto 00857 if len(what$) = 0% & \ goto 00857 if not atch% & \ j.ppn% = fnMATCH.NAME%(j.name$) & \ goto 00857 if j.ppn% = 0% & \ goto 00860 if j.ppn% = swap%(p%) + pn% & ! Scan all the jobs to see if one has a directory name... & ! like the one specified. & ! Skip unattached, "non-present", and jobs just logging on... & ! 00857 j.job% = j.job% + 1% & \ goto 00855 & ! Increment and look at the next one... & ! 00858 j.jdb% = fnON%(j.job%) & \ j.job% = -1% if (j.jdb% = -1%) or (len(what$) = 0%) or (not atch%) & ! We don't want to call these guys... & ! 00860 fnJOB% = j.job% & \ fnend & ! 00869 ! ====================================================== & ! & ! fnANSR% & ! & ! This function is called to answer a phone that is & ! ringing. Once answered, the users can talk. & ! ====================================================== & ! 00870 def fnANSR%(a.command$) & \ open "CALL" + num1$(my.job%) + ".PHN" for input as file 4% & \ input #4%, a.job% & \ close #4% & \ kill "CALL" + num1$(my.job%) + ".PHN" & \ print #10%, "Job number";a.job%;'calling...' & \ a.i% = fnON%(a.job%) & \ open fnMAKE.PPN$(p%,pn%) + "ANSR" + num1$(a.job%) + ".PHN" for output as file 4% & \ close #4% & \ a.i% = fnHOOK.OFF%("") & \ a.i% = fnCONVERSE%(a.job%) & \ a.i% = fnHOOK.ON%("") & \ goto 00879 & ! Get the calling job's job number... & ! Get rid of the file... & ! Let the other job know that we picked up the phone... & ! by putting our job number into their ANSR??.phn file. & ! Take the phone off the hook... & ! Talk for awhile... & ! ANd hangup... & ! 00878 print #10%, "The phone is not ringing." & ! We arrive here if someone tried to answer a phone... & ! that was not ringing... & ! 00879 fnANSR% = -1% & \ fnend & ! 00880 ! ====================================================== & ! & ! fnRING%(Job, NumberOfRings) & ! & ! This function will ring a job's phone once and & ! decrements the ring counter. & ! ====================================================== & ! 00881 def fnRING%(r.job%, r.rings%) & \ r.ansr% = 0% & \ r.ansr$ = "ANSR" + num1$(my.job%) + ".PHN" & \ r.ring$ = "Your PHONE is ringing..." + cr$ + lf$ & \ r.i% = fnON%(r.job%) & \ r.kb% = kb% & \ r.file$ = fnMAKE.PPN$(p%,pn%) + "CALL" + num1$(r.job%) + ".PHN" & \ open r.file$ for output as file 4% & \ print #4%, my.job% & \ close #4% & ! Find out the other job's keyboard number... & ! CALL them with my job number... & ! 00885 goto 00890 if r.rings% = 0% & \ r.i% = fnBROADCAST%(r.kb%,r.ring$) & \ print #10%, "[ring "; fnLEFTPAD$(2%,num1$(r.rings%)); "] ", & \ r.rings% = r.rings% - 1% & \ sleep 3% & \ open r.ansr$ for input as file 4% & \ close #4% & \ kill r.ansr$ & \ r.ansr% = -1% & ! Ring their phone and wait for three seconds... & ! If we can open the file, they have answered... & ! 00890 kill r.file$ if not r.ansr% & \ fnRING% = r.ansr% & \ fnend & ! 00899 ! ====================================================== & ! & ! fnBUSY%(Job, p, pn) & ! & ! Returns true if a job's phone is busy. & ! & ! ====================================================== & ! 00900 def fnBUSY%(b.job%,b.p%,b.pn%) & \ b.busy% = 0% & \ b.busy% = -1% if (b.p% = 0%) and (b.pn% = 0%) & \ goto 00901 if b.busy% & \ b.ppn$ = fnMAKE.PPN$(b.p%,b.pn%) & \ open b.ppn$ + "PHON" + num1$(b.job%) + ".PHN" for input as file 5% & \ close #5% & \ b.busy% = -1% & ! The phone is busy if this file exits... & ! 00901 fnBUSY% = b.busy% & \ fnend & ! 00909 ! ====================================================== & ! & ! fnHOOK.OFF(Job) fnHOOK.ON(Job) & ! & ! These functions make a Job's phone busy, or not busy, & ! depending on the function. & ! ====================================================== & ! 00910 def fnHOOK.OFF%(ho.command$) & \ job$ = num1$(my.job%) & \ where$ = fnMAKE.PPN$(my.p%,my.pn%) & \ ho.lb% = instr(1%,ho.command$,"#") & \ priv% = (my.p% = 1%) & \ ho.job% = val(right(ho.command$,ho.lb% + 1%)) if ho.lb% and priv% & \ ho% = fnON%(ho.job%) if ho.lb% and priv% & \ where$ = fnMAKE.PPN$(p%,pn%) if ho.lb% and priv% & \ job$ = num1$(ho.job%) if ho.lb% and priv% & \ open where$ + "PHON" + job$ + ".PHN" for output as file 5% & \ close #5% & \ fnHOOK.OFF% = -1% & \ fnend & ! Lob a PHON??.PHN into the account, making it busy... & ! 00920 def fnHOOK.ON%(ho.command$) & \ job$ = num1$(my.job%) & \ where$ = fnMAKE.PPN$(my.p%,my.pn%) & \ ho.lb% = instr(1%,ho.command$,"#") & \ priv% = (my.p% = 1%) & \ ho.job% = val(right(ho.command$,ho.lb% + 1%)) if ho.lb% and priv% & \ ho% = fnON%(ho.job%) if ho.lb% and priv% & \ where$ = fnMAKE.PPN$(p%,pn%) if ho.lb% and priv% & \ job$ = num1$(ho.job%) if ho.lb% and priv% & \ kill where$ + "PHON" + job$ + ".PHN" & ! Kill a PHON??.PHN if we can... & ! 00921 fnHOOK.ON% = -1% & \ fnend & ! Catch the error if we can't & ! 00999 ! ====================================================== & ! & ! fnCONVERSE%(Job) & ! & ! Converse with the job specified. & ! & ! ====================================================== & ! 01000 def fnCONVERSE%(c.job%) & \ my.x% = 1% & \ my.y% = 17% & \ print #10%, fnERASELINE$(c.i%); for c.i% = 2% to 14% & \ print #10%, fnERASELINE$(c.i%); for c.i% = 17% to 24% & \ print #10%, fnPOSITION$(1%,4%) + halfintensity$ + underline$ + grfchrset$ & \ print #10%, dash$ + reset.attributes$ + ascchrset$; & \ c.i% = fnON%(c.job%) & \ c.name$ = "" & \ c.name$ = cvt$$(fnNICK.NAME$(p%,pn%),128%) if not playback% & \ c.name$ = "" if playback% & \ c.name$ = "#" + num1$(c.job%) if len(c.name$) = 0% & \ print #10%, fnPOSITION$(40% - (len(c.name$)/2%),6%); & \ print #10%, bold$ + c.name$ + reset.attributes$; & \ print #10%, fnPOSITION$(29%,3%) + "Type to hang up." & \ print #10%, fnPOSITION$(my.x%,my.y%); & \ close #1% if not playback% & \ open "KB:" as file 1%, mode 1% if not playback% & ! Clear out the windows... & ! Print the proper headers... & ! Put the keyboard in binary mode... & ! 01005 b$ = fnGET$(inp$) & ! Get a buffer full of keystrokes (from somewhere) & ! 01010 goto 01005 if len(b$) = 0% & \ c$ = left(b$,1%) & \ b$ = right(b$,2%) & \ b$ = lf$ + b$ if c$ = cr$ and not playback% & \ i% = fnRECORDING% if c$ = chr$(18%) & \ goto 01010 if c$ = chr$(18%) & \ print #5%, c$; if recording% & \ goto 01010 if c$ = chr$(2%) or c$ = chr$(3%) & \ goto 01015 if c$ = chr$(1%) & \ c$ = chr$(2%) if c$ = chr$(127%) & \ c$ = chr$(4%) if c$ = chr$(27%) & \ c.i$ = fnPUT$(fnPOSITION$(my.x%,my.y%)) & \ c.i$ = fnPUT$(chr$(8%) + " " + chr$(8%)) if c$ = chr$(2%) & \ c.i$ = fnPUT$(c$) if (c$ <> chr$(2%)) and (c$ <> chr$(4%)) & \ send.them$ = chr$(1%) + chr$(32% + my.x%) + chr$(32% + my.y%) + c$ & \ c.i% = fnFORCE%(kb%,send.them$) if not playback% & \ goto 01020 if c$ = chr$(4%) & \ my.x% = my.x% + 1% if ascii(c$) >= 32% & \ my.x% = my.x% + 8% if c$ = chr$(9%) & \ my.x% = my.x% - 1% if (c$ = chr$(8%)) or (c$ = chr$(2%)) & \ my.x% = 1% if c$ = chr$(13%) & \ my.y% = my.y% + 1% if c$ = chr$(10%) & \ my.y% = my.y% + 1% if my.x% > 80% & \ my.x% = 1% if my.x% < 1% & \ my.y% = 17% if my.y% < 17% & \ my.x% = 1% if my.x% > 80% & \ my.y% = 24% if my.y% > 24% & \ goto 01010 & ! Get a character to work on... & ! B$ = CDR(B$) & ! Add a linefeed if we typed a carriage return... & ! Start recording if it was a CTRL-R & ! and swallow it. & ! Save the character if we are taping it... & ! Swallow the character if it was one of special "delimiters" & ! Go below if it was from the other user... & ! Put the character in our window... & ! Packet it up with a ^A in front, my (X,Y) cooordinates... & ! the character, and ship it to them... & ! Get out if we are hanging up...& ! Else update my screen coordinates and get the next character... & ! 01015 them.x% = ascii(left(b$,1%)) - 32% & \ print #5%, left(b$,3%); if recording% & \ b$ = right(b$,2%) & \ them.y% = ascii(left(b$,1%)) - 32% - 10% & \ b$ = right(b$,2%) & \ c$ = left(b$,1%) & \ b$ = right(b$,2%) & \ goto 01010 if (them.y% > 14%) or (them.y% < 7%) & \ goto 01010 if (them.x% < 1%) or (them.x% > 80%) & \ c.i$ = fnPUT$(fnSCROLL.AREA$(7%,14%) + fnPOSITION$(them.x%,them.y%)) & \ c.i$ = fnPUT$(chr$(8%) + " " + chr$(8%)) if c$ = chr$(2%) & \ goto 01020 if c$ = chr$(4%) & \ c.i$ = fnPUT$(c$) if c$ <> chr$(2%) & \ c.i$ = fnPUT$(fnSCROLL.AREA$(17%,24%) + fnPOSITION$(my.x%,my.y%)) & \ goto 01010 & ! They sent us a character so we had better put it in their... & ! window, and get out if they hung up on us... & ! 01020 close #1% & \ close #2% & \ open "KB:" as file 1%, mode 16384% & \ print #10%, & \ i% = fnRECORDING% if recording% & \ print #10%, & \ print #10%, "[click]" & \ print #10%, fnSCROLL.AREA$(17%,24%) + fnPOSITION$(1%,23%) & \ print #10%, "[dial tone]" & \ fnCONVERSE% = -1% & \ fnend & ! Close up shop... & ! Stop the recording... & ! Reset the screen... & ! And stop talking... & ! 01099 ! ====================================================== & ! & ! fnRECORDING & ! & ! Toggles the recording flag and updates the top of the & ! terminal screen. & ! ====================================================== & ! 01100 def fnRECORDING% & \ recording% = not recording% & \ r$ = fnPUT$(fnERASELINE$(4%)) if not recording% & \ close #5% if not recording% & \ goto 01110 if not recording% & \ open "RECORD.PHN" for output as file 5% & \ r$ = "Recording..." & \ r.p$ = fnPUT$(fnPOSITION$(40% - (len(r$)/2%),4%)) & \ r$ = fnPUT$(blink$ + r$ + reset.attributes$) & ! 01110 fnRECORDING% = recording% & \ r$ = fnPUT$(fnPOSITION$(my.x%,my.y%)) & \ fnend & ! 01199 ! ====================================================== & ! & ! fnPLAY% & ! & ! Fakes a converastion with a file. The recorded & ! conversation is stored in RECORD.PHN & ! ====================================================== & ! 01200 def fnPLAY%(p.command$) & \ playback% = -1% & \ open "RECORD.PHN" for input as file 4% & \ p.i% = fnHOOK.OFF%(p.command$) & \ p.i% = fnCONVERSE%(my.job%) & \ p.i% = fnHOOK.ON%(p.command$) & ! 01201 close 4% & \ playback% = 0% & \ print #10%, fnPOSITION$(1%,23%) & \ fnPLAY% = -1% & \ fnend & ! 10000 ! ============================================== & ! & ! M A I N & ! & ! ============================================== & ! 10010 print #10%, erase.all$; & \ list.page% = 0% & \ recording% = 0% & \ playback% = 0% & \ JOBTBL% = swap%(cvt$%(mid(sys(fip$ + chr$(-3%)),11%,2%))) & \ dim m%(30%) & \ i$ = sys(fip$ + chr$(9%) + chr$(0%)) & \ change i$ to m% & \ header$ = hdr$ + right(i$,3%) & \ print #10%, fnPOSITION$(40% - (len(header$)/2%),1%); & \ print #10%, bold$ + header$ + reset.attributes$ & \ my.job% = m%(1%)/2% & \ my.kb% = m%(2%)/2% & \ i% = fnON%(my.job%) & \ my.p% = p% & \ my.pn% = pn% & \ my.name$ = cvt$$(fnNICK.NAME$(my.p%,my.pn%),128%) & \ prompt$ = '> ' & \ dash$ = string$(80%,111%) & \ print #10%, fnPOSITION$(1%,14%) + halfintensity$ + underline$ + grfchrset$ & \ print #10%, dash$ + reset.attributes$ + ascchrset$; & \ my.header$ = my.name$ if len(my.name$) > 0% & \ my.header$ = '#' + fnLEFTPAD$(2%,num1$(my.job%)) if len(my.name$) = 0% & \ print #10%, fnPOSITION$(40% - (len(my.header$)/2%),16%); & \ print #10%, bold$ + my.header$ + reset.attributes$ & \ print #10%, fnSCROLL.AREA$(17,24%); & \ open 'KB:' as file 1%, mode 16384% & \ print #10%, fnPOSITION$(1%,23%) & ! Clear the screen and get set up... & ! reset all flags... & ! Get a pointer to the system job table... & ! Print the header... & ! Find out MY job number and keyboard number... & ! Get my NICK.NAME if I have one... & ! Print it... & ! Make only the bottom of the screen scroll... & ! 10015 open "CALL" + num1$(my.job%) + ".PHN" for input as file 4% & \ close #4% & \ i% = fnANSR%("ANSWER") & ! Answer the phone if it is ringing... & ! 10020 print #10%, prompt$; & \ inputline #1%, command$ & \ command$ = cvt$$(command$, 4% + 8% + 16% + 64% + 128%) & \ goto 10020 if len(command$) = 0% & \ ok% = 0% & \ ok% = fnALIAS%(command$) if instr(1%,command$,"=") & \ cmnd$ = left(cvt$$(command$,32%),2%) & \ ok% = fnWHO%(cmnd$) if cmnd$ = "WH" or cmnd$ = "SY" & \ ok% = fnDIR%(command$) if cmnd$ = "DI" & \ ok% = fnCALL%(command$) if cmnd$ = "CA" & \ ok% = fnANSR%(command$) if cmnd$ = "AN" & \ ok% = fnLIST%(command$) if cmnd$ = "LI" & \ ok% = fnSORT%(command$) if cmnd$ = "SO" & \ ok% = fnPLAY%(command$) if cmnd$ = "PL" & \ ok% = fnHELP%(command$) if cmnd$ = "HE" & \ ok% = fnHELP%("HELP " + right(command$,2%)) if cmnd$ = "?" & \ ok% = fnEXIT%(command$) if cmnd$ = "EX" & \ ok% = fnEXIT%(command$) if cmnd$ = "X" & \ ok% = fnHOOK.OFF%(command$) if cmnd$ = "OF" & \ ok% = fnHOOK.ON%(command$) if cmnd$ = "ON" & \ print #10%, "Unrecognized command - "; command$ if ok% = 0% & \ goto 10020 & ! Otherwise, get and process commands until we are told to quit. & ! 29999 ! & & ! E R R O R R O U T I N E S & & ! 30000 er.i$ = sys(fip$ + chr$(-7%)) & \ resume if err = 28% & \ resume 00901 if (err = 5%) and (erl = 00900) & \ resume 00652 if (err = 5%) and (erl = 00651) & \ resume 10020 if (err = 5%) and (erl = 10015) & \ resume 00885 if (err = 5%) and (erl = 00885) & \ resume 00878 if (err = 5%) and (erl = 00870) & \ resume 00921 if (err = 5%) and (erl = 00920) & \ resume 01201 if (err = 5%) and (erl = 01200) & \ print #10%, "*"; if (err = 52%) and (erl = 01015) & \ resume 00751 if erl = 00750 & \ resume 01010 if erl = 01015 & \ print #10%, '[';num1$(err);',';num1$(erl);']' & \ print #10%, "?Illegal Project,Programmer Number." if err = 52% & \ close #4% if (erl = 500) or (erl = 280) & \ resume 00510 if err = 52 and erl = 00500 & \ gosub 31000 if err = 5% and erl= 00280 & ! 30999 resume & ! 31000 open "DIRECT.PHN" for output as file 4% & \ print #10%, "Phone Directory Initialized." & \ alias$(0%) = cvt%$(0%) & \ close #4% & \ sleep 3% & \ return & ! We arrive here if there is no directory yet... & ! We must initialize it to zero entries. & ! 32767 end & !