






                Advanced Function Library for the BASIC Compiler


                              ADVBAS v99, 04/02/88

                   Copyright (C) Thomas Hanlin III, 1985-1988

                              1712 Maple Hill Place
                              Alexandria, VA 22302





     Requirements:

          An  IBM  PC  or compatible with the IBM BASIC Compiler v2.x or any
     Microsoft  QuickBASIC  Compiler.   PC-DOS/MS-DOS versions 2.0 or higher
     should  be  used.   Some  functions  may require a PC AT or compatible,
     as noted.  Please read the Operation Notes.

          NOTE  that  this  is  the  final release of ADVBAS.  There will be
     no  further  releases.   As  of  August  1, 1988, I will not accept any
     further  contributions,  so  if you want the source code, get it before
     then.   I  have  decided  to  abandon  shareware entirely, for a number
     of reasons...

          While  ADVBAS  is  full-featured  and  is not crippled in any way,
     I'd  like  you  to  consider  it as a sample of the commercial library,
     ProBas.   You  may  use  ADVBAS  subject to the restrictions below, but
     you  will  be  much better off by upgrading to ProBas.  ProBas contains
     nearly  twice  the  routines in ADVBAS, and comes with a printed manual
     of  nearly  600  pages,  with tutorial and reference sections.  See the
     PROBAS.DOC file for further information on ProBas.


     Copying and Distribution:

          ADVBAS  may  be  copied  and  distributed  freely  EXCEPT  FOR THE
     ASSEMBLY  SOURCE  CODE.   If  you  distribute  ADVBAS on communications
     systems  such  as  BBSes  or  CompuServe,  the  Source, et al, you must
     include  a  minimum  of  the following unmodified files as a set (using
     ARC   or  an  equivalent  archive  utility):   ADVBAS.EXE,  ADVBAS.LIB,
     ADVBAS.DOC,   ADVBAS.NEW,   ADVBAS.QRF,  ADVBAS.ERR,  CONTRIB.DOC,  and
     PROBAS.DOC.   No  fee  other  than a disk and handling charge (of up to
     $10) may be charged.

          The  copyright  is to preserve my options, and to protect you from
     the  untoward  modifications  of others.  It is not intended to prevent
     the public distribution of ADVBAS, subject to the above limitations.
















     Introduction:

          The  BASIC  Compiler  is  a  powerful and flexible tool.  However,
     it  suffers  from  a  number of limitations.  It is hard to access many
     of  the  capabilities of DOS; any feature which requires error trapping
     cannot  be  used  in  a  subprogram; the memory requirements are fairly
     substantial;  and  the  speed  is not all that it might be, for all its
     improvement  over  interpreted  BASIC.   To reduce these problems, I've
     designed  a  number of assembly language routines which perform various
     functions,  and  put  them  in a library which the compiler can access.
     Since  I  have  found  these functions to be useful, I thought I'd pass
     them  on  to other people.  You may use ADVBAS functions in any of your
     programs.   I'd appreciate it if you acknowledged use of these routines
     in your program or documentation.

          If  you  find  ADVBAS useful, please support the author's efforts!
     A minimum contribution of $25 will get you a disk containing the latest
     version  of  ADVBAS,  including  source  and object code, PROVIDED THAT
     YOU  SEND  IT  IN  BEFORE  AUGUST  1,  1988!  After then, I will not be
     accepting any further contributions.



     Support:

          Please  read  this  manual  before  calling  me with any problems.
     You can probably find the answer here, and save us both trouble. 
          If  you  are  a  contributor  (bless you!), I'll certainly be glad
     to  help  you  with  any  difficulties you may encounter.  U.S. Mail is
     the  preferred  method  of  exchange,  but  feel  free  to  call if the
     situation gets out of hand.

          If  you  are  not  a  contributor  (sigh), please send a SASE, and
     I'll  get  back to you.  PLEASE do not phone!  If you don't care enough
     to  contribute  the minimal fee I ask, you should not expect me to pro-
     vide services.  TANSTAAFL!  (There Ain't No Such Thing As A Free Lunch)



     Caveats:

          These  functions  have  not  caused  me  any problems, and seem to
     be  fully debugged.  However, I will not be responsible for any damages
     caused by use, misuse, or inability to use ADVBAS.

          If  you run into problems, please read through the first few pages
     of the manual.  All the information you need to use ADVBAS is in there.



















     Misc. Notes:

          This  is  the  final shareware release of ADVBAS.  I will continue
     to  support  it,  but I will not be releasing any new versions.  ADVBAS
     is  being  replaced  by  the  ProBas  library,  which is being marketed
     through commercial channels.

          ProBas  contains  about  twice  as many routines as ADVBAS.  Among
     other goodies: sorting, expanded memory support, dynamic array support,
     improved mouse routines, new equipment detection and control functions,
     more  flexible  screen  handling,  an improved pop-up window generator,
     controllable  field  input  with  editing,  "long" number support (even
     if  you  don't  have  QuickBASIC 4.0!), and much more.  One of the more
     powerful  capabilities  provided  by ProBas lies in a full set of func-
     tions  to  support  "virtual  screens".  These are screens which can be
     set  up  in memory, and then displayed (entirely or in part) instantly.
     Using  conventional  or  expanded  memory,  you  can  store hundreds of
     screens  in  memory  for instant recall.  This is similar to the paging
     ability  of  EGA  and most CGA displays, but will work with any system,
     and is not limited to just a few screens of information.

          An  extensive  (600-page)  printed  user  manual contains detailed
     information  on  the  routines  in  a  format that is equally suited to
     the  novice  or  the professional.  Fully documented demonstration code
     in BASIC is also provided.

          ProBas  is  priced  at  $99.00.   Shipping is $3.00.  Sales tax is
     applicable   for  Maryland  residents.   There  is  an  order  form  in
     PROBAS.DOC, or you may address your ProBas order to:

          HCSI
          8008 Sandy Spring Rd
          Laurel, MD 20707

          For  more  information,  write  to  the  above address, or you can
     call  (301)  953-2191.   C.O.D. orders  are  accepted,  and credit card
     orders will hopefully be accepted in the near future.





























     Using ADVBAS with QuickBASIC 4.0:

          Note  the  list  of  bugs  in  QuickBASIC  4.0  at the end of this
     manual!  Some of them affect ADVBAS functions, so read up!

          If  you  use  QuickBASIC  in the programming environment, you need
     to  have  a copy of ADVBAS.QLB in the drive/subdirectory where you keep
     your  library  files  (like BRUNxx.LIB).  When you start up QuickBASIC,
     you  need  to  tell  it  to  load the ADVBAS library so you can use its
     features.   Run  QuickBASIC  with the following syntax: "QB /L ADVBAS".
     You  may  also  specify a program to load: "QB MYPROG /L ADVBAS".  Note
     that  you  are  not  meant  to  type in the quotes, which are there for
     guidance  only.   You  may  also  need to include a drive/path spec for
     ADVBAS  if  it  is  in  a  different drive/path than the default (which
     is  either  the current area, or the area specified by the DOS environ-
     ment  variable  "LIB").   That might look something like the following:
     "QB /L C:\LIB\ADVBAS"



     Using ADVBAS with QuickBASIC 2.0 - 3.0:

          If  you  use  QuickBASIC  in the programming environment, you need
     to  have  a copy of ADVBAS.EXE in the drive/subdirectory where you keep
     your  library  files  (like BRUNxx.LIB).  When you start up QuickBASIC,
     you  need  to  tell  it  to  load the ADVBAS library so you can use its
     features.   Start  up  QuickBASIC using the syntax: "QB /L ADVBAS.EXE".
     You  may  also  specify  a program to load: "QB PROGRAM /L ADVBAS.EXE".
     Note  that  you  are  not  meant to type in the quotes, which are there
     for  guidance  only.   You  may  also need to include a drive/path spec
     for  ADVBAS  if it is in a different drive/path than the default.  That
     might look something like "QB /L C:\LIB\ADVBAS.EXE".



     Using IBM or Microsoft BASIC compilers (command-line mode):

          Copy  ADVBAS.LIB to the disk on which you keep your BASIC Compiler
     library files.  For programs which use ADVBAS functions, specify ADVBAS
     when  LINK  asks  you  which  libraries to use.  That is, at the LINKer
     prompt  "Libraries  [.LIB]:"  you  should  say  "ADVBAS"  (without  the
     quotes!).   You  may  need to provide a drive/path spec if your program
     is  not  in  the  same area that ADVBAS is, and if you don't have a SET
     LIB  in  your  autoexec  file to tell the compiler where the library is
     (only newer versions of the compilers have this feature). 





















     Other languages:

          A  library  for  Microsoft  C is available under the name of ADVC.
     It  is  in  C  source  format, so you can convert any nonstandard func-
     tions  to  your  own  variety of C.  If you can't find it on your local
     BBS,  I'll  send  you  a  copy for the recommended minimum contribution
     of  $15,  IF  YOU  SEND  IT  IN BEFORE AUGUST 1, 1988.  Updates are not
     anticipated.

          Commercial  versions  of  the  ADVBAS library to support languages
     other  than  BASIC  will  be  shipping  in early 1988.  Languages to be
     supported  are  Microsoft  C,  Pascal,  and  FORTRAN compilers, as well
     as assembly language.  There will be no support for Borland's languages
     until they come up with a decent way to handle libraries.




     Advantages of ADVBAS:

          1) Adds abilities which are not otherwise available.
          2) Is faster than the corresponding Compiled BASIC code.
          3) Usually takes up less space in the resulting EXEcutable file.
          4) Often leaves more free programming space.
          5) Provides a useful library of tested low-level routines.









































                                 Operation Notes




     Function Requirements:

          Numeric  variables  used in function calls must be integers unless
     specified  otherwise.   Either declare them using DEFINT, or add a per-
     cent sign "%" to the end of the variable name.

          Strings  must  sometimes  be  defined to a certain minimum length,
     due  to  limitations  on  what  assembly  language routines are allowed
     to do to strings. 

          Dynamic Arrays cannot be used interchangeably with normal (Static)
     arrays.   Use  only  static arrays with functions which require arrays.
     Note  that  functions  requiring  static  arrays  cannot be used in the
     QuickBASIC  4.0  environment,  due to a QB bug.  However, you may still
     use them in the stand-alone version of the compiler, BC. 



     Compatibility:

          These  functions  vary in what they demand of your PC.  Some func-
     tions  will  work only on IBM PCs or clones, some will work on compati-
     bles,  and  some  will  work  on any MS-DOS machine.  The compatibility
     level  of each function is now listed, using the categories CLONE (will
     work  on  hardware  compatibles  only),  BIOS  (close compatibles), DOS
     (any  MS-DOS  machine), and ANY (hardware independent).  Be warned that
     the  BASIC  Compiler  itself  does  not produce particularly compatible
     code (BASIC video routines seem to be BIOS-compatible, etc).

































                                Routine Reference




     Disk:
          CopyFile:  copy a file
          DelSub, GetSub, MakeSub, SetSub:  subdirectory handling
          DiskStat:  assorted disk status information
          DrvSpace:  space left on a given drive
          Exist:  see if a file exists
          Fclose, Fcreate, Fopen, Fread, FsetEnd, FsetRec, Fclose:
             file i/o
          FindFirstF, FindNextF:  handle file(s) with wildcards
          GetDrv, SetDrv:  get/set the default drive
          GetFdate, GetFtime, SetFTD, GetFattr, SetFattr:  file info control
          GetNameF, GetDateF, GetTimeF, GetAttrF, GetSizeF: file dir control
          Mload:  a BLOAD routine
          SubExist:  see if a subdirectory exists

     Input:
          ClrKbd:  clear the keyboard buffer of pending keys
          DosInkey:  get a key using DOS standard input
          GetKbd, SetKbd:  get/set the status of the keyboard toggles
          GetKey:  get one of a list of valid keys
          KeyPress:  see if a key has been pressed

          MMcursorOn, MMcursorOff:         mouse cursor control
          MMgetloc, MMsetloc, MMsetrange:  mouse display control
          MMbutton, MMcheck, MMclick:      mouse status info

     String:
          Bsq, BusqLen, Busq:  text compression/decompression
          Checksum, CRC:  error checking (for telecomm and other uses)
          Crunch:  remove duplicates of a character from a string.
          DateN2S, DateS2N:  convert the date (numbers <--> string)
          Extract:  take delimited substrings from a string using an index
          Locase, Upcase:  case conversion
          MultiAnd, MultiOr, MultiXor:  bit manipulations on strings
          Strip, StripBlanks, StripRange:  deletion of chars from a string
          LRotate, RRotate, Reverse:  reorder chars in a string
          Soundex:  return the Soundex code of a string
          TimeN2S, TimeS2N:  convert the time (numbers <--> string)
          Tinstr:  find a given type of char within a string
          Xlate:  run the chars of a string through a translation table





















                                Routine Reference




     Array:
          AddMatI, SetMatI:  integer array manipulation
          ReadBitF, WriteBitF:  handle arrays of arbitrary bit length

     Video:
          CalcAttr:  calculate attribute from fore and background colors
          ClrEol, BkSpace, DelChr, InsChr, MDelChr, MInsChr:  screen control
          DMprint, Mprint, MprintC, Qprint, XQprint:  various print routines
          GetCRT:  get display type (mono or color)
          MakeWindow:  make pop-up windows
          Mwindow, Scroll, BkScroll:  display window control
          PrintScreen:  print out the display to the default printer
          ScrSave, ScrRest, GetLine:  save/restore the contents of a screen
          ScrSaveP, ScrSavePD, ScrRestP, ScrRestPD:  variants on the above
          GetScreen, PutScreen:  new flexible screen save/restore routines
          ReColor: change any screen color to another w/o clearing screen
          ResetPoint, SetPoint, TestPoint:  low-res graphics in text mode

     Miscellaneous:
          Any2Dec, Dec2Any:  radix conversion (decimal <--> another base)
          BlockMove:  move data from one area of memory to another
          Carrier:  check modem Carrier Detect signal
          DataSeg:  return the value of the default Data Segment
          Date2int, Int2date:  date compression
          Delay, Delay18th:  delay for a given amount of time
          DTR:  turn the communications line "DTR" on or off
          Equipment:  get hardware info about memory and installed ports
          GetDOSv:  get the version number of the MS-DOS being used
          GetExtM:  return the amount of extended memory (AT systems only)
          GetLIMM:  get the status of expanded memory in the system
          Month:  given a month number, returns the name of the month
          SetComm:  set up any comm port to any baud, without closing comm
          ShiftL, ShiftR:  bit shifts for integers
          Speaker:  turns sound effects on or off
          Time2int, Int2time:  time compression
          WeekDay:  returns the day of the week, Sunday through Saturday

























                               Compatibility Chart




     Works on ANY machine:

          ADDMATI,   ANY2DEC,   BLOCKMOVE,  BSQ,  BUSQ,  BUSQLEN,  CALCATTR,
     CHECKSUM,  CRC,  CRUNCH,  DATASEG, DATE2INT, DEC2ANY, EXTRACT, GETLINE,
     INT2DATE,   INT2TIME,   LOCASE,   LROTATE,  MONTH,  MULTIAND,  MULTIOR,
     MULTIXOR, READBITF, REVERSE, RROTATE, SETMATI, SHIFTL, SHIFTR, SOUNDEX,
     STRIP,  STRIPBLANKS,  STRIPRANGE,  TIME2INT, TINSTR, UPCASE, WRITEBITF,
     XLATE



     Works on DOS compatibles:

          COPYFILE,  DELSUB,  DISKSTAT,  DMPRINT, DOSINKEY, DRVSPACE, EXIST,
     FCLOSE, FCREATE, FINDFIRSTF, FINDNEXTF, FOPEN, FREAD, FSETEND, FSETREC,
     FWRITE,   GETATTRF,  GETDATEF,  GETDOSV,  GETDRV,  GETFATTR,  GETFDATE,
     GETFTIME, GETNAMEF, GETSIZEF, GETSUB, GETTIMEF, MAKESUB, MLOAD, SETDRV,
     SETFATTR, SETFTD, SETSUB, SUBEXIST, WEEKDAY



     Works on BIOS compatibles (* if it requires the AT BIOS):

          BKSCROLL,  BKSPACE,  CARRIER,  CLRKBD,  CLREOL,  DATEN2S, DATES2N,
     DELAY,   DELAY18TH,   EQUIPMENT,  GETCRT,  GETEXTM*,  GETKEY,  GETLIMM,
     KEYPRESS,  MDELCHR,  MINSCHR,  MMBUTTON, MMCHECK, MMCLICK, MMCURSOROFF,
     MMCURSORON,  MMGETLOC,  MMSETLOC, MMSETRANGE, MPRINT, MPRINTC, MWINDOW,
     PRINTSCREEN, RESETPOINT, SETPOINT, SCROLL, TESTPOINT, TIMEN2S, TIMES2N,
     XMPRINT



     Works on CLONEs (hardware compatibles):

          DELCHR,  DTR,  GETKBD,  GETSCREEN,  INSCHR, MAKEWINDOW, PUTSCREEN,
     QPRINT,  RECOLOR,  SCRREST,  SCRRESTP,  SCRRESTPD,  SCRSAVE,  SCRSAVEP,
     SCRSAVEPD, SETCOMM, SETKBD, SPEAKER, XQPRINT, XQPRINTD



          Note  that  routines  from  higher  sections will work on machines
     from  lower  sections  (DOS-level  routines  will  work  on  BIOS-  and
     CLONE-level   machines).    It   doesn't  work  the  other  way  around
     (CLONE-level routines may not work on a DOS-level machine).

















     Name: ADDMATI

     Type: Miscellaneous / ANY

     Description:
          Adds a scalar (integer) value to the first SIZ elements of an
     integer  array.   You  can  subtract  by  adding a negative number.  If
     the  results  of  the calculation ever go outside integer range (-32768
     to  32767),  the  overflow flag is set on return.  See SETMATI for more
     information.

     Example:
          OPTION BASE 1: DIM ACK%(10000): SIZ%=10000
           .
           .
          ADDVAL%=-6: ARLOC%=VARPTR(ACK%(1))
          CALL ADDMATI(ARLOC%,SIZ%,ADDVAL%,OVFLOW%)
          IF OVFLOW% THEN PRINT"Uh oh, overflowed somewhere..."
          REM  we just subtracted six from each element of the array ACK.




     Name: ANY2DEC

     Type: Miscellaneous / ANY

     Description:
          Converts  a  number  (in  string  form)  from any base (2-35) to a
     decimal integer (base 10).  The number to be converted may be in either
     signed  integer  range  (-32768  to 32767) or unsigned integer range (0
     to  65535).   It  is  converted  to a signed integer, which is the only
     integer type BASIC supports.

     Example:
          INPUT"Number, base of number";ANUM$,NBASE%
          CALL ANY2DEC(ANUM$,NBASE%,DNUM%,ERCD%)
          IF ERCD% THEN PRINT"Bad number!" ELSE PRINT"Decimal: ";DNUM%




























     Name: BKSCROLL

     Type: Video / BIOS

     Description:
          The  same  as  SCROLL  (q.v.),  but  scrolls lines in the opposite
     direction (Back Scroll).

     Example:
       
          CALL BKSCROLL(LEFTCOL%,TOPROW%,RTCOL%,BOTROW%,NUMLINES%)




     Name: BKSPACE

     Type: Video / BIOS

     Description:
          Move  cursor back one space, destroying the character on the space
     moved  to.   Will  wrap  from one line to the next higher if necessary.
     If  at  the  top  left  corner  of  the screen, no action is performed.
     Two  arguments  return  the  new  cursor coordinates.  Works with 40 or
     80 column screens in text mode.

     Example:
          CALL BKSPACE(COL%,ROW%): LOCATE ROW%,COL%







































     Name: BLOCKMOVE

     Type: Miscellaneous / ANY

     Description:
          Copies information from one area of memory to another.  You supply
     the  source  segment and offset, destination segment and offset, number
     of  bytes  to  move (0 - 65535), and direction (zero, forward; nonzero,
     backward).   This  can  be  used,  for  instance,  to duplicate numeric
     arrays. including dynamic arrays.

     Example:
     CALL BLOCKMOVE(FROMSEG%,FROMOFFSET%,TOSEG%,TOOFFSET%,BYTES%,DIRECTION%)




     Name: BSQ

     Type: String / ANY

     Description:
          Uses  several  techniques to compress blank spaces out of an ASCII
     string.   Savings  range  from  16% (reliable, for ordinary text) to up
     around 50% or more for space-intensive info, such as lines in an assem-
     bly  source  file.   BSQ  cannot  handle  more than 127 spaces in a row
     on  a  single  line,  or  lines  which contain ASCII characters greater
     than  127  (which  are  IBM-specific  graphics characters).  Do not use
     BSQ  on  lines  which  may  contain  such information!  BSQ compression
     is  designed  to  produce printable (if odd-looking) text which you may
     read/write to ordinary sequential files.

     Example:
          INPUT"String to squeeze";ST$: CALL BSQ(ST$,SLEN%)
          PRINT"Squeezed string: ";LEFT$(ST$,SLEN%)




     Name: BUSQ

     Type: String / ANY

     Description:
          Decompresses  a  line  squeezed  by  BSQ.  Use BUSQLEN before this
     routine to find out how long the unsqueezed line will be!

     Example:
          see BUSQLEN

















     Name: BUSQLEN

     Type: String / ANY

     Description:
          Tells  how  long  a  line  squeezed  with  BSQ  will  be once it's
     unsqueezed.  You must use this before unsqueezing the line with BUSQ.

     Example:
          CALL BUSQLEN(ST$,SLEN%)
          IF SLEN%<0 THEN line not squeezed, or damaged-- exit!
          ELSE UNSQ$=SPACE$(SLEN%): CALL BUSQ(ST$,UNSQ$)




     Name: CALCATTR

     Type: Video / ANY

     Description:
          Calculates  the  color  attribute  for  such  routines as XQPRINT.
     Unlike  the  BASIC  formula  it  replaces,  CALCATTR  allows use of the
     "blink" attribute.

     Example:
          REM  old formula was  ATTR% = (BACKGND% AND 7)*16 + FOREGND%
          CALL CALCATTR(FOREGND%,BACKGND%,ATTR%)




     Name: CARRIER

     Type: Miscellaneous / BIOS

     Description:
          Returns  the  status  of the modem Carrier Detect signal.  You may
     specify communications port one or two.

     Example:
          COMMPORT% = 1
          CALL CARRIER(COMMPORT%,CDSTATUS%)
          IF CDSTATUS% THEN PRINT "Carrier detected" ELSE PRINT "No carrier"






















     Name: COPYFILE

     Type: Disk / DOS

     Description:
          Copies a file.  This is faster than the corresponding DOS command,
     and  doesn't  have  the  overhead of using the SHELL command.  Note: to
     avoid  possibly  wiping  out  an  existing file on the destination end,
     you may wish to use the EXIST function before this one.
          The  copy  will  usually  fail  for one of two reasons: the source
     file  doesn't  exist,  or  there is not enough room on the disk for the
     destination file.

     Example:
          SOURCE$="A:EXAMPLE.TXT"+CHR$(0)
          DESTINATION$="C:\DOCUMENT\EXAMPLE.TXT"+CHR$(0)
          CALL COPYFILE(SOURCE$,DESTINATION$,ERRCODE%)
          IF ERRCODE% THEN PRINT"The copy failed"
















































     Name: CHECKSUM

     Type: Miscellaneous / ANY

     Description:
          Calculates  a  checksum  for  a  record.   Can be used with Xmodem
     or Ymodem.

     Example:
          CALL CHECKSUM(REC$,CHKSM%)




     Name: CLREOL

     Type: Video / BIOS

     Description:
          Clears  from  the  cursor  position to the end of the line without
     moving the cursor.

     Example:
          CALL CLREOL




     Name: CLRKBD

     Type: Input / BIOS

     Description:
          Clears any pending keys from the keyboard buffer.

     Example:
          CALL CLRKBD
          INPUT"File not found.  Continue (Y/N)";ANS$




























     Name: CRC

     Type: Miscellaneous / ANY

     Description:
          Calculates  a  cyclical redundancy check value for a record.  This
     is  useful  for  error  detection,  and  can be used with Xmodem CRC or
     Ymodem CRC modem transfer protocols.

     Example:
       Sending a record:
          REC$=REC$+STRING$(2,0) : CALL CRC(REC$,HICRC%,LOCRC%) :
          MID$(REC$,LEN(REC$)-1,2) = CHR$(HICRC)+CHR$(LOCRC%)
          REM  we're set to send an Xmodem record
       Receiving a record:
          CALL CRC(REC$,HICRC%,LOCRC%) : IF HICRC%=0 AND LOCRC%=0
               THEN record is fine, save it
               ELSE record is bad, request it to be sent again




     Name: CRUNCH

     Type: String / ANY

     Description:
          Crunches  duplicates  of  a  given  character  in a string down to
     a single character.

     Example:
          ST$="This####is#a##test"
          CH$="#"
          CALL CRUNCH(ST$,CH$,SLEN%)
          ST$=LEFT$(ST$,SLEN%)
          REM  the result here will be "This#is#a#test"






























     Name: DATASEG

     Type: Miscellaneous / ANY

     Description:
          Returns  BASIC's  data  segment.   This  is  useful for BLOCKMOVE,
     among other things.

     Example:
          CALL DATASEG(DSEG%)




     Name: DATE2INT

     Type: Miscellaneous / ANY

     Description:
          Compresses  a  date  down  to  a single integer, to reduce storage
     requirements.   The  date  is  assumed to be valid.  The year should be
     within  the  range  1900-2026  (0-99  is  ok,  and  is  assumed  to  be
     1900-1999).  See also INT2DATE.

     Example:
          CALL DATE2INT(MONTH%,DAY%,YEAR%,SQZDATE%)




     Name: DATEN2S

     Type: String / ANY

     Description:
          Converts the date from numeric form to a string.  You must reserve
     at least eight characters for the string.

     Example:
          MONTH% = 3: DAY% = 2: YEAR% = 1987
          REM  We could use YEAR%=87 instead
          DAT$ = SPACE$(8)
          CALL DATEN2S(MONTH%,DAY%,YEAR%,DAT$)
          REM  From this, we will get DAT$ = "03/02/87"






















     Name: DATES2N

     Type: String / ANY

     Description:
          Converts  the date from a string to numeric form.  The date string
     may   be  in  either  BASIC  format  ("03-15-1987")  or  normal  format
     ("03/15/87").

     Example:
          CALL DATES2N(MONTH%,DAY%,YEAR%,DATE$)




     Name: DEC2ANY

     Type: Miscellaneous / ANY

     Description:
          Converts  a  number  from  decimal  (base  10)  to  any other base
     (2-35).   The  number  will be converted to an unsigned integer (signed
     range of -32768 to 32767 is converted to unsigned range of 0 to 65535),
     to  conform with the built-in BASIC conversion functions HEX$ and OCT$.
     ANUM$  must be initialized to the maximum size you expect the resultant
     number  to  be;  this  is recommended to be 16 characters, which is the
     maximum  length  possible.   The result is right-justified in the field
     you  provide,  so  if  you want to keep leading zeroes, just ignore the
     actual-length specification ALEN%.

     Example:
          INPUT"Decimal number, to base";DNUM%,NBASE%
          ANUM$ = STRING$(16,"0"): CALL DEC2ANY(DNUM%,NBASE%,ANUM$,ALEN%)
          IF ALEN%<0 THEN PRINT"Bad base or ANUM$ initialized too short"
          ELSE PRINT"Result: ";RIGHT$(ANUM$,ALEN%)































     Name: DELAY

     Type: Miscellaneous / BIOS

     Description:
          Delays for a given number of seconds.  This is based on the system
     clock,  and  will  delay  for  the  same  amount  of time on an 8088 or
     80286-based  computer.   It  is  normally  accurate to within about one
     percent.

     Example:
          SECONDS%=60
          CALL DELAY(SECONDS%)
          REM  sit and "do nothing" for one minute




     Name: DELAY18TH

     Type: Miscellaneous / BIOS

     Description:
          Delays  for  a given number of eighteenths of seconds.  Otherwise,
     this is identical to DELAY (see).

     Example:
          MINIDELAY%=9
          CALL DELAY18TH(MINIDELAY%)
          REM  delay for half a second (9/18 = 1/2 second)




     Name: DELCHR

     Type: Video / CLONE

     Description:
          Deletes  a  character  from  the specified location on the screen.
     The  character  at  that  location  will  disappear, and all characters
     to  the  right  of  it on the same screen line will be shifted left one
     space.   The  first  page  only  (on  color monitors) is supported, and
     text mode is required.

     Example:
          COL%=POS(0): ROW%=CSRLIN
          CALL DELCHR(ROW%,COL%)


















     Name: DELSUB

     Type: Disk / DOS

     Description:
          Deletes  a  subdirectory.   Parameters  used  are  the  same as in
     SETSUB.   Note  that  you  may  not delete a subdirectory if it has any
     files  left  in  it,  or  if  it is the main directory, or if it is the
     current default subdirectory.

     Example:
          TMP$=SUB$+CHR$(0)
          CALL DELSUB(TMP$,ERRCODE%)
          IF ERRCODE% THEN couldn't delete subdir ELSE subdir deleted




















































     Name: DISKSTAT

     Type: Disk / DOS

     Description:
          Returns  status  information  for  a  given disk drive.  The drive
     spec should be a letter, or use "@" for the default drive.  Information
     returned  will  be  Free  Clusters,  Total  Clusters, Bytes per Sector,
     and  Sectors  per Cluster.  This will enable you to calculate the total
     space  on  the  disk,  free  space  left on the disk, the actual amount
     of  space  a  file  takes up, and so forth.  A "cluster" is the minimum
     block  of  space  that  can  be allocated on a disk.  The actual amount
     of  space  taken  up  by  a  file  depends on the cluster size.  If the
     cluster  size  is  1024 bytes, any file that is listed as being between
     1  and  1024  bytes  will  take  up 1024 bytes of disk space.  Any file
     listed  as  having  1025  -  2047 bytes will take up 2048 bytes (1024 *
     2), and so on.

     Example:
          DRIVE$ = "@":  REM  Use the default drive
          CALL DISKSTAT(DRIVE$,FRE.CLUST%,TOT.CLUST%,BYTES.SEC%,SECS.CLUST%)
          CLUSTER.SIZE# = CDBL(BYTES.SEC%) * CDBL(SECS.CLUST%)
          FREE.DISK.SPACE# = CDBL(FRE.CLUST%) * CLUSTER.SIZE#
          TOTAL.DISK.SPACE# = CDBL(TOT.CLUST%) * CLUSTER.SIZE#
          PRINT "There are";FREE.DISK.SPACE#;" bytes free out of";
          PRINT TOTAL.DISK.SPACE#;" with";CLUSTER.SIZE#;" bytes per cluster"








































     Name: DMPRINT

     Type: Video / DOS

     Description:
          Displays  a string at the current cursor position, using DOS calls
     for  output  (so  device  drivers  such  as  ANSI.SYS will work).  This
     routine  is  faster  than  MPRINT  (q.v.),  but offers fewer amenities.
     Character  translation  is  limited to what DOS provides, meaning that,
     for  instance,  Backspace  just  moves  the  cursor back without wiping
     out  the previous character.  Other control codes may not be translated
     as  you  might  hope,  either.   Finally,  since DOS provides no way of
     finding  the  current  print position, you have to figure out where the
     cursor  will  be  yourself if you need it (like other display routines,
     DMPRINT  does  not  update  the  BASIC  cursor position).  You can gain
     control  of  such  things  by  using the ANSI.SYS driver.  See your DOS
     manual for more information on that.

     Example:
          CALL DMPRINT(ST$)




     Name: DOSINKEY

     Type: Keyboard / DOS

     Description:
          Gets  a  key  from  the  standard  input device.  This is normally
     the  keyboard,  but  redirection  is  allowed  (to a file, or to a port
     via  CTTY).  Two parameters are returned: the first gives the key code,
     if  any,  and  the  second gives status information.  If the CHRTYPE is
     zero,  there  is  no  key  pressed.   If it is one, the key returned is
     a  normal  keypress.   If  it  is  two, the key returned is the code of
     an Extended ASCII key (like a function key or arrow key).

     Example:
          REM  This is an INKEY$-oriented routine to get a keypress.
          KY$ = ""
          WHILE KY$=""
              KY$ = INKEY$
          WEND
          IF LEN(KY$)=2 THEN EXTCODE=-1: KY$=RIGHT$(KY$,1) ELSE EXTCODE=0
          RETURN

          REM  This is the same routine, using DOSINKEY.
          CHRTYPE% = 0
          WHILE CHRTYPE%=0
              CALL DOSINKEY(CHRCODE%,CHRTYPE%)
          WEND
          KY$ = CHR$(CHRCODE%)
          IF CHRTYPE%=2 THEN EXTCODE%=-1 ELSE EXTCODE%=0
          RETURN












     Name: DRVSPACE

     Type: Disk / DOS

     Description:
          Returns  the  amount  of  free  space  left on a given disk drive.
     The  drive  string  may  be  any legal disk drive, or "@" (AT sign) for
     the default drive, and must be at least one character long.  An illegal
     drive or other error will cause free space to be returned as a negative
     value.  See also DISKSTAT.

     Example:
          DRV$="A:"
           .
           .
          CALL DRVSPACE(DRV$,A%,B%,C%)
          FREE# = CDBL(A%)*CDBL(B%)*CDBL(C%)
          PRINT"Free space on drive ";DRV$;" is";FREE#;"bytes."




     Name: DTR

     Type: Miscellaneous / CLONE

     Description:
          Switches  the  communications  signal  DTR  (Data  Terminal Ready)
     on  or  off.   Turning the DTR off has the effect of making most modems
     drop  carrier  (hang  up  the  phone).   The comm port should be one or
     two.  Use zero to turn the DTR off, or nonzero to turn it back on.

     Example:
          COMMPORT% = 1
          TOGGLE% = 0   : REM  turn the DTR off
          CALL DTR(COMMPORT%,TOGGLE%)






























     Name: EQUIPMENT

     Type: Miscellaneous / BIOS

     Description:
          Returns  basic  information  about  the  hardware configuration of
     the  computer: memory  installed,  in  kilobytes;  number  of  parallel
     (printer)  ports,  0-3;  number  of RS232 serial (comm) ports, 0-7; and
     number of game ports, 0-1.

     Example:
          CALL EQUIPMENT(MEMORY%,PARALLEL%,SERIAL%,GAME%)






















































     Name: EXIST

     Type: Disk / DOS

     Description:
          Tells  you  if  a  given  file already exists.  Returns zero if it
     doesn't,  or  a  nonzero  value if it does.  Requires an ASCIZ filename
     without  wildcards.   If  you  need  to use wildcards, or are operating
     in a network environment, use the FINDFIRSTF function instead.

     Example:
          FIL$="TEST.TXT"+CHR$(0)
          CALL EXIST(FIL$,FILEXISTS%)
          IF FILEXISTS% THEN PRINT "File already exists"




     Name: EXTRACT

     Type: String / ANY

     Description:
          Extracts  a  delimited  substring  from  a  string given an index.
     Requires  a  string  of  any  length,  a  delimiter of one character in
     length,  and  an  index value from 1-256; returns the starting location
     and  length  of  the  substring.   If the delimiter is null (an error),
     the  substring  length  will  be returned as -1.  If the index value is
     greater  than  the  number  of  delimited  substrings, a length of zero
     will be returned.

     Example:
          ST$="John Doe/15 Maple Rd/Hometown, CA 99199/(300) 111-1111"
          INDEX%=2
          DELIMITER$="/"
          CALL EXTRACT(ST$,DELIMITER$,INDEX%,START%,SLEN%)
          PRINT MID$(ST$,START%,SLEN%)
          REM  This will print the second substring (INDEX%=2) of the string
          REM  (ST$) delimited by "/" (DELIMITER$), which in this case
          REM  will be "15 Maple Rd".


























     Name: FCLOSE

     Type: Disk / DOS

     Description:
          Closes a file opened by MOPEN (q.v.)

     Related functions: MCREATE, MOPEN, MREAD, MSETEND, MSETREC, MWRITE.

     Example:
          CALL FCLOSE(HANDLE%)




     Name: FCREATE

     Type: Disk / DOS

     Description:
          Opens  a  file  with  a  given  attribute for read/write access in
     normal  mode.   If  the  file  doesn't exist, it's created; if it does,
     it's  set  to  zero  bytes in length.  A "handle" is returned, which is
     used  to  identify  the  file  (like  BASIC's file numbers).  See FOPEN
     for  an  explanation  of  modes.   For more information, see the end of
     this manual.

     Related functions: FOPEN, FREAD, FSETEND, FSETREC, FWRITE.

     Example:
          FIL$="TEST.TXT"+CHR$(0)
          ATTR%=0
          CALL FCREATE(FIL$,ATTR%,TEST.HANDLE%,ERRCODE%)
          IF ERRCODE% THEN PRINT "Couldn't create file"
































     Name: FINDFIRSTF

     Type: Disk / DOS

     Description:
          Given  a  filename  (which  may contain the wildcards "*" and "?",
     and  a  drive  and  path  spec  if you like), this searches the default
     (or  specified)  directory  to  find  the first matching file.  Further
     matches  can  be  obtained  through  the  FINDNEXTF routine (q.v.).  If
     there  is  a  match,  ERCD%  will return zero, otherwise it will return
     a  positive  value  (unless  you entered a null filename, in which case
     ERCD%  will be -1 to flag an error).  You can retrieve various informa-
     tion  about  the  matched file via a number of supplementary functions:
     GETNAMEF  to  get  the filename, GETATTRF to get the attribute (there's
     a  page  at  the end of this document on file attributes), GETDATEF and
     GETTIMEF  to  get the date and time, and GETSIZEF to get the file size.
     You  may  specify  a search attribute as well: 0 (zero) to match normal
     files, 2 to match hidden files, 4 for system files, and 16 for subdirec-
     tories.   Attributes  other  than zero will return normal files as well
     as  the  specified  type,  and  you  can match on more than one kind of
     attribute (for instance, to get all kinds of files, you'd use an attri-
     bute  of 22, or 2+4+16).  You can read the volume label using an attri-
     bute  of  8,  which  is  supposed  to return only the volume label, but
     may not (see notes in the File Attribute info at the end of this file).

          This  function can be used to duplicate the DOS directory command,
     or to allow filename wildcards in your program, among other things.

     Example:
          FIL$=FIL$+CHR$(0)
          CALL FINDFIRSTF(FIL$,ATTR%,ERCD%)
          IF ERCD% THEN PRINT"No matching files"


































     Name: FINDNEXTF

     Type: Disk / DOS

     Description:
          This  is  used  after  the  FINDFIRSTF function (q.v.) in order to
     find further matching files.

     Example:
          CALL FINDNEXTF(ERCD%)
          IF ERCD% THEN PRINT"No more matching files"























































     Name: FOPEN

     Type: Disk / DOS

     Description:
          Opens  an  already-existing  file.   If  you  want to create a new
     file,  use  the  FCREATE  function.   You  tell  it the ASCIZ filename,
     ACCESS%  method,  and  MODE%; it gives back a HANDLE% or ERRCODE%.  The
     ACCESS%  method  is  how  you want to open the file: 0, read; 1, write;
     2, read/write.  The MODE% controls access to the file by other programs
     operating  at  the same time, and is hence only useful for multitasking
     or  networking.   MODE%  is: 0, normal (no multitasking or networking);
     1,  exclusive  (no  other  program  can access the file); 2, deny write
     (no  other program may change the file); 3, deny read (no other program
     may  look  at  the  file);  4,  deny none (any other program may access
     the  file).   To  activate  handling of nonzero modes, you must execute
     the  DOS  utility  SHARE, which is included on your DOS disk.  For more
     information, see the end of this manual.

     Related functions: FCLOSE, FCREATE, FREAD, FSETEND, FSETREC, FWRITE.

     Example:
          FIL$="TEST.TXT"+CHR$(0)
          FACCESS%=2  : REM  Open the file with read/write access
          FMODE%=0    : REM  Normal mode, not networking or multitasking
          CALL FOPEN(FIL$,FACCESS%,FMODE%,TEST.HANDLE%,ERRCODE%)
          IF ERRCODE% THEN PRINT "Unable to open the file"

     Example:
          FIL$="C:\DOCUMENT\TEST.TXT"+CHR$(0)
          FACCESS%=2  : REM  Open the file for read access
          FMODE%=2    : REM  Deny Write mode, for networking/multitasking
          REM  We "deny write" so nobody else can change the file while
          REM
               we're reading it.  We'll let others read from the file while
          REM  we are, though.  (This works like Normal mode if SHARE wasn't
          REM  executed)
          CALL FOPEN(FIL$,FACCESS%,FMODE%,TEST.HANDLE%,ERRCODE%)
          IF ERRCODE% THEN PRINT "Unable to open file"




























     Name: FREAD

     Type: Disk / DOS

     Description:
          Reads  information  from  a  file opened by FOPEN or FCREATE.  You
     tell  it  which  file  to  read  from by giving it the handle which was
     returned  when  you  opened  the  file.   You give it a buffer location
     to read into, which can be either an array (for use, say, with SCRREST)
     or  a string (for more usual purposes).  You are responsible for seeing
     that  the  buffer  is  large enough to hold all the bytes that you want
     to read!
          FREAD  returns  a  nonzero  ERRCODE%  if  anything went wrong.  If
     ERRCODE% is -1, it was able to read only part of the information before
     hitting  an  end  of  file.  In that case, BYTESREAD% will tell you how
     many  bytes  were  actually  read  in.   See the end of this manual for
     info on error codes.

     Related functions: FCLOSE, FCREATE, FOPEN, FSETEND, FSETREC, FWRITE

     Example:
          OPTION BASE 1: DIM ARRAY%(2000): REM  Set up the array buffer
           .
           .
          REM  Do a FOPEN to open the file
          BUFFER%=VARPTR(ARRAY%(1)): REM  Use first element of array here
          BYTES%=4000: REM  Read in 4000-byte saved screen into the array
          CALL FREAD(HANDLE%,BUFFER%,BYTES%,BYTESREAD%,ERRCODE%)
          IF ERRCODE% THEN PRINT "Error reading file..."
          REM  Do a SCRREST to put the info on the screen

     Example:
          BYTES%=128          : REM  Read in 128 bytes/characters
      
          BUF$=SPACE$(BYTES%) : REM  Set up the string buffer
          V%=VARPTR(BUF$)
          BUFFER%=PEEK(V%+2)+PEEK(V%+3)*256
          CALL FREAD(HANDLE%,BUFFER%,BYTES%,BYTESREAD%,ERRCODE%)
          IF ERRCODE% THEN PRINT "Error reading file..."




























     Name: FSETEND

     Type: Disk / DOS

     Description:
          For  use  with  files  opened with FOPEN / FCREATE.  This function
     sets  the  file pointer to the end of the file, so that any information
     written using FWRITE will be appended to the file.

     Related functions: FCLOSE, FCREATE, FOPEN, FREAD, FSETREC, FWRITE

     Example:
          CALL FSETEND(HANDLE%)





















































     Name: FSETREC

     Type: Disk / DOS

     Description:
          For  use  with  files  opened with FOPEN / FCREATE.  This function
     sets  the  file  pointer to a given record in the file, so that it will
     be the next record read or written.

     Related functions: FCLOSE, FCREATE, FOPEN, FREAD, FSETEND, FWRITE

     Example:
          RECSIZE%=128: REM  Number of bytes in a record in our file
          RECNO%=34: REM  Record number (starting from 1, as in BASIC)
          CALL FSETREC(HANDLE%,RECSIZE%,RECNO%)




     Name: FWRITE

     Type: Disk / DOS

     Description:
          Allows  you  to  write  to a file opened by FOPEN or FCREATE.  The
     parameters  are  the same as in FREAD (q.v.), except for BYTESWRITTEN%,
     which replaces BYTESREAD%.

     Related functions: FCLOSE, FCREATE, FOPEN, FREAD, FSETEND, FSETREC

     Example:
          REM  Do a SCRSAVE to save a screen into ARRAY%()
          BUFFER%=VARPTR(ARRAY%(1))
          BYTES%=4000: REM  4000 bytes = 2000 integer array elements
          CALL FWRITE(TEST.HANDLE%,BUFFER%,BYTES%,BYTESWRITTEN%,ERRCODE%)
          IF ERRCODE% THEN PRINT "Unable to write to file..."
          REM  See FREAD for an example of how to set up a string buffer
          REM  as the setup is different than when using an array buffer




























     Name: GETATTRF

     Type: Disk / DOS

     Description:
          Returns  the  actual  attribute of a file matched using FINDFIRSTF
     or  FINDNEXTF.   See  the  end of this document for information on file
     attributes.

     Example:
          REM  use this AFTER calling FINDFIRSTF / FINDNEXTF to initialize
          REM  the appropriate file information!
          CALL GETATTRF(ATTR%)




     Name: GETCRT

     Type: Video / BIOS

     Description:
          Tells  you what kind of display is being used.  The returned value
     will be reset if it's monochrome, or set if color.

     Example:
          CALL GETCRT(COLORDISPLAY%)
          IF COLORDISPLAY% THEN PRINT"Color" ELSE PRINT"Monochrome"




     Name: GETEXTM

     Type: Miscellaneous / AT BIOS

     Description:
          Tells  you  how  much extended memory is available.  This function
     requires  the  AT  BIOS,  and  shouldn't  be  used  with PCs.  See also
     GETLIMM.

     Example:
          CALL GETEXTM(KBYTES%)
          PRINT KBYTES%;" kilobytes of extended memory"






















     Name: GETKBD

     Type: Input / CLONE

     Description:
          Gives  the  status  of  the  keyboard  toggles.  The variable will
     be set if the toggle is on, and reset if it is off.  See also SETKBD.

     Example:
          CALL GETKBD(INSERT%,CAPSLOCK%,NUMLOCK%,SCROLLLOCK%)
          IF INSERT% THEN PRINT"Insert mode is on"
          IF CAPSLOCK% THEN PRINT"Caps Lock is on"
          IF NUMLOCK% THEN PRINT"The keypad is in numeric mode"
          IF SCROLLLOCK% THEN PRINT"Scroll Lock is on"




     Name: GETDATEF

     Type: Disk / DOS

     Description:
          Returns the date associated with the file matched using FINDFIRSTF
     or FINDNEXTF.

     Example:
          CALL GETDATEF(MONTH%,DAY%,YEAR%)




     Name: GETDOSV

     Type: Miscellaneous / DOS

     Description:
          Gets  MS-DOS  version.  The major version is returned in the first
     parameter,  the minor version in the second (e.g., MS-DOS v. 2.11 would
     return MAJ% = 2, MIN% = 11).

     Example:
          CALL GETDOSV(MAJ%,MIN%)























     Name: GETDRV

     Type: Disk / DOS

     Description:
          Returns  the  letter  of the default drive.  The drive string must
     be at least one character long.

     Example:
          DRV$="x:": CALL GETDRV(DRV$)




     Name: GETFATTR

     Type: Disk / DOS

     Description:
          Gets  the attribute of a file.  See the section on file attributes
     at the end of this manual.

     Example:
          FIL$=FIL$+CHR$(0)
          CALL GETFATTR(FIL$,ATTR%)









































     Name: GETFDATE

     Type: Disk / DOS

     Description:
          GETFDATE  returns  the  file  creation date, that is, the date you
     see  on  a  file  when  you  get  a  DIRectory.   The file name must be
     terminated  with  a NUL character.  If there is an error, such as there
     being no such file, the month will be set to -1.

     Example:
          FIL$="TESTFILE.TXT"+CHR$(0)
          CALL GETFDATE(FIL$,MONTH%,DAY%,YEAR%)




     Name: GETFTIME

     Type: Disk / DOS

     Description:
          This  function complements GETFDATE, and returns the file creation
     time.   The  hour is in 24-hour (military) format, and will be returned
     as  -1  if  there  is no such file or a bad file name.  The seconds are
     rounded  to  the next lower even number, due to the DOS storage format.
     The file name must be terminated with a NUL character.

     Example:
          FIL$="ANYFILE.EXT"+CHR$(0)
          CALL GETFTIME(FIL$,HOUR%,MINUTE%,SECOND%)



































     Name: GETKEY

     Type: Keyboard / BIOS

     Description:
          Waits  until  one  of  a  list of keys is pressed, and returns it.
     The  key  list  (any  length)  should be uppercase.  If the key list is
     null,  the  first  key pressed will be returned.  The key returned will
     be  capitalized.   The  variable  to return the key in must be at least
     one  character  long.   This  function is designed for returning one of
     a menu of choices, for example.

     Example:
          PRINT "Would you like to try again (Y/N)? ";
          GOODKEYS$="YN" : REM  Allow Y or N
            .
            .
          KY$="x": CALL GETKEY(GOODKEYS$,KY$)




     Name: GETLIMM

     Type: Miscellaneous / BIOS

     Description:
          Returns  the  status  of  expanded memory, in total pages and free
     pages  (where  a  page  is  16k bytes).  GETLIMM should only be used on
     systems with EMS or EEMS memory installed.  See also GETEXTM.

     Example:
          CALL GETLIMM(TOTPAGES%,FREEPAGES%)
          PRINT TOTPAGES%;"pages of expanded memory are installed."
          IF TOTPAGES%>0 THEN PRINT FREEPAGES%;"pages of that are free."































     Name: GETLINE

     Type: Video / ANY

     Description:
          Returns  a  selected  line  from  a screen saved via SCRSAVE, with
     the  trailing  spaces  removed.   The  line  string must be at least 80
     characters  long.   This  will  also  return a line from a screen saved
     with GETSCREEN, as long as full 80-column lines were saved.

     Example:
          OPTION BASE 1: DIM SCR%(2000)
          WHERE%=VARPTR(SCR%(1)): CALL SCRSAVE(WHERE%): CLS
          LINENR%=10: LIN$=SPACE$(80): WHERE%=VARPTR(SCR%(1))
          CALL GETLINE(WHERE%,LINENR%,LIN$,LLEN%)
          PRINT"Line 10 was:": PRINT LEFT$(LIN$,LLEN%)




     Name: GETNAMEF

     Type: Disk / DOS

     Description:
          Returns  the  filename  of  the  file  matched using FINDFIRSTF or
     FINDNEXTF.   The FIL$ string must be initialized to at least 12 charac-
     ters  in  length.  The actual length of FIL$ will be returned in FLEN%,
     which  will  be  -1  if  you  didn't initialize FIL$ long enough.  Note
     that the filename will not contain a drive or path spec.

     Example:
          FIL$=SPACE$(12)
          CALL GETNAMEF(FIL$,FLEN%)
          FIL$=LEFT$(FIL$,FLEN%)































     Name: GETSCREEN

     Type: Video / CLONE  (not with QuickBASIC 4.0 or BC)

     Description:
          Allows  you  to  save  any  part  of a text screen display (on any
     page,  active  or  inactive,  if  you  have  a color graphics adapter).
     You  need  to  specify  an  integer array where the information will be
     stored,  the  coordinates  of  the  upper  left corner and bottom right
     corner  of  the  part  of the screen to save, the display page to save,
     and the screen mode.
          The  screen  mode  should  be  zero for flicker-free screen saving
     if  you  have  a  low quality color graphics adapter and are saving the
     currently-active  display  page.   Otherwise, set it to 1 or -1 for the
     fastest save speed.
          You  specify  the  area  of  the screen to save as a rectangle, by
     giving  the  locations of the upper leftmost corner and lower rightmost
     corner  of  the  area  to save.  This can range from a single character
     to  the entire screen.  Make sure that the coordinates do not get mixed
     up, or you will get unpredictable results.
          To  figure  out  how  many array elements you need to save an area
     of the screen, use the following calculation:
     ELEMENTS%=(BOTTOMROW%-TOPROW%+1)*(RIGHTCOLUMN%-LEFTCOLUMN%+1)
     You  can  store  multiple  screen  areas in one array by specifying the
     proper  starting  element,  which  must be one after the previous saved
     area.   You'll  have  to  keep track of where each saved area is in the
     array yourself.
          If you have a monochrome adapter, or are not using unusual display
     pages, you should set the page specification to zero.
          Note  that  you don't have to restore the saved area of the screen
     (see  PUTSCREEN)  to  the same area it was taken from.  This allows you
     to move windows around, change the shape of windows, and other interes-
     ting tricks...
          See  also  PUTSCREEN,  to  restore a given area of the screen; and
     SCRSAVE, SCRREST, SCRSAVEP, SCRRESTP, SCRSAVEPD, and SCRRESTPD, earlier
     versions  of  similar  functions.  Note that if you save/restore a full
     80-column,  25-row  screen,  the  information in the save/restore array
     is    identical    whether    you're   using   GETSCREEN/PUTSCREEN   or
     SCRSAVExx/SCRRESTxx.   On  that  level,  the  routines  are  completely
     compatible.

     Example:
     CALL GETSCREEN(SCRN%(0),TOPROW%,LFCOL%,BOTROW%,RTCOL%,PAGE%,SCRNMODE%)
       REM  SCRN%(0) is the location in the array to save the area to.
       REM  TOPROW%,LFCOL% and BOTROW%,RTCOL% are the corners of the area.
       REM  PAGE% is the display page number (0-3 if Color, 0 if Mono).
       REM  SCRNMODE% is screen access mode: 0, snowless; 1 / -1, fast.



















     Name: GETSIZEF

     Type: Disk / DOS

     Description:
          Returns  the size of the file matched via FINDFIRSTF or FINDNEXTF.
     Since  the  file  size  may  be  outside  integer bounds, there is some
     additional code you will have to add which uses double-precision values
     (see  the example).  You can modify the example to use single-precision
     instead,  but  really large file sizes will then lapse into exponential
     notation.

     Example:
          CALL GETSIZEF(SIZELOW%,SIZEHIGH%)
          SIZELOW#=CDBL(SIZELOW%)
          IF SIZELOW%<0 THEN SIZELOW#=SIZELOW#+65536#
          FILESIZE#=SIZELOW#+CDBL(SIZEHIGH%)*65536#




     Name: GETSUB

     Type: Disk / DOS

     Description:
          Gets  the  default  subdirectory.   The  subdirectory  string must
     be  64  characters  long,  and it is recommended that you set it to NUL
     characters.   Note  that  the  returned  string  will NOT be started by
     a backslash "\" character-- you should add one if appropriate.

     Example:
          SUB$=STRING$(64,0)
          CALL GETSUB(SUB$,SLEN%)
          SUB$="\"+LEFT$(SUB$,SLEN%)




     Name: GETTIMEF

     Type: Disk / DOS

     Description:
          Returns  the  time  associated with the file matched by FINDFIRSTF
     or FINDNEXTF.  The hour is returned in military (24-hour) format.

     Example:
          CALL GETTIMEF(HOUR%,MINUTE%,SECOND%)

















     Name: INSCHR

     Type: Video / CLONE

     Description:
          Inserts  a  space at the specified screen location.  The character
     previously  at  that  position  and  all  characters to the right of it
     on  the  same  screen  line  will  be shifted right one space.  Subject
     to the same limitations as DELCHR (q.v.).

     Example:
          COL%=POS(0): ROW%=CSRLIN
          CALL INSCHR(ROW%,COL%): PRINT"*";




     Name: INT2DATE

     Type: Miscellaneous / ANY

     Description:
          Decompresses  a  date  squeezed  using  DATE2INT (q.v.).  The year
     will be a four-digit value (1900-2026).

     Example:
          CALL INT2DATE(MONTH%,DAY%,YEAR%,SQZDATE%)




     Name: INT2TIME

     Type: Miscellaneous / ANY

     Description:
          Decompresses  a  time squeezed using TIME2INT (q.v.).  The seconds
     will be an even value (rounded down) due to the storage format.

     Example:
          CALL INT2TIME(HOUR%,MIN%,SEC%,SQZTIME%)

























     Name: KEYPRESS

     Type: Keyboard / BIOS

     Description:
          Tells  you  whether  a  key is waiting in the keyboard buffer (for
     use  with  INKEY$  routines,  etc).   KYHIT is set if a key is waiting,
     cleared otherwise.

     Example:
          100 CALL KEYPRESS(KYHIT%)
              IF KYHIT% THEN KY$=INKEY$ ELSE 100




     Name: LOCASE

     Type: String / ANY

     Description:
          Converts a string to all lowercase characters.

     Example:
          MSG$="THis IS a test OF tHe lowercase CONVERTER!"
            .
            .
          CALL LOCASE(MSG$)






































     Name: LROTATE

     Type: String / ANY

     Description:
          Rotates  the  characters  in a string left.  That is, the leftmost
     character  is  removed,  and  tacked  onto the end of the string.  This
     is  useful  for  rotating  queues and for character-graphics animation.
     If the string is of length one or less, it is returned unchanged.

     Example:
          ST$="12345"
          CALL LROTATE(ST$)
          REM  ST$ will end up being "23451"




     Name: MAKESUB

     Type: Disk / DOS

     Description:
          Makes  a  subdirectory.   Use  a  NUL-terminated string to specify
     the  subdirectory.   An  error  code  will  be returned if there was an
     error.

     Example:
          TMP$=SUB$+CHR$(0)
          CALL MAKESUB(TMP$,ERRCODE%)
          IF ERRCODE% THEN couldn't make subdir ELSE subdir created



































     Name: MAKEWINDOW

     Type: Video / CLONE

     Description:
          Creates  a  pop-up  window  on the screen.  You specify the window
     by  giving  the  upper left corner and lower right corner of the inside
     of  the  window.   The  frame  is  drawn  -outside-  the  window you've
     specified, so be sure to allow room for the frame!  For normal windows,
     the  frame  takes up only one column or row on each side.  For shadowed
     windows,  the  frame  will  instead  take  up three columns on the left
     and three rows on the bottom.

          There are four types of window:
     0, Normal:   the window pops onto the screen.
     1, Growing:  the window "grows" from a spot to a full-sized window.
     2,  Shadowed:  the  window  is shadowed on the left and bottom for a 3D
        effect.
     3, Growing/Shadowed: the window is shadowed and grows.

          You may also choose five types of frames:
     0, None: composed of spaces.
     1, Single: composed of a single line.
     2, Double: composed of a double line.
     3,  Double/Single:  made with a double vertical and a single horizontal
        line.
     4,  Single/Double:  made with a single vertical and a double horizontal
        line.

          You  must select fore and background colors.  A label is optional.
     If  you  give  one, it is bracketed within the top of the frame, on the
     left side.  The screen page is selectable on color monitors.

     Example:
          LCOL%=5:  TROW%=5:  REM  top left corner
          RCOL%=79: BROW%=20: REM  bottom right corner
          LABEL$="Test Window"
          FORE%=7: BACK%=0:   REM  color/attributes
          PAGE%=0:           REM  screen display page
          FRAME%=1:          REM  single-line frame
          TYPE%=3:           REM  growing, shadowed window
          CALL MAKEWINDOW(LCOL%,TROW%,RCOL%,BROW%,LABEL$,
                          FRAME%,TYPE%,FORE%,BACK%,PAGE%)
          REM  the above line shouldn't be divided in your program!
          REM  it's separated like that to accommodate my word processor.





















     Name: MDELCHR

     Type: Video / BIOS

     Description:
          Deletes  the  character  at the current cursor position.  It obeys
     the  window  defined  by  MWINDOW.   It's  more compatible than DELCHR,
     but much slower.
            Note  that  this  routine  can  be  used to scroll a window left
     by  doing an MDELCHR at the first location of each line to be scrolled.
     To scroll right, do the same using MINSCHR instead.

     Example:
          CALL MDELCHR




     Name: MINSCHR

     Type: Video / BIOS

     Description:
          Inserts a space at the current cursor position, obeying the window
     defined by MWINDOW.  See notes at MDELCHR.

     Example:
          CALL MINSCHR






































     Name: MMBUTTON

     Type: Input / BIOS

     Description:
          Returns  which  mouse  buttons are currently being held down.  See
     also MMCLICK.

     Example:
          CALL MMBUTTON(LFT%,RGT%)
          IF LFT% THEN PRINT"The left button is being pressed."
          IF RGT% THEN PRINT"The right button is being pressed."




     Name: MMCHECK

     Type: Input / BIOS

     Description:
          Returns  whether  a  mouse  is  installed, and how many buttons it
     has if it is installed.

     Example:
          CALL MMCHECK(MOUSE%)
          IF MOUSE% THEN PRINT"A mouse with ";MOUSE%;" buttons is present."




     Name: MMCLICK

     Type: Input / BIOS

     Description:
          Returns  which  mouse  buttons  have  been  clicked since you last
     used this function.  See also MMBUTTON.

     Example:
          CALL MMCLICK(LFT%,RGT%)
          IF LFT% THEN PRINT"The left button was pressed."
          IF RGT% THEN PRINT"The right button was pressed."























     Name: MMCURSORON

     Type: Input / BIOS

     Description:
          Makes  the  cursor  associated  with  the  mouse visible.  This is
     normally  a  blinking  block,  and  shows  where the mouse is currently
     pointing.  See also MMCURSOROFF.

     Example:
          CALL MMCURSORON



     Name: MMCURSOROFF

     Type: Input / BIOS

     Description:
          Makes  the  cursor  associated with the mouse invisible.  See also
     MMCURSORON.

     Example:
          CALL MMCURSOROFF




     Name: MMGETLOC

     Type: Input / BIOS

     Description:
          Gets  the  current location of the mouse cursor.  This is returned
     as  a  value  from  0-639 for columns, and 0-199 for rows.  You need to
     adjust  this  for  the  current screen format.  If you're in text mode,
     divide  the  columns  by eight and the rows by eight.  If you're in low
     res  graphics  mode,  divide the columns by two.  If you're in high res
     graphics, the numbers are fine.

     Example:
          CALL MMGETLOC(COL%,ROW%)
          LOCATE ROW%,COL%: PRINT "!";























     Name: MMSETLOC

     Type: Input / BIOS

     Description:
          Sets  the current value of the mouse cursor.  Uses the same format
     as MMGETLOC (q.v.).

     Example:
          COL%=40*8-8: ROW%=24*8-8: REM  middle of the text-mode screen
          CALL MMSETLOC(COL%,ROW%)




     Name: MMSETRANGE

     Type: Input / BIOS

     Description:
          Sets  the  range  of  locations  where the mouse cursor is allowed
     to  be.   This  is  done  by specifying the upper left corner and lower
     right  corner  of  the  edges  of  the mouse input field.  Use the same
     format as MMGETLOC (q.v.).

     Example:
          LFTCOL%=20*8-8: TOPROW%=1*8-8
          RGTCOL%=60*8-8: BOTROW%=10*8-8
          CALL MMSETRANGE(LFTCOL%,TOPROW%,RGTCOL%,BOTROW%)
          REM  sets up a text-mode input field




































     Name: MLOAD

     Type: Disk / DOS

     Description:
          Works  the  same  way  as  the  BLOAD statement does.  This is for
     use  with older compilers, which don't have the BLOAD statement.  MLOAD
     restores the information to the same place it was when BSAVEd.

     Example:
          FIL$="SCRNSAVE.BIN"+CHR$(0)
          CALL MLOAD(FIL$)




     Name: MONTH

     Type: Miscellaneous / ANY

     Description:
          Given  the  number  of  a  month  (1-12), this routine returns the
     name  of  the  month  (January  -  December).  You must supply a string
     of at least nine spaces in length to hold the month.

     Example:
          MONTH$=SPACE$(9)
          CALL MONTH(MONTH$,MLENGTH%,MONTHNUMBER%)
          MONTH$=LEFT$(MONTH$,MLENGTH%)





































     Name: MPRINTC

     Type: Video / BIOS

     Description:
          Using  this  function,  you  can  access  device  drivers  such as
     ANSI.SYS.   This  is  a video output function which goes through MS-DOS
     function   calls.   It  prints  a  single  character  to  the  display.
     MPRINTC allows use of ANSI.SYS and similar video drivers, and windowing
     via  MWINDOW,  but is slower and takes more memory that the usual PRINT
     statement.

     Example:
          CALL MPRINTC(CH$,COL%,ROW%): LOCATE ROW%,COL%




     Name: MPRINT

     Type: Video / BIOS

     Description:
          Same  as  MPRINTC  (q.v.),  only  it  allows you to send an entire
     string out to the display, rather than just a single character.

     Example:
          CALL MPRINT(ST$,COL%,ROW%): LOCATE ROW%,COL%






































     Name: MULTIAND

     Type: String / ANY

     Description:
          This is a flexible function with many possible uses.  Every charac-
     ter  in  a  given  string  is ANDed with a value you supply.  One thing
     this  could  be  used for is translating Wordstar files to ASCII files,
     by  using  a bit mask (the value that will be ANDed with the character)
     of  &H7F,  which strips off the high bit of each character.  The string
     may  be  any length; the bit mask is an integer, with only the low byte
     in use (value of 0-255).

     Example:
          ST$ = ""
          FOR X%=65 TO 70: ST$=CHR$(X%)+CHR$(X%+128): NEXT
          PRINT ST$
          BITMASK%=&H7F
          CALL MULTIAND(ST$,BITMASK%)
          PRINT ST$




     Name: MULTIOR

     Type: String / ANY

     Description:
          Does  the  exact  opposite  of MULTIAND-- instead of stripping off
     bits,  it  turns  on  bits.   It ORs instead of ANDs.  One possible use
     for  this would be to encode a text string by ORing with 128, and later
     decoding  by  ANDing with 128.  This would allow you to save the string
     to  disk  using  text files, even if the string included control codes,
     although  that  won't  work right if the string has graphics characters
     (using  ExtASCII codes, which are codes from 128-255) in it.  The para-
     meters are the same as for MULTIAND.

     Example:
          ST$ = "ABCDE": PRINT ST$
          SETBITS%=&H80
          CALL MULTIOR(ST$,SETBITS%)
          PRINT ST$























     Name: MULTIXOR

     Type: String / ANY

     Description:
          An  exclusive-or  operation  for strings.  Bits in the string will
     be  set  only  if they are set in the string byte or mask byte, but not
     in  both  of them.  Note that this can be used as a "MULTINOT" function
     by  using  a  mask  of  &HFF or 255.  In this case, all bits are set in
     the  mask, so the result of the XOR will be the same as a NOT operation
     on  the  string.   Note  that XORing a string with the same value twice
     will  return  the  original  string-- it can thus be used to encode and
     decode strings.

     Example:
          CALL MULTIXOR(ST$,MASK%)




     Name: MWINDOW

     Type: Video / BIOS

     Description:
          Sets  up  a  window  for the MPRINT and MPRINTC routines.  Windows
     are  defined  by  their  upper left corner and lower right corner.  The
     default  window  is  thus (1,1,80,24), which leaves out the bottom line
     (BASIC's  status  line).   To  use  the  full screen, call this routine
     with  values  (1,1,80,25).   Note  that the cursor should be positioned
     inside  the window before using MPRINT/MPRINTC.  Note also that windows
     should be defined to contain at least two rows.

     Example:
          LFCOL%=20: TOPROW%=5: RTCOL%=60: BOTROW%=15
          CALL MWINDOW(LFCOL%,TOPROW%,RTCOL%,BOTROW%)
          LOCATE TOPROW%,LFCOL%
          REM  sets up a window (of 40 cols x 10 rows)
          REM  in the middle of the screen.



























     Name: PRINTSCREEN

     Type: Miscellaneous / BIOS

     Description:
          This  sends  an  image  of  the  current screen display out to the
     first  printer  device.   It  works  exactly in the same way as doing a
     Shift-PrtSc  from  the  keyboard,  so  it  can display graphics as well
     as text if you have the DOS GRAPHICS program installed.




     Name: PUTSCREEN

     Type: Video / CLONE   (not with QuickBASIC 4.0 or BC.EXE)

     Description:
          This  restores  an  area  of  the  screen that was saved using the
     GETSCREEN  function  (q.v.).   You need not restore an area to the same
     screen coordinates or to the same display page.
          It  is  possible  to  change  the shape of an area by changing the
     coordinates  specified.   For  instance,  suppose  you  had saved a six
     character,  one  line  message,  "FOOBAR",  at coordinates (1,1)-(1,6).
     You  could  restore it as a three char by two line message, "FOO" "BAR"
     by specifying the coordinates (1,1)-(2,3).  Note that these coordinates
     are  in Microsoft's mixed up form of (ROW,COLUMN), not the normal alge-
     braic format.
          It  is  also  possible to restore only part of the screen that was
     saved.   For  instance,  suppose  you had saved the entire screen in an
     array SCRN starting at element 0, and only wanted to restore the bottom
     half  of  the  screen.  Using the calculation for screen elements given
     in  GETSCREEN,  you  would  find that 2000 elements were needed for the
     whole  screen, or only 1000 elements for the bottom half of the screen.
     That  means  that  in  the  array,  elements 0-999 hold the top half of
     the  screen,  and  1000-1999  hold  the bottom half (assuming a default
     OPTION  BASE=0).   So,  you  would  tell  PUTSCREEN to start with array
     element  SCRN%(1000),  and  give it the starting and ending coordinates
     of the corners of the lower half of the screen.
          Parameters specifications are the same as they are for GETSCREEN.

     Example:
     CALL PUTSCREEN(SCRN%(0),TOPROW%,LFCOL%,BOTROW%,RTCOL%,PAGE%,SCRNMODE%)























     Name: QPRINT

     Type: Video / CLONE

     Description:
          This  function  bypasses  the  usual  video routines, and prints a
     string directly on the screen, at a -much- higher speed than the normal
     PRINT  statement  does.   It also contains a built-in LOCATE statement,
     and  doesn't  affect the cursor position.  Note that control characters
     will  show  up  as graphics characters instead of having their original
     functions,  and  the  color/attributes  used  will  be the ones already
     on  the  screen.   Display  page zero is used with color adapters.  See
     also XQPRINT.

     Example:
          ST$="This is a test of fast screen printing"
          ROW%=10: COL%=20
          CALL QPRINT(ST$,ROW%,COL%)
















































     Name: READBITF

     Type: Miscellaneous / ANY

     Description:
          Reads  a  word  from  an  array  of arbitrary bit length, given an
     index.   The  words  in  the  array  may  be made of one to eight bits.
     Indices  begin  at  zero  and are limited by integer range.  That is up
     to  &HFFFF,  subject  to  memory constraints-- the index is taken to be
     an  unsigned integer value.  This function allows very memory-efficient
     storage  of  arrays  of  numbers,  provided that the numbers are within
     a  restricted  range.   The  simulated  array  is  held within a normal
     integer  array,  which  must  be  dimensioned  large enough to hold all
     of  the arbitrary-length words (will depend on bits per word and number
     of words desired).

     Example:
          OPTION BASE 0: DIM INTARRAY%(50): BITFSIZE%=8
            .
            .
          ARRAYLOC%=VARPTR(INTARRAY%(0))
          CALL READBITF(ARRAYLOC%,NDX%,BITFSIZE%,VALUE%)
          REM  Returns a value from the array location indexed by NDX%,
          REM  where the array is composed of bytes (8-bit words).
          REM  See the disk file BITFTEST.BAS in the source files
          REM  for a working example program.




     Name: RECOLOR

     Type: Video / CLONE

     Description:
          Takes everything on the screen that's of a given color and changes
     its  color to whatever you like.  This can be used for special effects,
     or  just to change the screen color without having to clear the screen.
     This will work only in text mode.  The color attributes must be defined
     from the foreground and background colors using the CALCATTR routine.

     Example:
          CALL CALCATTR(FOREGND%,BACKGND%,OLDCOLR%)
          CALL CALCATTR(NEWFORE%,NEWBACK%,NEWCOLR%)
          CALL RECOLOR(OLDCOLR%,NEWCOLR%)





















     Name: RESETPOINT

     Type: Video / BIOS

     Description:
          Resets a point on a text screen.  This is the opposite of SETPOINT
     (see).

     Example:
          ROW%=0
          FOR COLUMN%=0 to 79
             CALL RESETPOINT(COLUMN%,ROW%)
          NEXT COLUMN%
          REM  this clears a line from the top of the screen
          REM  (undoes the line from the SETPOINT example)



















































     Name: REVERSE

     Type: String / ANY

     Description:
          Reverses  the  order  of  characters  in  a  string.   This can be
     combined with the XLATE function and a judiciously-designed translation
     table  to provide mirror images of strings for character-graphics-based
     displays.   It  can also be used with INSTR to provide a function which
     returns the last occurrence of a given substring within a string.

     Example:
          MSG$="This is a test"
          CALL REVERSE(MSG$)
          PRINT MSG$




     Name: RROTATE

     Type: String / ANY

     Description:
          Rotates  the  characters  in  a string right.  This is the same as
     LROTATE, only in reverse.  See LROTATE for further details.

     Example:
          ST$="12345"
          CALL RROTATE(ST$)
          REM  ST$ will end up being "51234"



































     Name: SCROLL

     Type: Video / BIOS

     Description:
          Scrolls  any  selected  portion of the screen as many times as you
     like
     (or  use  0 to clear that part of the screen entirely).  There are five
     parameters  to  this  function: coordinates (LFCOL,TOPROW) of the upper
     left  corner  of  the  area  to be scrolled, coordinates (RTCOL,BOTROW)
     of  the  lower  right corner of the area to be scrolled, and the number
     of  times  to scroll the area.  This routine may be used to create win-
     dows.   Note  that  RTCOL  must  be at least one greater than LFCOL (no
     single-line  scrolling,  obviously).   Note  also  that  you should not
     try  to  scroll  more  times  than  there  are  lines in the area to be
     scrolled  (use  0  instead).  Parameters are not checked, so be careful
     not to use illegal screen coordinates.

     Example:
          CALL SCROLL(LFCOL%,TOPROW%,RTCOL%,BOTROW%,NUMLINES%)














































     Name: SCRREST

     Type: Video / CLONE

     Description:
          Restores  the  screen  display  from an image put into an array by
     SCRSAVE.  Same requirements and limitations of SCRSAVE.

     Example:
          WHERE%=VARPTR(SCR%(1))
          CALL SCRREST(WHERE%)
          LOCATE OLDROW%,OLDCOL%




     Name: SCRSAVE

     Type: Video / CLONE

     Description:
          Stores  the  current  screen  display  (page  0 only) in an array.
     Text  modes  only.   Requires  an  array  of 4000 bytes, and an integer
     which  points  to  the  location  of the array.  The cursor position is
     not saved.

     Example:
          OPTION BASE 1: DIM SCR%(2000)
           .
           .
          WHERE%=VARPTR(SCR%(1))
          CALL SCRSAVE(WHERE%)
          OLDCOL%=POS(0): OLDROW%=CSRLIN
          REM  Dim of 2000 w/ option base 1 gives us 2000 integers,
          REM  which gives us 4000 bytes of storage space.
          REM  Note: you can store more than one screen in an array by
          REM  dimensioning it large enough.  Use WHERE%=VARPTR(SCR%(2001))
          REM  to locate the second screen, and so forth.




























     Name: SCRRESTP, SCRRESTPD, SCRSAVEP, SCRSAVEPD

     Type: Video / CLONE

     Description:
          These  functions  are  variations  of SCRREST and SCRSAVE.  All of
     them  allow  specification  of a page number, for color monitors.  They
     will  save  or restore text to a given page.  When used with monochrome
     monitors,  the  page  specification  should  always be zero.  SCRRESTPD
     and  SCRSAVEPD  write  directly to the screen at high speed.  This will
     cause  "snow"  if  you  have  an  old  or poorly designed color display
     adapter  and  are  writing  to  the  active  screen  page.  Under those
     conditions, you should use SCRRESTP/SCRSAVEP or SCRREST/SCRSAVE.

     Example:
          WHERE%=VARPTR(SCR%(1)): SCRNPAGE%=0
          CALL SCRRESTP(WHERE%,SCRNPAGE%): LOCATE OLDROW%,OLDCOL%

















































     Name: SETCOMM

     Type: Miscellaneous / CLONE

     Description:
          Sets   communications   parameters  on  an  opened  communications
     device.  This allows you to set the baud rate higher than BASIC normal-
     ly  allows,  and  to change the comm parameters without having to close
     the comm device.
          Why  is  it  bad  to  have to close the comm device?  Because that
     will  make  the  DTR  signal drop, which will cause many modems to drop
     the  carrier and lose your connection.  In fact, for Hayes-type modems,
     that's  a  much  more reliable way to end communications than using the
     ATH "hang up modem" command.
          If  you  try  to  set  a  comm port which does not exist, the port
     number  will  be set to zero after the call.  If you give illegal para-
     meters  elsewhere,  the port will be set to a default of 300 baud, Even
     parity,  Seven-bit  words,  and  One  stop  bit (any of the parms which
     were legal will be used).

     Example:
          OPEN"R",1,"COM1:300,E,7,1,RS,CS,DS"
          COMMPORT%=1: BPS%=6: PARITY%=0: WORDLENGTH%=8
          STOPBITS%=1
          CALL SETCOMM(COMMPORT%,BPS%,PARITY%,WORDLENGTH%,STOPBITS%)
          REM  sets the port to 19200 baud, No parity, 8 bit words
          REM  and 1 stop bit.

     Settings:
          COMMPORT% may be 1 - 2, and will be returned as 0 if the specified
     port doesn't exist.
          BPS%  ("baud  rate")  is  specified  by  a number from 0 - 7.  Use
     0  for  300  bps,  1 for 600, 2 for 1200, 3 for 2400, 4 for 4800, 5 for
     9600,  6  for  19200,  and  7  for 38400 bps.  Whether you can actually
     get speeds over 9600 will depend on the quality of your comm port.
          PARITY% is a number 0-2.  Use 0 for None, 1 for Odd, 2 for Even.
          WORDLENGTH% may be 7 or 8.
          STOPBITS% may be 1 or 2.




























     Name: SETDRV

     Type: Disk / DOS

     Description:
          Sets  the  default  drive.   The drive string must be at least one
     character long, and start with a letter specifying a disk drive.

     Example:
          DRV$="B:"
            .
            .
          CALL SETDRV(DRV$)




     Name: SETFATTR

     Type: Disk / DOS

     Description:
          Sets  the attribute of a file.  See the section on file attributes
     at the end of this manual.

     Example:
          FIL$=FIL$+CHR$(0)
          CALL SETFATTR(FIL$,ATTR%)




     Name: SETFTD

     Type: Disk / DOS

     Description:
          Sets  file  time/date stamp.  The filename must be terminated with
     a  NUL  character.   The  year  may be either a four digit or two digit
     number  (e.g.,  either  1986  or  just 86).  DOS will round the seconds
     value  off  to  the next lower even number.  If there is a problem with
     the  filename,  the  month  will be returned as -1.  Note that midnight
     is 24:00, not 00:00 (which tells DOS not to display the file's time).

     Example:
          FIL$=FIL$+CHR$(0)
          CALL SETFTD(FIL$,MONTH%,DAY%,YEAR%,HOUR%,MINUTE%,SECOND%)
          IF MONTH%=-1 THEN PRINT "No such file"


















     Name: SETMATI

     Type: Miscellaneous / ANY

     Description:
          Sets  the  first  SIZ%  elements  of  an  integer array to a given
     (scalar)  value,  INITVAL%.   It will work on multi-dimensional arrays,
     in  which  case  the leftmost dimension increments first (unless you've
     set  the  compiler  option  telling  it to do otherwise).  See examples
     for clarification.

     Example:
          OPTION BASE 0: DIM BANANA%(9)
          SIZ%=10: INITVAL%=-3: ARLOC%=VARPTR(BANANA%(0))
          CALL SETMATI(ARLOC%,SIZ%,INITVAL%)
          REM  we have just initialized all 10 elements of the array to
          REM  the value -3.

     Example:
          OPTION BASE 1: DIM FOO%(3,5)
          SIZ%=5: INITVAL%=20000: ARLOC%=VARPTR(FOO%(1,1))
          CALL SETMATI(ARLOC%,SIZ%,INITVAL%)
          REM  we have just set the first five elements of the array to
          REM  20000.  The first five elements are FOO%(1,1), FOO%(2,1),
          REM  FOO%(3,1), FOO%(1,2), FOO%(2,2).  If you want to initialize
          REM  the whole array to 20000, set SIZ%=3*5 for OPTION BASE 1
          REM  or SIZ%=(3+1)*(5+1) for OPTION BASE 0.
          REM  By changing the first element (in the ARLOC% assignment), you
          REM  can set any part of the array, not just the first elements.
          REM  See SCRSAVE/SCRREST if you need to clear up that last point.




































     Name: SETKBD

     Type: Input / CLONE

     Description:
          Sets  the  status  of  the keyboard toggles.  The toggle is set on
     if  the  value  is  nonzero,  and off if the value is zero.  Good style
     suggests  that,  before  using  this  function  for the first time, you
     should  get  the  toggles  with GETKBD (see) and save them.  You should
     then  restore  the  keyboard  to that original state before exiting the
     program.

     Example:
          REM  Let's turn off Insert, Caps Lock, and Scroll Lock
          REM  and put the keypad into numeric mode by turning on Num Lock
          INSERT%=0: CAPSLOCK%=0: NUMLOCK%=1: SCROLLLOCK%=0
          CALL SETKBD(INSERT%,CAPSLOCK%,NUMLOCK%,SCROLLLOCK%)




     Name: SETPOINT

     Type: Video / BIOS

     Description:
          Sets  a  point  on  a  text  screen.   This  allows low-resolution
     graphics  on  monochrome  as  well  as color monitors.  Normal text can
     also  be  mixed  with  the graphics.  Resolution is 80x50 (0-79 columns
     by 0-49 rows).  See also RESETPOINT and TESTPOINT.

     Example:
          ROW%=24
          FOR COLUMN%=0 TO 79
             CALL SETPOINT(COLUMN%,ROW%)
          NEXT COLUMN%
          REM  this draws a line across the middle of the screen.




     Name: SETSUB

     Type: Disk / DOS

     Description:
          Sets  the  default  subdirectory.   The  subdirectory  string must
     be  terminated  by  a  NUL character.  An error will be returned if the
     specified subdirectory doesn't exist.

     Example:
          TMP$=SUB$+CHR$(0): CALL SETSUB(TMP$,ERRCODE%)
          IF ERRCODE% THEN bad subdir ELSE new default subdir selected













     Name: SHIFTL

     Type: Miscellaneous / ANY

     Description:
          Shifts all the bits in an integer left COUNT times, putting zeroes
     in  the bit positions which have been vacated.  This effectively multi-
     plies  the  value  by  a power of two in most instances.  This function
     is  included  for  those  advanced  programmers who know what it's good
     for...

     Example:
          VALUE%=47: COUNT%=3
          CALL SHIFTL(VALUE%,COUNT%)
          REM  we just shifted VALUE% left three bits
          REM  (in this case getting 47 * 2^3, or 376)




     Name: SHIFTR

     Type: Miscellaneous / ANY

     Description:
          Same  as  SHIFTL, but shifts the bits right instead of left.  This
     is similar in effect to an integer divide by a power of two.

     Example:
          VALUE%=47: COUNT%=3
          CALL SHIFTR(VALUE%,COUNT%)
          REM  we just shifted VALUE% right 3 bits
          REM  (here getting 47 \ 2^3, or 5)

































     Name: SOUNDEX

     Type: String / ANY

     Description:
          This  routine  returns  the Soundex code for a string you give it.
     I'm  not sure who invented Soundex, but it's pretty handy.  The Soundex
     routine  takes  a  word  and returns a string which represents what the
     word  sounds  like  in  an abstract format.  Similar-sounding words can
     thus  be  identified  easily  by your program after Soundex processing.
     This  can  be  useful in applications where a person is not sure of the
     exact  spelling  of  a  word/name/city,  etc.   To use, put the word in
     WORD$, initialize the return string SCODE$ to the same length as WORD$,
     and  execute  the  routine.   SLEN%  will  return  the actual length of
     SCODE$,  which  may  vary  from zero to the length of WORD$.  If SCODE$
     is  not  as  long  as  WORD$  when the routine is called, SLEN% will be
     returned  as  -1  to  flag  an  error.  The Soundex code is returned as
     a  series  of  digits  in  SCODE$,  although you can represent this any
     way you choose in your program.

     Example:
          WORD$="AnyWord": SCODE$=WORD$
          CALL SOUNDEX(WORD$,SCODE$,SLEN%)
          PRINT"The Soundex code for ";WORD$;" is ";LEFT$(SCODE$,SLEN%);"."
          REM  Try this routine a few times to get a feel for it.




     Name: SPEAKER

     Type: Miscellaneous / CLONE

     Description:
          This  function  allows  you  to  turn the speaker on or off.  This
     allows you to disable sound effects for a program.  Your sound routines
     will  still  be  executed,  but  will not produce any sound if you have
     turned  the  speaker off.  Thus, your routines will execute at the same
     speed  whether  or  not  sound is turned on, and the timing will remain
     the same.  Note that you should turn the speaker back on before exiting
     the program!
          Use zero to turn off the speaker, nonzero to turn it back on.
          NOTE: This  function  appears  to be erratic, especially when used
     with  slightly  incompatible  machines  such as the AT.  It is unlikely
     to work on a PCjr.  Test it to see if it works for you.

     Example:
          SPKR% = 0
          CALL SPEAKER(SPKR%)
          REM  turn the speaker off
















     Name: STRIP

     Type: String / ANY

     Description:
          Strips  all  occurrences  of a given target character from a given
     source  string.   The  target  string must be at least one character in
     length (if more, the first character will be used).

     Example:
          MSG$="12 - 2 =   10"
            .
            .
          CH$=" ": CALL STRIP(MSG$,CH$,MLEN%): MSG$=LEFT$(MSG$,MLEN%)




     Name: STRIPBLANKS

     Type: String / ANY

     Description:
          Strips  blanks  (and  control  characters) from either the left or
     right  side of a string, or both sides.  Specify 0 (zero) for no strip,
     1 to strip left, 2 to strip right, or 3 to strip both sides.

     Example:
          STRIPWHICH=3: REM strip both sides of blanks
          CALL STRIPBLANKS(ST$,STRIPWHICH%,SLEN%)
          ST$=LEFT$(ST$,SLEN%)



































     Name: STRIPRANGE

     Type: String / ANY

     Description:
          Strips all characters within a given range out of a source string.

     Example:
          MSG$="ALL uppercase letters will be G-O-N-E gone"
          LO%=ASC("A"): HI%=ASC("Z")
          CALL STRIPRANGE(MSG$,LO%,HI%,MLEN%)
          MSG$=LEFT$(MSG$,MLEN%)




     Name: SUBEXIST

     Type: Disk / DOS

     Description:
          Tests  to  see  if  a  given subdirectory exists.  You may include
     a  drive  spec  in  the  subdirectory name, which must be terminated by
     a null.

     Example:
          SUBDIR$="C:\TEMP"+CHR$(0)
          CALL SUBEXIST(SUBDIR$,VALID%)
          IF VALID% THEN PRINT"Subdirectory exists"
          ELSE PRINT"No such subdirectory"




































     Name: TESTPOINT

     Type: Video / BIOS

     Description:
          Tests  a  pixel  on  a  text  screen to see if it's on or off (see
     SETPOINT  for  information  about  text  graphics).  The value returned
     will be set if the point is set, or reset if the point is not set.

     Example:
          COL%=39: ROW%=24: REM  check a point near the middle of the screen
          CALL TESTPOINT(COL%,ROW%,STATUS%)
          IF STATUS% THEN PRINT"The point is lit"
          ELSE PRINT"The point is not lit"




     Name: TIME2INT

     Type: Miscellaneous / ANY

     Description:
          Squeezes  the  time  down to a single integer, for reduced storage
     requirements.   You  will lose some accuracy in the seconds, which will
     be  converted  to  an  even  number (odd numbers will be rounded down).
     To  avoid  ambiguity,  it  is  recommended that you specify hours using
     a 24-hour clock.  See also INT2TIME.

     Example:
          CALL(HOUR%,MIN%,SEC%,SQZTIME%)




     Name: TIMEN2S

     Type: String / ANY

     Description:
          Converts  the  time  from  numbers to a string.  The string should
     be at least eight characters long.  See also TIMES2N.

     Example:
          HOUR%=13: MIN%=30: SEC%=8: TIM$=SPACE$(8)
          CALL TIMEN2S(HOUR%,MIN%,SEC%,TIM$)
          REM  From this, we get TIM$="13:30:08"



















     Name: TIMES2N

     Type: String / ANY

     Description:
          Converts  the  time  from  a  string  to numbers.  The seconds are
     optional, and will be set to zero if nonexistent.

     Example:
          TIM$="13:09:42"
          CALL TIMES2N(HOUR%,MIN%,SEC%,TIM$)
          REM  We get HOUR%=13, MIN%=9, SEC%=42
          TIM$="03:15"
          CALL TIMES2N(HOUR%,MIN%,SEC%,TIM$)
          REM  We get HOUR%=3, MIN%=15, SEC%=0




     Name: TINSTR

     Type: STRING / ANY

     Description:
          Allows  you  to  search  for  a  given  type of character within a
     string.   You  may  search for any of several character types by adding
     the  values of the types to search for.  This also allows you to search
     for  the  opposite  of  a  character type (that is, search for anything
     other than that type).

     Character types:
     1
          Alphabetic  A-Z, a-z
     2
          Numeric     0-9
     4
          Symbolic    (anything not covered by other types)
     8
          Control     (control codes: ASCII 0-31, 127)
     16
          Graphics    (PC graphics codes: 128-255)
     32
          Blank       (a blank space, ASCII 32)

     Example:
          CHRTYPE%=1+2+4+8+16  : REM search for first non-blank character
          CALL TINSTR(ST$,CHRTYPE%,PLACE%)
          IF PLACE%=0 THEN PRINT"The string contains no non-blank chars"
          ELSE PRINT"The first nonblank character is at location";PLACE%;"."

     Example:
          CHRTYPE%=2  : REM search for first numeric character
          ST$="Springfield, VA 22152"
          CALL TINSTR(ST$,CHRTYPE%,PLACE%)
          PRINT"The zip code is: ";MID$(ST$,PLACE%,5)

















     Name: UPCASE

     Type: String / ANY

     Description:
          Converts a string to all uppercase.

     Example:
          MSG$="Four score and seven years ago"
            .
            .
          CALL UPCASE(MSG$)






















































     Name: WEEKDAY

     Type: Miscellaneous / DOS

     Description:
          Returns  an  integer  from  1  - 7 indicating the day of the week,
     Sunday  through  Saturday.  The example routine turns this integer into
     the week day.

     Example:
          CALL WEEKDAY(DAY%)
          DLEN%=VAL(MID$("3346535",DAY%,1))
          DLOC%=ASC(MID$("ADGKQVY",DAY%))-64
          REM  The above string MUST be in uppercase!
          PRINT"Today is";
          PRINT MID$("SunMonTuesWednesThursFriSatur",DLOC%,DLEN%);"day."




     Name: WRITEBITF

     Type: Miscellaneous / ANY

     Description:
          Allows  a value to be written into a given location of a simulated
     array  of  words  of  arbitrary  bit  length (1-8 bits per word).  This
     goes  with  the  READBITF function above.  The "BITF" is for Bit Field,
     because  the  functions work by creating fields of arbitrary bit length
     within what is actually an integer array.

     Example:
          CALL WRITEBITF(ARRAYLOC%,INDEX%,BITFSIZE%,VALUE%)
          REM  See the READBITF function, and see the BITFTEST.BAS if you
          REM  have the ADVBAS contributor disk, to better idea of what's
          REM  going on.  This function is not for novice programmers!






























     Name: XLATE

     Type: String / ANY

     Description:
          This  function  translates a string, character by character, using
     a  table  you supply.  The character's ASCII value is used as the index
     to  the  table, and the value at that location replaces the character's
     current  value.   The  character  may  be  one byte in length, in which
     case  it  will be translated, or zero bytes, in which case nothing will
     happen.   The  translation  string  must  be  256 bytes long (remember,
     strings  may  be  longer  than  255 bytes in Compiled BASIC, so this is
     ok).

     Example:
          XLT$=""
          FOR X%=0 TO 255: XLT$=XLT$+CHR$(X%): NEXT
          MID$(XLT$,1,5)="ABCDE": CH$=CHR$(0)
          CALL XLATE(CH$,XLT$)
          PRINT CH$
          REM  CH$ ends up "A", since the start of the table + zero bytes
          REM      contains "A".  We add zero bytes, because CH$ was
          REM      originally equal to CHR$(0).




     Name: XMPRINT

     Type: Video / BIOS

     Description:
          This  routine  combines the XLATE and MPRINTC functions.  It takes
     a  character,  runs  it  through  a translation table, and prints it to
     the  screen  unless  the translated value is NUL (ASCII zero).  If it's
     NUL,  no  printing  takes  place.   MS-DOS calls are used for printing,
     so  ANSI.SYS will work.  See the XLATE and MPRINTC routines for further
     information.

     Example:
          CALL XMPRINT(CH$,XLATE$,COL%,ROW%): LOCATE ROW%,COL%

























     Name: XQPRINT

     Type: Video / CLONE

     Description:
          This  function  is  an  extended  version  of  QPRINT.  It is more
     flexible,  and  only  a trifle slower.  XQPRINT has two advantages over
     QPRINT: it  allows  you  to  choose  a color/attribute to use, and lets
     you  choose  a  display  page  (color/graphics  adapters  only!).   The
     attribute  ATTR  must  be  set up using the CALCATTR routine.  The page
     argument is ignored for monochrome adapters.

     Example:
          ST$="This is a test of fast screen printing"
          ROW%=10: COL%=20: PAGE%=0
          CALL CALCATTR(FOREGND%,BACKGND%,ATTR%)
          CALL XQPRINT(ST$,ROW%,COL%,ATTR%,PAGE%)




     Name: XQPRINTD

     Type: Video / CLONE

     Description:
          This  function  is  identical  to  XQPRINT, with the one exception
     that  it  writes  directly  to  the  screen.  That makes it even faster
     than  XQPRINT, but means that it will cause snow on some color monitors
     when printing to the active display page.




































                                 File Attributes




          Every  file  has  an  "attribute byte" which tells something about
     the  file.   This  can  be  modified to some extent.  For instance, any
     file  can  be  made  "hidden", in which case it will be invisible; this
     includes  subdirectories,  which  can  still  be used even if you can't
     see  that  they're there.  Some kinds of changes are not possible, how-
     ever: you can't change a subdirectory into a normal file, for example.


     Attribute      Code      Description

     Normal         00h       A normal file.
     Read-only      01h       File can't be killed or rewritten.
     Hidden         02h       File disappears from view.
     System         04h       Like HIDDEN.  For system (DOS, BIOS) files.
     Volume label   08h       A disk's volume label.  Only one, in the root.
     Directory      10h       Subdirectory.
     Archive        20h       Usually set.  May be used for disk backup.


          Combinations  of  the  codes are possible, as I've mentioned.  For
     instance,  a  hidden subdirectory would have a code of 10h + 02h = 12h.
     A  normal  file,  because  of  the archive bit, might show up as either
     00h  or  20h... and  so on.  Note this is all in hexadecimal, hence the
     "h"  postfix.   Convert  to  decimal  form  as  necessary  when calling
     routines  which  use the file attribute.  BASIC has functions to handle
     this  for  you  if you don't understand hex-- see the HEX$ function and
     &H prefix in your BASIC manual.

          NOTE: Reading  the  volume  label is unreliable in versions of DOS
     prior to MS-DOS 3.1, due to a DOS bug.  The most secure way of handling
     it  is to do a search with the label attribute (8), then to doublecheck
     the  actual  attribute  of  the  file  (if any) which was returned.  If
     it's not the volume label, use FINDNEXTF and try again.




























                              New file I/O routines



          This  contains  some  general  information  about the new file I/O
     routines:  FCLOSE, FCREATE, FOPEN, FREAD, FSETEND, FSETREC, and FWRITE.

          These  routines  duplicate  a  number  of  extant BASIC functions.
     They  are  useful,  however, for a number of reasons.  They provide you
     with  low-level  control  over  the  details  of file input and output.
     They  may  be safely used in subprograms, since they return error codes
     rather  than  using error trapping (subprograms have severe limitations
     on  use  of  error  trapping).   They  provide access to the file-level
     locking  capabilities  of  DOS  2.0 and above, which allows creation of
     programs  which  work  on normal computers as well as those with multi-
     tasking  or  networking  (BASIC's  record-level locking is incompatible
     with normal computers unless SHARE is activated).

          In  BASIC,  you give the file a number when you open it, and refer
     to  the  file  by that number from then on.  With the ADVBAS functions,
     you  are  given  a  "handle"  when  you open the file, which serves the
     same  purpose.  In BASIC, a file is automatically created (or truncated
     if  it  exists)  if  you open it for output.  With ADVBAS, you must use
     FCREATE  to  produce  that  result.  If you have an existing file which
     you  want  to  modify  (or  read), use FOPEN.  With ADVBAS, like BASIC,
     you  can  read  or write to a file, or move the file pointer to a given
     record or to the end of file (to append information).  Also like BASIC,
     you must close a file when you are finished using it.

     The error codes returned by these functions are as follows:
       -1    Unable to read or write the entire record
        2    File not found
        3    Path not found
        4    No handle available
        5    Access denied
        6    Invalid handle
       15    Invalid drive specification

          If  you  get  "no  handle  available", you have run out of room to
     open  files.   You  can  fix  this  by not opening so many files at the
     same  time, or by increasing the FILES=xx statement in your CONFIG.SYS.
     See your DOS manual for further information.
























                                   BASCOM Bugs



     Microsoft QuickBASIC Compiler v1.00:

          If  there  is  not enough memory when you try to execute the SHELL
     command, your program will crash.
          The  error  STRING FORMULA TOO COMPLEX appears erratically in some
     programs, for no apparently good reason.


     Microsoft QuickBASIC Compiler v1.02:

          This  release  solves the SHELL crash problem.  Also, more control
     characters  are  now  printed out just like BASICA.  Many miscellaneous
     problems  have  been  fixed... but  not the infamous STRING FORMULA TOO
     COMPLEX error.
















































                                   BASCOM Bugs



     Microsoft QuickBASIC Compiler v2.0 and v3.0:

          If  your  program  uses  error trapping, it must have at least one
     line  number in the program, even you normally only use labels.  Other-
     wise the program will crash if it runs into an error.
          Screen paging doesn't work in v2.0.
          If  you have a REMark on the same line as a DATA statement, you'll
     get peculiar error messages.

          The  programming  environment doesn't work properly with user lib-
     raries  (such  as  ADVBAS)  under  certain  conditions.  In particular,
     compiling  to  an  EXE  or  BRUN  file will produce flaky code.  If you
     run  into  this  problem,  just  compile  the program the old way, from
     the command line.  Instead of
          QB PROGRAM.BAS /L ADVBAS.EXE
     you would use something like
          QB PROGRAM;
          LINK PROGRAM,,,ADVBAS
     to  compile  and  link the program.  You may need to provide additional
     information,  depending  on whether your program uses things like error
     trapping or event trapping.  See your QuickBASIC manual for details.









































     Microsoft QuickBASIC 4.0:

          ADVBAS  functions  which  require  static  arrays will not work in
     the  environment,  due  to a bug in QuickBASIC.  You may be able to use
     them  by  declaring  them in COMMON statements, but do this at your own
     risk.   You  can  still  use  these  routines in programs compiled with
     the  stand-alone  version,  BC.EXE,  however,  except for GETSCREEN and
     PUTSCREEN.   Note  that  this problem does not affect ProBas functions,
     which  were written to deal with dynamic arrays as well (and the static
     arrays  in  the  QB4  environment  behave somewhat similarly to dynamic
     arrays).

          When  you try to produce an .EXE file from the QuickBASIC environ-
     ment,  the  compiler  (QB.EXE)  executes the stand-alone version of the
     compiler  (BC.EXE)  in  order  to  compile your program.  No problem so
     far,  although  it  means you must have your libraries in both .QLB and
     .LIB  form.   Then  QB  executes  the  LINK utility (LINK.EXE) in order
     to  create  the final .EXE file.  Trouble!  For obscure reasons, Quick-
     BASIC  specifies  the  parameters  for  the  LINK  command in the wrong
     order.   This  works,  sort  of... that  is, if you're using libraries,
     it  will  make  your  programs much larger, because it links everything
     in  the library rather than just the routines you use.  It also ignores
     your  DOS  environment  setting  for the library location, meaning that
     you  need  to  have  your  libraries in the current drive/subdirectory.
     Finally,  it  may not work at all if you have a lot of routines in your
     library.  This is really a nuisance!

          Solution: don't  create  .EXE  files  from within the environment.
     Only  use  the  environment  for  debugging,  and create the final .EXE
     files  yourself  with  BC  and  LINK,  using the old syntax.  Don't try
     to add the library to the filename, the way QB tries to do, but instead
     specify the library name when LINK asks you for libraries.


































     Notes on Microsoft's QuickBASIC v4.0:

          You  might  guess  from  the  version  number  that this is merely
     another  in  a  series  of  improvements  to QuickBASIC.  In fact, this
     version  represents  an  entire  rewrite  of  the compiler.  The result
     is  in  general much more powerful than earlier versions of QuickBASIC,
     but does have its own quirks.

          Some  of the nice new features: recursive functions and procedures
     (at  last!),  long integers (with a range of plus or minus two billion,
     this  numeric  type  is very handy, and is provided in many languages),
     code  which  can  be  linked  with other languages (subject to a number
     of  limitations),  and  an  improved compiling environment.  The editor
     provided  in  the  environment  now  accepts Wordstar-type commands, as
     well  as  Microsoft's  own  esoteric  commands.  Programs are instantly
     compiled  into  "p-code"  as  you enter them, which gives you automatic
     syntax  checking  (can  be  turned  off)  and reformatting (which can't
     be  turned  off),  and  means  you  never have to wait for your program
     to  compile.   The reformatter makes all BASIC keywords uppercase, puts
     spaces  between  parameters  to  a function call, makes all occurrences
     of  a  given  variable  have the same case as the last time you entered
     it,  and so forth.  Many people find this a nuisance, but on the whole,
     I  think  I  like  it.  Input and output now take place through DOS, so
     you  can easily redirect input or output from the command line.  Output
     to  the  screen is also faster, if you've got an ANSI driver installed,
     since  ANSI  is  more  efficient  than  the old BIOS calls.  The screen
     is  no  longer  automatically  cleared  when your program starts, which
     is very nice.

          Problems: there  is  a  new  library  format for the environment--
     QLB  instead of EXE.  Old assembly routines usually need to be modified
     to  work  with  QB4 whether or not the environment is used.  Procedures
     and  functions  are  kept in separate areas from your main program, and
     it  takes  several  keystrokes  to  get at them.  If you are particular
     about  the  style  of  your  code,  you may hate the reformatter.  Code
     produced  is  about  the same size or larger, but is much slower unless
     you  have  a  numeric  coprocessor  (8087,  80287, or 80387) installed.
     There  is  less  string  space available than in older compilers, which
     may cause trouble with large programs.

          Personally,  I really like most of the changes.  I have been look-
     ing  for  some  of  these  features  for a long time, and it's great to
     see  them.   There  are a lot of drawbacks too, though, and many people
     don't  like the new compiler.  You'll have to draw your own conclusions
     on  this  one.  It's worth the (painful) wait for the upgrade, though--
     if  QB4  suits  you,  it  will improve your productivity immensely.  If
     not... put  it  up for sale, this is going to be a top seller.  Despite
     its other problems, QB4 is a very convenient environment for beginners,
     especially  those  moving  from interpreted BASIC.  This is one product
     that is going to do Real Well.
















     Notes on Borland's Turbo BASIC v1.0:

          Turbo  BASIC  is almost completely compatible with BASICA/GWBASIC,
     and  fairly  compatible  with  QuickBASIC.  It supports recursive func-
     tions,  local  variables, long integers, and the 8087 chip, among other
     things.   It  has  a  fairly  slick  windowing programming environment,
     and features online, context-sensitive help.  The editor is a configur-
     able  Wordstar-type  editor.   Code  size  and speed seem to be roughly
     comparable  to QuickBASIC (probably better than QuickBASIC 4.0).  Turbo
     BASIC's  main  fault  seems  to  be  that it lacks an assembly language
     interface--  it  uses  a  machine-language  INLINE  format like that in
     Turbo  Pascal.  This is more than enough to dissuade me from converting
     ADVBAS  to  work  with  Turbo BASIC.  Otherwise, though, it's nearly as
     strong  a  product  as  Microsoft's QuickBASIC, and it looks like we're
     shaping up for some fine marketing battles.





                                   BASIC Bugs




          This  is  a  peculiar  one... it seems that BASIC can create files
     having  names  which  contain blank spaces.  This is a problem, because
     DOS  considers  the  space  to  be  a delimiter, and thus cannot handle
     these files.  Such files will not be listed correctly in the directory,
     and  will  be  impossible  to  manipulate from DOS (can't read, delete,
     or  otherwise  handle  the  file).  So, be careful to screen out spaces
     when  creating files from BASIC!  This caveat also applies to subdirec-
     tories, including those created with the MAKESUB routine of ADVBAS.

          If  you take the VAL() of a string, you expect the value converter
     to stop when it runs into the end of the string or a non-numeric charac-
     ter.   Trouble  is,  BASIC  ignores spaces rather than treating them as
     non-numeric  characters.   So  if  you  try  A = VAL("256 12") you will
     not  get  A  =  256, as you thought, but actually A = 25612.  Surprise!
     Microsoft  does  not  consider  this a bug, although it's hard to think
     of an application in which this behavior might be appropriate.



















