home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / qbasic / asylib11.zip / ASYLIB.DOC < prev    next >
Text File  |  1988-10-30  |  69KB  |  1,589 lines

  1.  
  2.  
  3.     AsyLIB - Documentation
  4.     version 1.10
  5.     Released  October, 1988
  6.     -Gizmo Mike
  7.  
  8.  
  9.     I. Introduction
  10.  
  11.     AsyLIB is a complete set of primitives for developing telecommunications
  12.     programs and utilites from QuickBASIC.  This library is compatible with
  13.     QuickBASIC 4.00, 4.00(a) and 4.00(b) as well as the MicroSoft BASIC
  14.     Compiler 6.00, though we _heartily_ recommend QB 4.00(b) or BC 6.0.
  15.     Included in the developer's kit are routines for 8 different file
  16.     transfer protocols, character I/O, ANSI.SYS support, keyboard control,
  17.     symbolic carriage return support for storing macro files to disk, even
  18.     a robust script language and a not-so-primitive terminal program to
  19.     demonstrate some of the functions, as well as many support items.  The
  20.     collection includes both low level and high level routines, with the
  21.     bulk being in BASIC with many, many support items being in assembler.
  22.  
  23.     By supplying things like low level routines to read blocks from disk,
  24.     there is no dependency on ANY general purpose library collection and
  25.     therefore, you may not need to buy anything else to get your own
  26.     terminal programs up and running.
  27.  
  28.     However, it must be noted that the addition of things like windows and
  29.     screen saves, will not only reduce the overall code size and development
  30.     time, but it will speed up program execution and most of all, will add
  31.     that flash and dazzle found in most all well written programs.
  32.  
  33.     The demo program included is a fully working implementation of a
  34.     terminal program that simply attempts to demonstrate how easy it is to
  35.     construct a terminal program of your own with modular, 'callable'
  36.     telecommunications routines.
  37.  
  38.     The key to the ease of use in AsyLIB is that it is totally modular:
  39.     practically everything is a CALLed sub program that means code is
  40.     extremely easy to read and program.  Further, virtually every
  41.     function is therefore available throughout the program and you can add
  42.     only those that you need:  if you have a singular purpose application in
  43.     mind that only needs to support say, Xmodem or Ymodem-G, then you need
  44.     not wade thru tons of GOTO AND GOSUB code, and waste hours editing out
  45.     Xmodem1k code and so forth: you simply execute CALLs to those you need
  46.     and let LINK tie in those that are used.
  47.  
  48.  
  49.  
  50.  
  51.  
  52.     II.    License, conditions of use
  53.  
  54.        Under no circumstances may these routines be distributed individually
  55.     or without the accompanying documentation and demo, which are both an
  56.     integral part of the package, nor may the documentation be altered in
  57.     anyway.  This includes, but is not limited to, distributing ASYLIB.QLB
  58.     for use in executing applications compiled to BRUN format.
  59.  
  60.        Under no circumstances may the routines in the AsyLIB package,
  61.     source, object files, libraries or documentation be distributed by or
  62.     otherwise become a part of, or affiliated with any group or organization
  63.     involved in the distribution of what is generally been come to be known
  64.     as SHAREWARE for disk or distribution fees, or for fees of any sort
  65.     without my express WRITTEN consent.  This includes supplying the
  66.     routines, library and or documentation for so-called disk fees.
  67.  
  68.        Finally, as the author, I make no claims that the routines herein
  69.     will fit your needs, simply that in all testing and prior use that they
  70.     worked for me and that you may find them interesting and helpful in your
  71.     programming.  Any liability for the use, misuse or inability to use the
  72.     AsyLIB routines or libraries, lies solely with user of AsyLIB.
  73.  
  74.  
  75.  
  76.     III.  AsyLIB
  77.  
  78.  
  79.     A.   AsyLIB  Compatibility
  80.  
  81.        Because QB has built in COM port support, in this case it would be
  82.     counter productive to replace them, so the majority of the AsyLIB
  83.     functions are in BASIC.  These were written with the MS BASIC Compiler
  84.     6.0 and should work equally as well with QB 4.00(b).  Note that prior
  85.     versions (read: QB 4.00 and QB4.00(a)) do have a few com port handling
  86.     problems.  If you are planning to attempt TCOMM related programs, you
  87.     are strongly urged to upgrade to QB 4.00(b), especially since it is
  88.     free from MicroSoft.
  89.  
  90.        The AsyLIB functions and routines are not suitable for use with
  91.     versions of QuickBASIC prior to QB 4.00.
  92.  
  93.  
  94.  
  95.     B.    Support
  96.  
  97.        As long as it exists, I will support and entertain questions
  98.     regarding QB, GLIB, DLIB or AsyLib via the QuickBASIC conference
  99.     on The Information Booth, (316) 684 8744, 1200 - 19200 bps, 24 hrs.
  100.     This is a "free" BBS, though registration is required.
  101.        If you have a problem or question on GLIB, DLIB or AsyLIB, PLEASE be
  102.     prepared to supply some sort of source code to demonstrate your problem.
  103.     I am more than a little interested in any LIB or QB bugs that you might
  104.     find, but PLEASE do not waste my time or yours with general, vague
  105.     inquiries without supporting source examples - I do not need .EXE's.
  106.  
  107.  
  108.  
  109.  
  110.     C.   License
  111.  
  112.        You are granted free and unlimited use of any and all routines in
  113.     AsyLIB that you may find of value.  Furthermore, you are free to pass
  114.     along the BBS distribution files (the demo and the documentation)
  115.     as long as they are passed along as a whole according to the guidlines
  116.     listed above.
  117.        No one is granted any permission to share or pass along the BCOM
  118.     library, nor object files or source code.
  119.  
  120.  
  121.  
  122.     D.    Purchase
  123.  
  124.        As distributed, the AsyLIB documentation, the demo and the
  125.     environment library (.QLB) provide you with everything you need to call
  126.     and execute AsyLIB routines from within the editor/environment.
  127.     In this manner, the user or programmer is granted unlimited rights for
  128.     using AsyLIB with QuickBASIC and the supplied .QLB library for personal
  129.     use either from the QB environment or even in the form of a 'BRUN' style
  130.     compiled library.
  131.  
  132.        This provides an ample forum for purposes of sampling, testing and
  133.     evaluation and allows unlimited latitude in terms of personal use or as
  134.     a tutorial regarding some of the more advanced features in today's
  135.     QuickBASIC.  If any of these are your intention, then the files included
  136.     with this documentation provide everything you need, and you are free to
  137.     use them in that format without further obligation.
  138.  
  139.        However, you might find some of the routines of value and want to
  140.     incorporate them into a standalone (BCOM type .EXE) application.  In
  141.     this case, the library of routines and permission to use them in such
  142.     applications can be purchased as described below.
  143.  
  144.        This is the best of all worlds:  You get unlimited personal and/or
  145.     evaluation use.  If you find it of value, the BCOM library can be
  146.     purchased.  If AsyLIB does NOT fit your needs, then you are 'out'
  147.     nothing, not even the time to download the .LIB file(s).
  148.  
  149.  
  150.     AsyLIB prices are as follows:
  151.  
  152.     BCOM .OBJ / LIB files, only             $ 30.00
  153.     BCOM .OBJ / LIB and BASIC source        $ 55.00
  154.  
  155.     Compare this with "commercial" .LIBS that sell for _TWICE_ as much:
  156.       The one that goes for $79 and NO SOURCE!
  157.       The one that runs a whopping $99 and requires another library!
  158.       The one that costs $129 and supports only XMODEM !!!
  159.  
  160.       ...and NONE have a free try out period !!!!!
  161.  
  162.                     Who pays for those goofy ads they run?
  163.                                  YOU DO
  164.  
  165.  
  166.     Regardless of the license level, you get everything in the BBS file
  167.     collection plus:
  168.     - A QB or BC LIB containing all the routines documented later, as well
  169.       as the object files themselves.
  170.  
  171.     - An Asynchronous communications overview with an in-depth
  172.       discussion of all the protocols supported.
  173.  
  174.     - A collection of QB4 / TCOMM programming tips and notes based on the
  175.        AsyDEMO.BAS terminal program provided and various things we
  176.        encountered in developing AsyLIB.
  177.  
  178.  
  179.  
  180.     - A Script File to disk routine that allows you to store compiled
  181.       script files to a file thus precluding the need to link in the
  182.       script file compile routine, reducing code size and execution time!
  183.       A complementary routine to read such a compiled file from file back
  184.       into memory at run time is also provided.
  185.  
  186.  
  187.     To purchase either the AsyLIB Object File/.LIB or the BASIC
  188.     Source Code library license (ASM source is not supplied):
  189.  
  190.     a. Fill out the enclosed mailer, with Cash, check or money order
  191.        payable in U.S. Funds and mail it to the address supplied on the
  192.        mailer.
  193.  
  194.     b. Orders not accompanied with the mailer/order form will be returned
  195.        as we need the information requested to correctly fill your order.
  196.  
  197.     c. Please allow 3-4 weeks for delivery (I am out of town a LOT).
  198.  
  199.  
  200.     Mailing Address:
  201.                                   InfoSoft
  202.                                  AsyLIB 1.1
  203.                                PO Box 782057
  204.                                  Wichita, Ks
  205.                                        67278-2057
  206.  
  207.  
  208.  
  209.  
  210.     IV.   Demo program notes
  211.          The demo program is not meant to be a Procomm or Qmodem
  212.     replacement.  Rather, it is meant as a vehicle to demonstrate some of
  213.     the basics of QB communications I/O and the functions of the AsyLIB
  214.     package.  In reality, were I to attempt to take on such a task, I would
  215.     NOT attempt it without a solid general library package to provide
  216.     support for such things as windows, screen saves and a text input
  217.     editor.  Without it, coding is considerably more tedious and lots less
  218.     flashy.
  219.  
  220.  
  221.         The demo vehicle, while fully functional, is meant more as a vehicle
  222.     to demonstrate some of the features in AsyLIB and spur some interest in
  223.     ideas that could be in a communications program.
  224.  
  225.     Some of the features you will find in the demo include:
  226.     o   A file upload and download counter or filed for each directory
  227.         entry.  AsyDemo  automagically increments each field once a
  228.         transfer is judged successful.
  229.  
  230.     o   Full macro key support including symbolic carriage return
  231.         character support.
  232.  
  233.     o   A high powered and robust Script Language module supporting
  234.         over FORTY functions and statements including IF/ELSE/ENDIF blocks!
  235.         This ScriptFile module allows your terminal program to operate
  236.         from a command file or script file.
  237.  
  238.  
  239.  
  240.         -  This support is comprised of a script file 'compiler'; by
  241.            producing a symbolic representation of the script file in memory,
  242.            syntax errors are caught prior to execution and execution time is
  243.            decreased to a minimum since the entire script file is held in
  244.            memory - no disk hits after the compilation.  This approach also
  245.            allows you to write support modules that check script files for
  246.            syntax prior to run time.  You need not even include the script
  247.            file compiler into your program!
  248.  
  249.         -  Another module 'decompiles' the script file into run time
  250.            function commands and arguments.  This is invoked with a simple
  251.            CALL statement!
  252.  
  253.           Of course, those who purchase a source license will get the source
  254.           to these modules and a discussion on adding more complex
  255.           statements and functions to the script language.
  256.  
  257.     o  An auto-password log on feature:  independant of any loaded macro
  258.        file, Alt-Q sends your password to the remote system.  AsyDemo
  259.        stores a password for each dialing directory entry as well as a
  260.        comment field and a file transfer count.
  261.  
  262.  
  263.  
  264.         In spite of these features ASYMODEM is meant primarily as a
  265.     demonstration vehicle for the AsyLIB functions and for its tutorial
  266.     aspects of QB4 and async programming.  Some of the features it lacks
  267.     for it to be a full featured TCOMM program include:
  268.  
  269.     o   A way to edit an existing macro file.  This is simply because QB's
  270.         native INPUT and LINE INPUT are inadequate for such things.
  271.  
  272.     o   The AsyLIB demo, AsyDemo, supports CR translation to CR or CR/LF
  273.         for incoming carriage returns, and the Script Language has
  274.         both incoming AND outgoing translation commands supported, the
  275.         terminal demo does not got so far as to translate incoming Carriage
  276.         Returns.  That is the terminal package demo does not support all
  277.         aspects supported by the Script File package.
  278.  
  279.     o   The dialing directory fully supports fields for such things as a
  280.         comment, an upload or download count and such, yet there is no way
  281.         to display these items.
  282.  
  283.     o   The Redial support is suitable for Hayes compatible modedms at best.
  284.  
  285.     o   Many of the keyboard I/O occasions crudely use simply BASICA
  286.         statements like LINE INPUT rather than a professional level
  287.         text input editor like FED.
  288.  
  289.     o   The Alt+Key menu functions do not allow a way to suspend a log,
  290.         although this is fully supported in the Script File language AND
  291.         demo.  There are several occasions of this where we have built in
  292.         abilities or functions into the script file language not supported
  293.         in the demo.
  294.  
  295.  
  296.  
  297.        Much of the logic behind some of the demo program's specifics is
  298.     explained in ASYNC.DOC supplied upon registration, however there are a
  299.     few points that inpact directly on the routines:
  300.  
  301.     First, a named COMMON block is used to make variables available to
  302.     other modules (sub programs) within the demo and library.  This cuts
  303.     down on the number of variables that need to be passed explicitly as
  304.     parameters for various calls, and also allows "automatic" access to
  305.     these key variables to any sub program that might need it.
  306.  
  307.     The block is:
  308.  
  309.          COMMON SHARED /TComm/ Bps%, Com$, ComFileNum%
  310.  
  311.     and should not be changed for the code to perform correctly.
  312.  
  313.  
  314.            Bps:  The current active baud rate.
  315.           COM$:  String representation of the comport in use.  IE "COM1" or
  316.                  "COM2"
  317.     ComFileNum:  The basic filenumber assigned to the comport file.
  318.  
  319.     This is setup in part for easy expansion and in part for some sub
  320.     program reasons that no longer exist.  However, if these variables are
  321.     used as global parameters throughout the terminal level code module, any
  322.     changes made to these is automatically reflected everywhere necessary.
  323.  
  324.  
  325.     In many places, you will note the use of SLEEP.  This command is
  326.     available in QB 4.00(b) and acts as a WHILE inkey$="":WEND loop but with
  327.     the additional function of terminating in x number of seconds OR if a
  328.     key is pressed.  If your implementation of QB4 does not support SLEEP,
  329.     replace this with the appropriate WHILE/WEND loop.  In many places the
  330.     code is provided but REMmed out.
  331.  
  332.     The initial dialing directory, contains only an entry for the Information
  333.     Booth set at 2400-N-8-1.  Likewise the ASYDEMO.INI file is preset to
  334.     2400-N-8-1.  You may delete these if you wish to reset the defaults,
  335.     or use the setup facility to set new ones.
  336.  
  337.     The terminal program uses the following external files:
  338.     ASYAUTO.SCR - Script to execute immediately upon start up (optional)
  339.     ASYAUTO.MAC - Macro file to load upon start up (optional)
  340.  
  341.     ASYDEMO.DIR - Dialing directory
  342.     ASYDEMO.INI - Terminal defaults
  343.  
  344.     ASYXTERN    - Used by the external protocols
  345.     ASY_R?.BAT  - External protocol RECV batch file.  1 for each external
  346.                   protocol.
  347.     ASY_S?.BAT  - External protocol SEND batch file.  1 for each external
  348.                   protocol.
  349.  
  350.  
  351.  
  352.  
  353.     V.      Script File Language
  354.  
  355.         As is, the script file language supports over 40 key functions.
  356.     The Script File Language supports modules to compile and interpret a
  357.     script file as well as 2 additional routines to read and write a com-
  358.     piled script to disk are included in both the LIB and source code
  359.     licenses.  Those who purchase a source code license will get complete
  360.     source to the script file compiler and reader and the ability to add as
  361.     many additional functions as their desire, ingenuity (and programming
  362.     ability) allow.
  363.  
  364.     Script file commands:
  365.  
  366.     ALARM x      -  Sound the alarm for x seconds.
  367.     ATIME x      -  Sets the default number of ALARM cycles.
  368.     BAUD x       -  Set the BPS parameter to x
  369.     CBUFFER      -  Clears the comport buffer - same as
  370.                      Alt-B (Burp ?) from terminal mode in ASYMODEM
  371.     CDET         -  Sets a module level variable indicating the carrier
  372.                     detect state.  This allows for easy further expansion
  373.                     beyond 'IF CD'.
  374.     CLRS         -  Clear the screen
  375.     COLOR x      -  Set the screen colors to th attribute x
  376.     CLOG         -  Close the log file
  377.     CRIN         -  Set the carriage return IN option (CR or CR/LF)
  378.     CROUT        -  Sets the carriage return OUT option (CR or CR/LF)
  379.                     that you may implement in your terminal package.
  380.     DATABITS x   -  Set the Databits or WordLen paramter to x.
  381.     DIAL x       -  Dials entry x from the fone directory.
  382.     DELAY x      -  Pauses x seconds
  383.     ECHO [ 0|1 ] -  Sets the echo status ON (1) or OFF (0)
  384.     ELSE         -  Indicates an alternative block of statements
  385.                       to execute in a IF/ELSE/ENDIF block
  386.     ENDS         -  Stops the script file, exits to terminal mode
  387.     ENDIF        -  Marks the end of an IF...END IF block
  388.     EXEC y$      -  Executes script file represented in y$
  389.     HANGUP       -  Hangs Up the phone
  390.     IF           -  The classic block IF/ELSE/ENDIF.  In this implementation,
  391.                     the the only subject conditions to the IF statement are
  392.                     'waitfor' and 'cd' to test the state of the last
  393.                     WAITFOR x$ x or the state of the carrier.
  394.     LMODE [APPEND | OUTPUT ]
  395.                  -  Sets the log file write mode
  396.     LOCATE x y   -  Locates the cursor to location x, y (note no comma in
  397.                        the script file syntax).
  398.     LOGN y$      -  Sets the Log file name to that named in y$.
  399.     MLOAD y$     -  Loads the macro file named in y$
  400.     MSEND x      -  Sends entry x from the loaded macro file.
  401.     OLOG         -  Opens the log file named in LOGN for write mode specified
  402.                        in LMODE
  403.     PASSWORD     -  Sends the password stored for the dialing directory
  404.                     entry you are online with.  Equivalent to Alt-Q from
  405.                     the Terminal mode keyboard.
  406.     PARITY x     -  Sets the parity variable to x
  407.     PORT x       -  Set the active comport to x.
  408.     PRINT y$     -  Prints the String y. See CRXlate and SetCRChar for
  409.                        information on embedded carriage return characters.
  410.     PREFIX y$    -  Sets the dialing prefix (ATDT, ATDP, ATDT15559000 etc) to
  411.                       that specified in y$
  412.  
  413.  
  414.     PROTOCOL x   -  Sets the protocol pointer to x.
  415.     QUIT         -  Exits the terminal package
  416.     RECV y$      -  Recieves the file indicated by y$ using the protocol set
  417.                       by the PROTOCOL command.
  418.     RLOG         -  Resumes logging to a log file previously suspended (SLOG).
  419.     RSHELL       -  Remote Shell
  420.     SEND y$      -  Sends file y$ using the protocol indicated by PROTOCOL
  421.     SETC         -  Sets Comport and parameters to those indicated by
  422.                       script commands CPORT, BAUD, DATABITS, STOP and PARITY.
  423.     SLOG         -  Suspends logging to the log file, until closed (CLOG) or
  424.                        resumed (RLOG).
  425.     STOPBITS x   -  Sets stop bits to x
  426.     TERMINAL     -  Enter Terminal mode
  427.     TRANSMIT y$  -  Sends the string y$ to the active comport.  See CRXlate
  428.                      and SetCRChar for information on embedded carriage
  429.                      return characters.
  430.     WAITFOR y$ x -  Wait for the string x$ for a maximum of x seconds.
  431.                     In addition to performing the WAITFOR act, it sets a
  432.                     module level variable that can later be tested with the
  433.                     IF statement.
  434.     ;            -  Remark character: everything after a semi colon is
  435.                       ignored
  436.  
  437.  
  438.     x   is any valid integer numeric.  Integer EXPRESSIONS such as
  439.         (Qwerty - Foobar)
  440.         are NOT supported
  441.     y$  is any UNQUOTED string LITERAL:
  442.          WAITFOR foobar 22     ...is legal
  443.          WAITFOR y$ 22         ...is not legal
  444.          WAITFOR "foobar" 15   ...is not legal
  445.  
  446.  
  447.     NOTE:  The strings arguments to script file statements and functions
  448.     are _NOT_ to be enclosed in quotes.  Example:
  449.  
  450.     CORRECT:
  451.            WAITFOR graphics 35
  452.  
  453.     WRONG:
  454.           WAITFOR "graphics" 30
  455.  
  456.     ScrCompiler uses the spaces in the line read to parse the arguments and
  457.     does not need quotes.
  458.  
  459.  
  460.     Further, the TAB character is not supported, the script file handler
  461.     routines will not parse the line correctly that has embedded TABS:
  462.     you may want to write a pre-processor to swap out TABS for spaces (or
  463.     remove them).
  464.  
  465.  
  466.  
  467.  
  468.  
  469.     VI.    Routines
  470.  
  471.     NOTE:  The Demo and the AsyLIB routines make use of a COMMON SHARED
  472.     block to make a number of parameters available to all routines who might
  473.     need them or might in the future.  The following line of code initiates
  474.     such a common block:
  475.  
  476.     COMMON SHARED /TComm/ Bps%, Com$, ComFileNum%
  477.  
  478.     In this manner, these parameters need not be passed to routines but are
  479.     implicitly available to them.
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.     Name: AnsiCol                 Type: Function             Source: BAS
  487.     Syntax: errc = AnsiCol(Col%, a$)
  488.  
  489.     This returns into a$, a string containing ANSI codes that will LOCATE
  490.     the local and remote cursor to the desired column position passed in
  491.     Col%.  This string must be printed or run thru ANSI for it to work, and
  492.     naturally ANSI must be loaded.  Errc is set (-1) when the column is
  493.     not valid (not in the range 1 to 80).
  494.  
  495.     Example:
  496.     errc = AnsiCol(4, a$)              ' get string for LOCATE 4, via ANSI
  497.     IF errc = 0 THEN                   ' col was legitimate
  498.         CALL AnsiPrint(a$, Arow, Acol) ' locate/print it locally
  499.         CALL SendString(a$, 0)         ' locate/print it on remote
  500.     END IF
  501.  
  502.  
  503.  
  504.     Name: AnsiColor               Type: Function             Source: BAS
  505.     Syntax: errc = AnsiColor(fg%, bg%, a$)
  506.  
  507.     Returns into a$ a string of ANSI codes to set the local and/or remote
  508.     terminal's colors to those indicated by fg and bg.  This allows you to
  509.     pass it BASIC color codes and let it make an ANSI string from them.
  510.     Errc is set (-1) if any of the colors is out of range (fg 0 to 31, bg 0
  511.     to 7).
  512.  
  513.     Example:
  514.     errc = AnsiColor(14, 0, a$)        ' get ANSI color$ for COLOR 14, 0
  515.     IF errc = 0 THEN
  516.         CALL AnsiPrint(a$, Arow, Acol) ' print it locally
  517.         CALL SendString(a$, 0)         ' print it on remote
  518.     END IF
  519.  
  520.  
  521.  
  522.     Name: AnsiRow                 Type: Function             Source: BAS
  523.     Syntax: errc = AnsiRow(Col%, a$)
  524.  
  525.     This returns into a$, a string containing ANSI codes that will LOCATE
  526.     the local and remote cursor to the desired row position passed in
  527.     Row%.  This string must be printed or run thru ANSI for it to work, and
  528.     naturally ANSI must be loaded.  Errc is set (-1) when the column is
  529.     not valid (not in the range 1 to 80).
  530.  
  531.     Example:
  532.     errc = AnsiRow(4, r$)              ' get string for LOCATE 4, via ANSI
  533.     errc = AnsiCol(1, c$)
  534.     ans$ = a$ + b$
  535.  
  536.     CALL AnsiPrint(ans$, Arow, Acol)   ' locate/print it locally
  537.     CALL SendString(ans$, 0)           ' locate/print it on remote
  538.  
  539.  
  540.  
  541.     Name: BaudRate                Type: Function             Source: BAS
  542.     Syntax: IncomingBaud = BaudRate(Cport)
  543.  
  544.     This reads the connected, baud rate from the serial port indicated.
  545.     While 'smart' modems may automatically adjust to the correct incoming
  546.     speed when in answer mode, you may well want to change the terminal
  547.     program's parameters - likewise in a BBS system.  This could be done
  548.     with a call to ReadBaud and then a call to CommPortInit (see the caution
  549.     under CommPortInit).
  550.  
  551.     Example:
  552.     IncBaud = BaudRate(Cport)          ' read the callers baud rate
  553.     IF IncBaud <> BPS THEN             ' Caller BPS = ours?
  554.         BPS = IncBaud                  ' nope, make global var theirs
  555.         CALL InitComPort(CPort, BPS, Parity, Wlen, StopBits)
  556.     END IF
  557.  
  558.  
  559.  
  560.     Name: CANAbort                Type: SUB                  Source: BAS
  561.     Syntax: CALL CANAbort
  562.  
  563.     This is a simple routine to send the normal CAN-ABORT sequence to the
  564.     other side to indicate an aborted or cancelled file transfer.  As a
  565.     CALL, it can be shared by all the file transfer procedures reducing
  566.     overall code size and make constructing your own protocols a bit
  567.     easier.
  568.  
  569.     Example:
  570.     IF x$ = CHR$(27) THEN              ' local KB input is Escape
  571.         CALL CANAbort                  ' tell other side to forget it
  572.         EXIT SUB                       ' exit to main code
  573.     END IF
  574.  
  575.  
  576.  
  577.     Name: CarrierDetect           Type: Function             Source: ASM
  578.     Syntax: cd= CarrierDetect(ComPort%)
  579.  
  580.     Returns a value indicating whether DCD (Data Carrier Detect) is true
  581.     or not for the indicated Comm Port.  This works only for COM1 or COM2 as
  582.     yet, and the ComPort parameter must be an INTEGER.  CarrierDetect will
  583.     return -1 for other than COM1 or 2 and non zero indicating TRUE DCD.
  584.  
  585.     Example:
  586.     IF CarrierDetect(1) = 0 THEN
  587.         GOTO LostCarrier
  588.     END IF
  589.  
  590.  
  591.  
  592.     Name: CCITCRC                 Type: SUB                  Source: ASM
  593.     Syntax: CALL CCITCRC(datastring$, CRCHi%, CRCLo%)
  594.  
  595.     Caluculate a hi and lo CRC value for a string.  This is similar to
  596.     CheckSumCRC but is much faster.  CheckSumCRC uses the polynominal method
  597.     to calculate the CRC, whereas CCITCRC uses the table lookup method.
  598.     This means it is a bit bigger than the polynominal method, but much
  599.     faster.  For optimum performance, AsyLIB uses the combined CRC-CheckSum
  600.     method for Xmodem which needs to be able to slip from one to another,
  601.     but the CCIT table look up method for Xmodem1k and all Ymodem variants
  602.     where the datastring is 1024 (compared to 128 bytes for Xmodem).  this
  603.     assures optimum performance.  All paramerters must be integers.
  604.  
  605.     Note: You will only need to actually use either CCITCRC or CheckSumCRC
  606.     if you decide to tinker with your own protocol or one of those in
  607.     AsyLIB.
  608.  
  609.     Example:
  610.     CALL CCITCRC(x$, CRCHi%, CRCLo%)
  611.  
  612.  
  613.  
  614.     Name: CheckSumCRC             Type: SUB                  Source: ASM
  615.     Syntax: CALL CheckSumCRC(DataString$, ChkSum%, CRC, CRCHi, CRCLo)
  616.  
  617.     This is a highly useful routine for use in XMODEM file transfer
  618.     routines.  Since it returns BOTH a checksum and a CRC, it is ideally
  619.     suited for XMODEM routines that should be able to 'sense' which mode,
  620.     CheckSum or CRC, is active.   With both calculations in one routine,
  621.     code flow based on 'IF CRCMode' type evaluations is considerably easier.
  622.     Further, while CRCHi and CRCLo are typically used in CRC based
  623.     protocols, the single byte CRC return allows for use in 'homegrown' type
  624.     protocols or KERMIT which does support a 1 byte CRC mode.
  625.  
  626.     Since this is in ASM, each and every parameter must be of INTEGER type.
  627.  
  628.  
  629.  
  630.     Name: CommPortInit            Type: Function             Source: ASM
  631.     Syntax: errc = CommPortInit(Port%, bps%, parity%, word%, stop%)
  632.  
  633.     This is the ASM equivalent to ComPortSetup, performing essentially the
  634.     same function with one major difference: Once opened via BASIC, the only
  635.     way to change settings is to CLOSE the file/port and thus break the
  636.     connection, only to reopen it at the new settings.  InitCom allows these
  637.     settings to be changed on the fly as needed - usually.  The viability of
  638.     this depends in part on the QB 4.00 flavour you are using:  we have had
  639.     no problem using this with QB 4.00 and the (a) version, but strange
  640.     things seem to happen in 4.00(b).  If you use CommPortInit, be sure to
  641.     thoroughly test your application in both the environment and EXE form!
  642.  
  643.     Parameters (all fairly obvious, but all must be integers):
  644.     Port:     Com port (1 or 2) to initialize or set
  645.     BPS:      Baud rate to set COmx to, valid bauds are 19200 to 300
  646.     Parity:   0=NONE, 1=EVEN
  647.     Word:     7 or 8 indicating dtaabits
  648.     Stop:     1 or 2 indicating Stop Bits
  649.     Errc:     is set to -1 is any parameter is not recognized.
  650.  
  651.     Example:
  652.     nuBPS = 19200
  653.     errc = ComPortInit(1, nuBPS, 0, 8, 1)
  654.     IF errc = 0 THEN
  655.        BPS = nuBPS                          ' set global variable
  656.        PRINT "Baud rate now set to ";BPS
  657.     END IF
  658.  
  659.  
  660.  
  661.     Name: CommPortSetup           Type: SUB                  Source: BAS
  662.     Syntax: CommPortSetUp (CPort%, Parity%, WdLen%, StopBit%, Errc%, BufSiz%)
  663.  
  664.     The most important function of this is to act as a control center
  665.     for initializing the communications paramters, and as such, prevents
  666.     hard coding practically anything.  Secondly, it sets several global
  667.     parameters (ie COMMON SHARED) required by other modules, which thereby
  668.     reduces the number of parameters required to be passed.
  669.  
  670.     Parameters:
  671.     CPort:     1 or 2 indicating either COM1 or COM2
  672.     Parity:    0=NONE, 1=ODD, 2=EVEN
  673.     WdLen:     7 or 8 indicating number of data bits
  674.     StopBit:   1 or 2 indicating the number of stop bits.  AsyLIB does
  675.                not support the 1.5 stop bits mode
  676.     Errc:      Error code is set to 1 on any error(s)
  677.     BufSiz:    Size of the communication buffer to use.
  678.  
  679.  
  680.  
  681.  
  682.  
  683.     Name: CRXlate                 Type: SUB                  Source: ASM
  684.     Syntax: CALL CRXlate(strng$)
  685.  
  686.     A support routine to quickly swap out an embedded character to a
  687.     Carriage return.  This is called from the routine that loads a macro
  688.     file to exchange '{' to carriage returns, and is called from the
  689.     ScrCompiler sub program to translate CRs in the string arguments to
  690.     the PRINT and TRANSMIT Script file commands. See also SetCRChar.
  691.  
  692.     Example:
  693.     a$ = "FIRSTNAME{LASTNAME{PASSWORD{"
  694.     CALL CRXLate(a$)
  695.     ' The {'s in the string will be converted to carriage returns (ASCII
  696.     13).
  697.  
  698.  
  699.  
  700.     Name: DTRHi                   Type: SUB                  Source: ASM
  701.     Syntax: CALL DTRHi(Cport)
  702.  
  703.     This simply tells the modem to hold DTR high until told otherwise (or
  704.     external modem is turned off, or system rebooted with internal modem).
  705.     This is especially useful with some minor versions of QB 4.0 to instruct
  706.     the modem to hold onto DCD while executing a shell operation.  This need
  707.     not be used with QB 4.00(b) for simple shell operations, but you might
  708.     want to include it in cases where the program shelled TO attempts to
  709.     alter the port.  See DTRLo.
  710.  
  711.     Example:
  712.     ComP = 1                           ' using COM1
  713.     CALL DTRHi(ComP)                   ' Set DTR hi on COM1
  714.  
  715.  
  716.  
  717.     Name: DTRLo                   Type: SUB                  Source: ASM
  718.     Syntax: CALL DTRLo(Cport)
  719.  
  720.     Instructs the modem to drop DTR.  This is useful in resetting modems
  721.     that require 'hard resets' or to reverse a previous call to DTRHi.  This
  722.     is also a little ineffective in QB4.00(b) where the Com Port handling is
  723.     immensely improved over the other versions, but where QB "hides" the
  724.     comport address, and seems to 'remember' certain serial port parameters
  725.     and restores them after a CALL.  DTRHi and DTRLo are extremely useful
  726.     with QB 4.00(a) and QB 4.00 though.    See DTRHi
  727.  
  728.     Example:
  729.     ComP = 2                           ' using COM2
  730.     CALL DTRLo(ComP)                   ' Set DTR Lo on COM2
  731.  
  732.  
  733.  
  734.     Name: FirstF                  Type: Function             Source: ASM
  735.     Syntax: errc = FirstF(mask$, ret$)
  736.  
  737.     This is an ASM support module for low level file access.  All the file
  738.     transfer protocols use low level routines (not BASIC's) for reading and
  739.     writing files to disk.  Further, Ymodem Batch protocol needs a way to
  740.     find a series of files matching a mask and FirstF and NextF provide this
  741.     access.  All the low level file access routines bear the same name as
  742.     those in GLIB so that either may be used.
  743.  
  744.     Errc returns 18 if there are no matching files (and as such can be used
  745.     as a File Exist type function), or returns the found filename in ret$.
  746.     Ret$ MUST be initalized to 12 spaces or else errc is set to -1.
  747.  
  748.     Example:
  749.     fret$ = SPACE$(12)
  750.     errc = FirstF("*.PAK", fret$)
  751.  
  752.  
  753.  
  754.     Name: NEXTF                   Type: Function             Source: ASM
  755.     Syntax: errc = NextF(fret$)
  756.  
  757.     Once a FirstF function is executed, NextF can be called to get
  758.     subsequent matching filenames.  When no more files are found, errc is
  759.     set to 18, if there is not enough room in fret$ for the filename,
  760.     errc is set to -1.
  761.  
  762.     Example:
  763.     fret$ = SPACE$(14)                 ' must be at least 12
  764.     errc = NextF(fret$)
  765.  
  766.  
  767.  
  768.     Name: File2Buffr              Type: FUNCTION             Source: ASM
  769.     Syntax: errc = File2Buffr(FHandle%, buffer$, BufSiz%)
  770.  
  771.     All the file transfer protocols in AsyLIB use buffered file I/O via
  772.     low level routines to minimize disk access.   In the case of a floppy
  773.     disk system, this will improve performance tremendously, and when
  774.     compared to a comparable routine that uses BASIC's I/O functions,
  775.     performance is similarily improved.  File2Buffr reads BufSiz% bytes
  776.     from the disk file represented by Fhandle% into buffer$.  Maximum buffer
  777.     size is 32k, BufSiz should be set the number of bytes to read in, and
  778.     returns as the number of bytes read.  Errc is set to indicate a DOS
  779.     error such as invalid handle etc.
  780.  
  781.     As with the CRC routines, you might never need these unless you decide
  782.     to try and concoct your own protocol or tinker with one of those in
  783.     AsyLIB.
  784.  
  785.     Example:
  786.     buf$ = SPACE$(1024)                     ' set up a 1k Buffer
  787.     f = FREEFILE                            ' get a file num from BASIC
  788.     OPEN "myfile" FOR INPUT AS #f
  789.     Fhandle = FILEATTR(f, 2)                ' get DOS File Handle
  790.     BSiz = LEN(buf$)                        ' bytes to read (BSiz = 1024 is
  791.                                             ' will work too.
  792.     errc = File2Buffr(Fhandle%, bufr$, bsiz)      ' read 1k into bufr$
  793.  
  794.  
  795.  
  796.     Name: Buffr2File              Type: Function             Source: ASM
  797.     Syntax: errc = Buffr2File(Fhandle%, bufr$, bytes%)
  798.  
  799.     As you can probably guess, this performs the reverse of File2Buffr by
  800.     writing a buffer to disk.  Where File2Buffer would be used (and is!) in
  801.     SENDING a file, Buffr2File is used in RECEIVE transfers.
  802.  
  803.     Example:
  804.     errc = Buffr2File(Fhandle%, bufr$, BSiz)
  805.     ' dumps bytes recieved in bufr$ to the file associated with FHandle.
  806.  
  807.  
  808.  
  809.     Name: KeyReady                Type: Function             Source: ASM
  810.     Syntax: KeyReady%
  811.  
  812.     This primitive is used internally by some of the subroutines as well as
  813.     in the main terminal code to determine if a keypress is waiting in the
  814.     buffer, WITHOUT actually reading and/or removing it from the buffer.
  815.  
  816.     Example:
  817.     IF KeyReady THEN
  818.        x$ = INKEY$
  819.     END IF
  820.  
  821.  
  822.  
  823.     Name: KBOption                Type: Function             Source: ASM
  824.     Syntax: MOpt = KBOption(ky$)
  825.  
  826.     As you can see from the demo terminal program, the actual managing of
  827.     incoming keyboard and com port characters is quite easy, the bulk of a
  828.     terminal program is going to be invoking all the extended functions such
  829.     as [Alt-X] or [Alt-U] etc to execute the specific functions.  Naturally
  830.     an examination of an input keyboard character could tell us whether it
  831.     is a simple character (A, b, C, u etc) or a shifted character such as
  832.     Ctrl+key or Alt+key.  This is however, an ideal job for ASM.  The code
  833.     is not only MUCH smaller but MUCH faster.
  834.     NOTE!  KBOption does not read a key from the buffer or keyboard, but
  835.     evaluates a key already read!
  836.  
  837.     MOpt returns as an integer indicating combination pressed, only Alt+
  838.     and key pad/ cursor key character strings return a MOpt code, that is,
  839.     Ctrl+ keys are ignored.  Once MOpt is gotten, a SELECT CASE construct
  840.     can be executed to perform the desired function(s).
  841.  
  842.     KBOption Returns:
  843.     0 - Key press not recognized, ie it is not a Alt+ or cursor key.
  844.     1 to 26  Alt + corresponding apha key (1 = A, 2 = B etc).
  845.     27 - Home
  846.     28 - Cursor Up
  847.     29 - PgUp
  848.     31 - Cursor Left
  849.     33 - Cursor Right
  850.     35 - End
  851.     36 - Cursor Down
  852.     37 - Pg Dn
  853.  
  854.     121 to 132 - Alt + the corresponding top row number key:
  855.            121 = [Alt-1], 122 = [Alt-2]...131 = [Alt+-], 132 = [Alt+=]
  856.  
  857.     Example:
  858.     IF KeyReady THEN                   ' is there a key waiting?
  859.         x$ = INKEY$                    ' yes, read it
  860.         MOpt = KBOption(x$)            ' convert to MOpt code
  861.         IF MOpt THEN                   ' is is ALT+something?
  862.             GOSUB MenuItem             ' yeah, do what they want
  863.         ELSE
  864.             CALL SendChar(x$)          ' nope, send the KB input
  865.             CALL TAnsiPrint(x$, Ar, AC) '  print it locally
  866.         END IF
  867.     END IF
  868.  
  869.  
  870.  
  871.     Name: MPacing                 Type: SUB                  Source: ASM
  872.     Syntax: MPacing(x)
  873.  
  874.     Pauses processing for x milliseconds.  This is used in the SendString
  875.     routine when used to transfer via ASCII to control the pace of the
  876.     transfer and prevent overrunning your own or the recievers buffer.
  877.  
  878.  
  879.  
  880.     Name: PurgeCommBuffer         Type: SUB                  Source: BAS
  881.     Syntax: CALL PurgeCommBuffer
  882.  
  883.     At times it is desirable to purge the comm buffer such as immediately
  884.     after an aborted file transfer.
  885.  
  886.     Example:
  887.     CALL SendXmodem1k(filname$, Success%)
  888.     IF Success = 0 THEN                       ' aborted
  889.         CALL PurgeCommBuffer                  ' purge buffer
  890.         SLEEP 1                               ' wait a sec
  891.         CALL PurgeCommBuffer                  ' again
  892.     END IF
  893.  
  894.  
  895.  
  896.     Name: RecChar                 Type: SUB                  Source: BAS
  897.     Syntax: CALL RecChar(TimeLimit%, NextChar$, Status%)
  898.  
  899.     This is one of the most used sub programs in AsyLIB: when called, it
  900.     polls both the keyboard and serial port active for a keypress or
  901.     incoming character.  This polling continues for the number of seconds
  902.     indicated by TimeLimit OR a key is pressed OR a com port character is
  903.     received.  STATUS returns -1, 1 or 2 code indicating:
  904.     -1  - Time Expired
  905.      1  - Key press waiting in buffer (but NOT read)
  906.      2  - Char was recieved from serial port
  907.  
  908.     In the case of a keyboard or serial port character - ie time has NOT
  909.     expired, TimeLimit returns with the number of seconds remianing.  For
  910.     this reason, TimeLImit should be passed as a variable not a numeric
  911.     literal.
  912.  
  913.     If a com port character is seen, it is returned in NextChar$.
  914.  
  915.      Example:
  916.      TLimit = 20
  917.      CALL RecChar(TLimit, ch$, Status)      ' wait 20 secs for input
  918.      SELECT CASE Status
  919.          CASE -1                            ' time expired!
  920.              ch$ = "Good Night Sleepy Head"
  921.              CALL SendString(ch$, 0)        ' send to them
  922.              CALL T0AnsiPrint(ch$, Ar, Ac)  ' local echo
  923.              GOSUB Hangup                   ' disconnect
  924.  
  925.          CASE 1                             ' KB key is waiting
  926.              ch$ = INKEY$                   '  get it
  927.              CALL SendString(ch$,0)         ' show them what we typed
  928.              CALL TAnsiPrit(ch$, Ar, Ac)    ' local echo
  929.  
  930.          CASE 2                             ' they typed something
  931.              CALL TAnsiPrint(ch$, Ar, Ac)   ' local echo
  932.     END SELECT
  933.  
  934.  
  935.  
  936.     Name: RecASCII                Type: SUB                  Source: BAS
  937.     Syntax: CALL RecASCII (fil$, BSMode)
  938.  
  939.     Receives incoming data from the active comport and stores it in the
  940.     indicated file.  The BSMode parameter indicates to the routine how to
  941.     handle incoming backspace characters ( CHR$(8) ), if BSMode = 1, the
  942.     literal CHR$(8) is not saved to disk but rather deletes the character
  943.     preceding character, if BSMode = 0 then BackSpaces are stored to the
  944.     file as literals.   If fil$ is not a valid DOS filename, a run time
  945.     error will occur, your main terminal code should see to this.
  946.  
  947.     Pressing Escape from the local keyboard, aborts the transfer.
  948.  
  949.     Example:
  950.     CALL RecASCII("foo.bar", 1)
  951.  
  952.  
  953.  
  954.     Name: RecSHELL                Type: SUB                  Source: BAS
  955.     Syntax: CALL RecShell (Fil$, protoID$, CPort%, Success%)
  956.  
  957.     This routine extends the availability of protocols far beyond those
  958.     directly supported in AsyLIB to virtually any well behaved protocol
  959.     driver such as the popular DSZ, the hot new JMODEM and others like
  960.     WXModem and even PCKermit.  As is, this procedure, which is based
  961.     on the method used by PCBoard(TM), will allow up to 26 such external
  962.     protocols.  The transfer's success is guaged by the external driver's
  963.     return code (aka ERRORLEVEL), so if a given driver does not return an
  964.     ERRORLEVEL in the case of aborted or failed transfers, the success code
  965.     parameter may not be right.  Note also that external drivers that steal
  966.     interrupts or work too closely with the hardware may have adverse
  967.     effects on your terminal code upon return.
  968.  
  969.     Protocols and drivers of interest that we have toyed with to one extent
  970.     or another in this manner are (BOTH from the environment AND .EXE's):
  971.     DSZ - Zmodem
  972.     DSZ - Xmodem 1k Overthruster (TM)
  973.     QMXFER - WXmodem
  974.     PCKermit - KERMIT
  975.     JMODEM - Jmodem version 1.09
  976.  
  977.     Parameters:
  978.     Fil$:     The file to send
  979.     protoID$: A one character identifier specifying the external protocol
  980.                 that is to be used.
  981.     CPort:    0 or 1 specifying the com port to be used by the external
  982.                 driver.
  983.     Success:  0 or 1 indicating any perceived error code returned by the
  984.               driver.
  985.  
  986.     This method works by executing a batch file named ASY_R?.BAT where ? is
  987.     the one character identifier specified in protoID$.  This batch file
  988.     passes the rest of the parameters to the driver in the form of batch
  989.     file arguments:
  990.     %1 = Com Port (1 / 2)
  991.     %2 = Baud Rate
  992.     %3 = Filename
  993.  
  994.  
  995.  
  996.     If any of these arguments are not needed by the driver of your choice,
  997.     simply omit them on the command line. Sample BATCH files are provided.
  998.  
  999.     NOTE: IF you are using QB 4.00, you may need to set DTR hi prior to
  1000.     the call to RecShell or SendShell so as to hold carrier until the
  1001.     driver program starts up.  If so, simply issue a call to DTRHi.  If you
  1002.     you do this, you should almost certainly issue a call to DTRLo when you
  1003.     wish to hangup the modem.  We have had little, if any, need to do this
  1004.     with QB 4.00(b), however.
  1005.     Example:
  1006.     protoID$ = "J"                ' like in JMODEM
  1007.     CALL RecSHELL ("foo.bar", protoID$, success)
  1008.  
  1009.  
  1010.  
  1011.     Name: RecvGen                 Type: SUB                  Source: BAS
  1012.     Syntax: CALL RecvGen(fil$, mode%, success%)
  1013.  
  1014.     Since XModem Checksum, Relaxed Xmodem, Xmodem CRC and Xmodem 1K are so
  1015.     similar, this general purpose recieve module will recieve in any
  1016.     of these methods.  In making this module 'smarter' than the XModem only
  1017.     or Xmodem1K only modules, it is a little larger and a slightly slower.
  1018.     However, we can envision some situations where this type approach may be
  1019.     desirable.  YmodemG and YModem BATCH are not included because economy of
  1020.     code was the objective, and they are considerably less common.
  1021.  
  1022.     The mode parameter indicates to the sub the protocol to recieve with:
  1023.     1 = Xmodem CheckSum
  1024.     2 = Xmodem CRC
  1025.     3 = Relaxed Xmodem
  1026.     4 = Xmodem 1K
  1027.  
  1028.     Note that since all of these are reciever driven, with the exception of
  1029.     Relaxed XMODEM, you can tell it to start in the Xmodem 1K mode and the
  1030.     module will 'step' down to Xmodem CRC or Checksum as needed.  Since the
  1031.     timing is changed on Relaxed Xmodem, this one should be explicitly
  1032.     passed.  By passing Xmodem1K as the mode, you might be able to goose
  1033.     the other side into this bigger block mode even if both sides were
  1034.     expecting to send in Xmodem CRC or Checksum mode.
  1035.  
  1036.  
  1037.  
  1038.     Name: RecXmodem               Type: SUB                  Source: BAS
  1039.     Syntax: CALL RecXmodem(fil$, Success%, CharTime%)
  1040.  
  1041.     This implementation of Xmodem supports 3 major variants of the 128 byte
  1042.     block Xmodem file transfer protocol:
  1043.     Xmodem CheckSum
  1044.     Xmodem CRC
  1045.     Relaxed Xmodem
  1046.  
  1047.     The sub program begins by requesting CRC mode since it is slightly more
  1048.     accurate than CheckSum mode.  If the sender does not support CRC mode,
  1049.     then it switches to Checksum.   This is all pretty standard, but you
  1050.     have additional control by invoking it in Relaxed Mode.
  1051.  
  1052.     Normal character timing conventions dictate a 1 second per character
  1053.     pacing, however, this is sometimes not long enough if you are operating
  1054.     on a packet switching network such as PCPursuit or CompuServe.  In this
  1055.     case, simply passing a longer CharTime will put the protocol into
  1056.     Relaxed Xmodem mode.  Further, this implementation of Xmodem, when in
  1057.     relaxed mode, will attempt to add yet another second to the pacing when
  1058.     timeouts are encountered on reading a character.  Your terminal package
  1059.     could even list Relaxed Xmodem as a separate supported protocol.
  1060.  
  1061.     CRC and CheckSum modes should be passed a CharTime value of 1, and in
  1062.     most cases, Relaxed Xmodem will work with a value of 2 or 3.  Note that
  1063.     you CAN attempt to pass a timing of 0, however, contrary to terminal
  1064.     level code, Xmodem throughput is NOT enhanced by this, in fact it can
  1065.     error out rather quickly.
  1066.  
  1067.     Example:
  1068.     IF relaxed THEN
  1069.         Timing = 3
  1070.     ELSE
  1071.         Timing = 1
  1072.     END IF
  1073.     CALL RecXmodem(Fil$, Timing)
  1074.  
  1075.  
  1076.  
  1077.     Name: RecXmodem1K             Type: SUB                  Source: BAS
  1078.     Syntax: CALL RecXmodem1k(fil$, Success%)
  1079.  
  1080.     Xmodem1k is often (and mistakenly) referred to as Ymodem.  True Ymodem
  1081.     allows for multiple file transfers as implemented in YmodemB, Xmodem1k
  1082.     however, is simply an expanded XModem protocol transferring 1k data
  1083.     blocks rather than 128 byte blocks.
  1084.     Example:
  1085.     CALL RecXmodem1k(fil$, Success)
  1086.     IF Success THEN
  1087.         PRINT "File received!"
  1088.     END IF
  1089.  
  1090.  
  1091.  
  1092.     Name: RecYmodemB              Type: SUB                  Source: BAS
  1093.     Syntax: CALL RecYmodemB(Success)
  1094.  
  1095.     Since the Ymodem BATCH protocol handles the passing of file names
  1096.     betwixt the sender and receiver itself, you need not pass a file name to
  1097.     receive.  The Success parameter indicates a 0 for failure on the first
  1098.     file, and otherwise, the number of files received.
  1099.  
  1100.     Note:
  1101.     We tested this against the YMODEM-B implementation in DSZ, since Mr.
  1102.     Forsberg is the author of both.  However, we found that we had to take
  1103.     certain liberties with the 'official' treatise on how to implement
  1104.     YModem BATCH: A 1 second delay needed to be added at start up, a second
  1105.     ACK had to be added when acknowledging End Of Session in order to be
  1106.     sure that sender got it.  I am not at all sure why these and a few other
  1107.     things were required, possibly it was an isolated glitch in the DSZ we
  1108.     used (since this is a receiver driven protocol, the problem almost
  1109.     certainly lies with either the treatise or DSZ).  Note further though,
  1110.     that we got the BEST performance in Ymodem B when setting it up as an
  1111.     external protocol and using the SHELL approach to execute it through
  1112.     DSZ.  This is inherent to QB.
  1113.  
  1114.  
  1115.  
  1116.     Name: RecYmodemG              Type: SUB                  Source: BAS
  1117.     Syntax: CALL RecYmodemG(Fil$, Success)
  1118.  
  1119.     As noted in the ASYNC.DOC, you will recall that Ymodem-G is a
  1120.     'no-protocol' protocol, that is, while data is packet-ized, the protocol
  1121.     does not ACK and NAK each (or ANY!) packet, in fact, if the software
  1122.     percieves an error in the data received (CRC, block or otherwise), the
  1123.     transfer is aborted.   Error detection and correction is left up to the
  1124.     modem.  These ARQ (Automatic Repeat Request) modems (such as those
  1125.     supporting MNP level ROM based error correcting code) are expected to
  1126.     detect such errors, request a resend and THEN pass it onto the
  1127.     software.  When this fails, the protocol must abort the transfer.
  1128.  
  1129.     YmodemG is one of the faster protocols, in our testing this sub program
  1130.     never got less than 238 cps at 2400 bps.
  1131.     Example:
  1132.     CALL RecYmodemG("FooBar.ARC", SuccessCode)
  1133.     IF SuccessCode THEN
  1134.         PRINT "File Transfer successful!"
  1135.     END IF
  1136.  
  1137.  
  1138.  
  1139.     Name: ScrCompiler             Type: Function             Source: BAS
  1140.     Syntax: errc = ScrCompiler(Fil$, a$)
  1141.  
  1142.     Compiles a script file into a memory image of that file.  The basic
  1143.     supplied Script File module supports over 40 functions.  The Script
  1144.     handler modules can be easily modified or added to according to your
  1145.     needs.  Complete details are in ASYSCRP.DOC available to those who
  1146.     get a source code license.  Errc is set to non zero on error.
  1147.  
  1148.  
  1149.  
  1150.  
  1151.     Name: ScrReader               Type: SUB                  Source: BAS
  1152.     Syntax: errc = ScrReader(Scr$)
  1153.  
  1154.     Interprets and excutes a compiled script file.  This may be used either
  1155.     as a called sub program or as a GOSUB type sub routine depending on the
  1156.     construction of your program.  This returns -1 on end of script.
  1157.  
  1158.  
  1159.  
  1160.     Name: ScrFRead                Type: SUB                  Source: BAS
  1161.     Syntax: CALL ScrFRead(Scr$, Fil$)
  1162.  
  1163.     Reads a compiled script file from a disk file.  Script Files can either
  1164.     be compiled at run time or pre compiled and stored to disk.  Compiled
  1165.     scripts cannot be edited, but load much more quickly.  This is not
  1166.     supplied in the BBS collection of files but is supplied to all those who
  1167.     register.
  1168.     See also: ScrFWrite.
  1169.  
  1170.  
  1171.  
  1172.     Name: ScrFWrite               Type: SUB                  Source: BAS
  1173.     Syntax: CALL Scr2Write(Scr$, Fil$)
  1174.  
  1175.     Once a Script File is compiled, you can avoid having to recompile it
  1176.     each time by storing it to disk in binary form with ScrFWrite and
  1177.     retrieve it with ScrFRead.  In so doing, you can reduce code size by
  1178.     not having to link in the Script File compiler module.  Should your
  1179.     terminal program require that the script files be precompiled (ie
  1180.     compiled and the read from a file at run time), you could write an
  1181.     ancillary program to compose, compile and check the script file's
  1182.     syntax, but skip the compile step at execution time by reading the
  1183.     compiled string from disk at runtime.  This is not supplied in the BBS
  1184.     collection of files but is supplied to all those who register.
  1185.     See also: ScrFRead.
  1186.  
  1187.  
  1188.  
  1189.     Name: SendChar                Type: SUB                  Source: BAS
  1190.     Syntax: CALL SendChar(char$)
  1191.  
  1192.     Sends the specified character string to the active comport.  This can be
  1193.     used as an alternative to SendString, if your application does not
  1194.     require the pacing feature.
  1195.     Example:
  1196.     CALL SendChar("Y")
  1197.  
  1198.  
  1199.  
  1200.     Name: SendASCII               Type: SUB                  Source: BAS
  1201.     Syntax: CALL SendASCII (fil$, pacing%)
  1202.  
  1203.     Sends the specified file to the receiver via the active comport.  The
  1204.     indicated file name string must be a valid filename  and represent a
  1205.     file that already exists.  If it does not exist a run time error will
  1206.     occur, your main terminal code should see to this.  The pacing parmeter
  1207.     allows you to pace the transfer by delaying a given number of
  1208.     milliseconds after each line is sent.  The pacing value should be in
  1209.     multiples of 100 ms.  Pressing Escape from the local keyboard, aborts
  1210.     the transfer.  Also, SendASCII expands TABS to spaces.
  1211.     Example:
  1212.     CALL SendASCII("foo.bar")
  1213.  
  1214.  
  1215.  
  1216.     Name: SendGen                 Type: SUB                  Source: BAS
  1217.     Syntax: CALL SendGen(fil$, mode%, success%)
  1218.  
  1219.     Since XModem Checksum, Relaxed Xmodem, Xmodem CRC and Xmodem 1K are so
  1220.     are so similar, this general purpose send module will transmit in any
  1221.     of these methods.  In making this module 'smarter' than the XModem only
  1222.     or Xmodem1K only modules, it is a little larger and a slightly slower.
  1223.     However, we can envision some situations where this type approach may be
  1224.     desirable.  YmodemG and YModem BATCH are not included because economy of
  1225.     code was the objective, and they are considerably less common.
  1226.  
  1227.     The mode parameter indicates to the sub the protocol to recieve with:
  1228.     1 = Xmodem CheckSum
  1229.     2 = Xmodem CRC
  1230.     3 = Relaxed Xmodem
  1231.     4 = Xmodem 1K
  1232.  
  1233.  
  1234.  
  1235.  
  1236.     Name: SendSHELL               Type: SUB                  Source: BAS
  1237.     Syntax: CALL SendShell (Fil$, protoID$, CPort%, Success%)
  1238.  
  1239.     This routine extends the availability of protocols far beyond those
  1240.     directly supported in AsyLIB to virtually any well behaved protocol
  1241.     driver such as the popular Zmodem in DSZ, the hot new JMODEM as well as
  1242.     others like WXModem and even PCKermit.  As is, this procedure, which is
  1243.     based on the method used by PCBoard, will allow up to 26 such external
  1244.     protocols.  See RecSHELL for other warnings.
  1245.  
  1246.     This method works by executing a batch file named ASY_S?.BAT where ? is
  1247.     the one character identifier specified in protoID$.  This batch file
  1248.     passes the rest of the parameters to the driver in the form of batch
  1249.     file arguments:
  1250.     %1 = Com Port (1 / 2)
  1251.     %2 = Baud Rate
  1252.     %3 = Filename
  1253.  
  1254.     If any of these arguments are not needed by the driver of your choice,
  1255.     simply omit them on the command line. Sample BATCH files are provided.
  1256.  
  1257.  
  1258.  
  1259.  
  1260.     NOTE: IF you are using QB 4.00 or QB 4.00(a), you may need to set DTR hi
  1261.     prior to the call to RecShell or SendShell so as to hold carrier until
  1262.     the driver program starts up, if so simply issue a call to DTRHi.  IF
  1263.     you do this, you should almost certainly issue a call to DTRLo when you
  1264.     wish to hangup the modem.  We have had little, if any, need to do this
  1265.     with QB 4.00(b), however.
  1266.     Example:
  1267.     protoID$ = "J"                ' like in JMODEM
  1268.     CALL SendSHELL ("foo.bar", protoID$, 1, success)
  1269.  
  1270.     See also RecSHELL
  1271.  
  1272.  
  1273.  
  1274.     Name: SendStr                 Type: SUB                  Source: BAS
  1275.     Syntax: CALL SendStr(send$)
  1276.  
  1277.     Sends the specified string to the active com port WITHOUT a trailing
  1278.     CR/LF pair and without the pacing time parameter of SendString.  This
  1279.     allows you to send a prompt then wait, possibly for input, and then
  1280.     erase the string on the remote terminal by sending the appropriate
  1281.     number of backspace characters ( CHR$(8) ).
  1282.     Example:
  1283.     prompt$ = "More ?"
  1284.     CALL SendStr(prompt$)              ' send the prompt
  1285.     CALL RecChar(45, ch$, Status)      ' wait 45 secs for reply
  1286.     SELECT CASE Status
  1287.         CASE 2                         ' COM input
  1288.             ' regardless of Y or N answer, erase the prompt by
  1289.             ' sending enough BS characters
  1290.             CALL SendStr(STRING$(LEN(prompt$), CHR$(8))
  1291.             ..
  1292.             ..
  1293.  
  1294.  
  1295.  
  1296.     Name: SendString              Type: SUB                  Source: BAS
  1297.     Syntax: CALL SendString(send$, x)
  1298.  
  1299.     Sends the specified string to the active com port and then waits
  1300.     the number of milliseconds.  This allows the SendString routine to send
  1301.     both strings and lines from ASCII files (as one might do in an ASCII
  1302.     file transfer).  You most likely will never need to add a pacing value,
  1303.     in which case, set 'x' to 0, but it is there if you need it.
  1304.     Example:
  1305.     x$ = INPUT$(10)                    ' read 10 chars from keyboard
  1306.     CALL SendString(x$, 0)
  1307.  
  1308.  
  1309.  
  1310.     Name: SendXmodem              Type: SUB                  Source: BAS
  1311.     Syntax: CALL SendXmodem(fil$, Success%, CharTime%)
  1312.  
  1313.     This implementation of Xmodem supports 3 major variants of the 128 byte
  1314.     block Xmodem file transfer protocol:
  1315.     Xmodem CheckSum
  1316.     Xmodem CRC
  1317.     Relaxed Xmodem
  1318.  
  1319.     The sub program automatically recognizes Xmodem Checksum and CRC
  1320.     transfer methods, additionally, you can start it in relaxed mode so as
  1321.     to better cope with time sharing systems like PCPursuit and Compuserve.
  1322.     The Timing value CAN be zero, but unlike terminal level, this does not
  1323.     improve throughput - in fact it will likely error out.
  1324.  
  1325.     See SendXmodem for more information.
  1326.     Example:
  1327.     IF relaxed THEN
  1328.         Timing = 3
  1329.     ELSE
  1330.         Timing = 1
  1331.     END IF
  1332.     CALL SendXmodem(Fil$, Timing)
  1333.  
  1334.  
  1335.  
  1336.     Name: SendXmodem1k            Type: SUB                  Source: BAS
  1337.     Syntax: CALL SendXmodem1k(fil$, Success%)
  1338.  
  1339.     Xmodem1k is often (and mistakenly) referred to as Ymodem.  True Ymodem
  1340.     allows for multiple file transfers as implemented in YmodemB, Xmodem1k
  1341.     however, is simply an expanded XModem protocol transferring 1k data
  1342.     blocks rather than 128 byte blocks.
  1343.     Example:
  1344.     CALL RecXmodem1k(fil$, Success)
  1345.     IF Success THEN
  1346.         PRINT "File received!"
  1347.     END IF
  1348.  
  1349.  
  1350.  
  1351.     Name: SendYmodemB             Type: SUB                  Source: BAS
  1352.     Syntax: CALL SendYmodemB(Success)
  1353.  
  1354.     Since the Ymodem BATCH protocol handles the passing of file names
  1355.     betwixt the sender and receiver itself, you need not pass a file name to
  1356.     receive.  The Success parameter indicates a 0 for failure on the first
  1357.     file, and otherwise, the number of files received.
  1358.  
  1359.     Note: See RecYModemB for additional notes on YmodemB
  1360.  
  1361.  
  1362.  
  1363.     Name: SendYmodemG             Type: SUB                  Source: BAS
  1364.     Syntax: CALL SendYmodemG(Fil$, Success)
  1365.  
  1366.     Ymodem-G is a 'no-protocol' protocol, that is, while data is
  1367.     packet-ized, the protocol does not ACK and NAK each packet, in fact, if
  1368.     the software percieves an error in the data received (CRC, block or
  1369.     otherwise), the transfer is aborted.  Error detection and correction is
  1370.     left up to the modem.  These ARQ (Automatic Repeat Request) modems (such
  1371.     as those supporting MNP level ROM based error correcting code) are
  1372.     expected to detect such errors, request a resend and THEN pass it onto
  1373.     the software.  When this fails, the protocol aborts the transfer.
  1374.  
  1375.     Example:
  1376.     CALL SendYmodemG("FooBar.ARC", SuccessCode)
  1377.     IF SuccessCode THEN
  1378.         PRINT "File Transfer successful!"
  1379.     END IF
  1380.  
  1381.  
  1382.  
  1383.     Name: SetBeep                 Type: SUB                  Source: ASM
  1384.     Syntax: CALL SetBeep(Freq, Duration)
  1385.  
  1386.     This sets the frequency and duration that TAnsiPrint will use to sound
  1387.     the speaker when it encounters a beep character ( CHR$(7) ).  Duration
  1388.     is set in milliseconds.  For reference, the normal, obnoxious BEEP is a
  1389.     frequency of 800 and a duration of 250 milliseconds.  TAnsiPrint uses
  1390.     a default tone of 500, 50, which you can change with a call to this
  1391.     routine.  Once set, the frequency and duration remain in effect (for
  1392.     TAnsiPrint - BEEP remains the same), until a subsequent call to SetBeep
  1393.     is executed.
  1394.  
  1395.     Example:
  1396.     'Reset TAnsiPrint's default beep to frequency of 1200 and .25 secs
  1397.     CALL SetBeep(1200, 250)
  1398.  
  1399.  
  1400.  
  1401.     Name: SetBline                Type: SUB                  Source: ASM
  1402.     Syntax: CALL SetBline(Brow)
  1403.  
  1404.     Sets the bottom line for TAnsiPrint in scrolling and CLS operations.
  1405.     Normally, the PC CRT scrolls up one line when a character is printed
  1406.     at (25, 79).  SetBline allows you to tell TAnsiPrint to do this
  1407.     scrolling at (22, 79), (24, 79) or even (5, 79).  In so doing, it
  1408.     leaves the remaining lines alone so that you need not refresh a status
  1409.     line you may be maintaining.
  1410.  
  1411.     The argument for SetBLine is an integer indicating the bottom line of
  1412.     the terminal or I/O portion of the screen.
  1413.     Example:
  1414.     Blin = 23                ' reserve 24 and 25 for status line
  1415.     CALL SetBline(Blin)
  1416.  
  1417.  
  1418.  
  1419.     Name: SetCRChar               Type: SUB                  Source: ASM
  1420.     Syntax: CALL SetCRChar(c$)
  1421.  
  1422.     In reading and storing macro strings into memory, the Carriage Return
  1423.     is represented by the default character "{".  The routine CRXlate
  1424.     exchanges all occurrences of a given character (the default is the left
  1425.     curly brace - ASCII 123)  in a string to a carriage return (ASCII 13).
  1426.     SetCRChar is used to change the default carriage return representation
  1427.     to whatever character you like.  The symbolic character should
  1428.     definitely be printable so that it can be properly stored to disk files,
  1429.     but SetCRChar will accept any legal character. See also CRXLate.
  1430.     Example:
  1431.     CALL SetCRChar("#")      ' symbolic CR is now #
  1432.  
  1433.  
  1434.  
  1435.     Name: TAnsiCLS                Type: SUB                  Source: ASM
  1436.     Syntax: CALL TAnsiCLS
  1437.  
  1438.     Clears the screen respecting any status line you may have set up using
  1439.     SetBline and works in tandem with TAnsiPrint by setting the current
  1440.     cursor position to (1, 1), however it does not pass back cursor position
  1441.     pointers, so PRINT statements after a TAnsiCLS and before a subsequent
  1442.     TAnsiPrint should execute a LOCATE 1, 1.
  1443.     Example:
  1444.     CASE 3                   ' Alt - C, Clearscreen
  1445.         CALL TAnsiCLS
  1446.  
  1447.  
  1448.  
  1449.     Name: TAnsiPrint              Type: SUB                  Source: ASM
  1450.     Syntax: CALL TAnsiPrint(ansi$, AnsRow%, AnsCol%)
  1451.  
  1452.     This is a specially developed print routine that uses DOS calls to
  1453.     display the output.  In so doing, if ANSI.SYS is loaded as a device
  1454.     driver, it is used.  TAnsiPrint is further specialized to allow a
  1455.     status line as is normally used in TCOM and BBS applications.  This
  1456.     bottom line is fully definable by you - you can reserve 1, 2, 3 or more
  1457.     lines for that status line, and TAnsiPrint will scroll the screen at
  1458.     the bottom of your 'window' rather than line 25 and NOT write over the
  1459.     status line.   Additionally, you can set a new tone for the standard
  1460.     (and annoying BEEP)!  See SetBline, SetBeep and SetCRIN.
  1461.  
  1462.     TAnsiPrint prints the indicated string at the current cursor location.
  1463.     This routine also passes back the updated cursor pointers so
  1464.     that PRINT statements can be used with continuity.  However, since
  1465.     TAnsiPrint handles wrap, backspaces and ANSI color codes (if ANSI is
  1466.     loaded), cursor codes and translates CHR$(12) as a CLS command, there is
  1467.     little advantage to using PRINT.  You may notice that little or no plain
  1468.     PRINT statements are used in the MODEM demo program.
  1469.  
  1470.     Example:
  1471.     prompt$ = "What is your first name? "        ' assign string
  1472.     CALL TAnsiPrint(prompt$, AnsR, AnsC)         ' local display
  1473.     CALL SendStrting(prompt$, 0)                 ' remote display
  1474.  
  1475.     In a host type system, as with a BBS, it might even make sense to have a
  1476.     dedicated variable for output destined for local and remote display, say
  1477.     e$ and make the 2 above CALLs code in a GOSUB:
  1478.     e$ = "Enter to continue"
  1479.     GOSUB Echo
  1480.       ..
  1481.       ..
  1482.     Echo:
  1483.         CALL TAnsiPrint(prompt$, AnsR, AnsC)
  1484.         CALL SendStrting(prompt$, 0)
  1485.     RETURN
  1486.  
  1487.  
  1488.  
  1489.     Name: UpdStatLine             Type: SUB                  Source: BAS
  1490.     Syntax: CALL UpdStatLine( fg, bg)
  1491.  
  1492.     Note: this is an inline type sub found in the ASYDEMO.BAS module.
  1493.  
  1494.     For those applications such as a BBS system or even an extensive
  1495.     terminal package, it is sometimes advantageous to keep certain
  1496.     information on a status line.  UpdStatLine demonstrates one way to do
  1497.     this using a single Fixed length string of 80 characters in length
  1498.     passed as a common variable.  The use of this is completely compatible
  1499.     with TAnsiPrint and TAnsiCLS.
  1500.  
  1501.  
  1502.  
  1503.     Name: XferMsg                 Type: SUB                  Source: BAS
  1504.     Syntax: CALL XferMsg(Proto%, Fil$, SRFlag%, BlkCnt%, BSiz%, Retry%, ErrT%)
  1505.  
  1506.     Any reputable terminal package provides an ongoing status report of a
  1507.     file transfer in progress.  The tools in AsyLIB, also provide for this
  1508.     capability.  XferMsg is called from inside each and every transfer
  1509.     protocol procedure (except ASCII) to update the screen report.  In the
  1510.     best case, a screen save type routine should save the portion of the
  1511.     screen used by XferMsg, your general purpose library should provide this
  1512.     support.
  1513.  
  1514.     Additional capabilities could easily be added to this such as calulating
  1515.     the total time to send a file, the time remaining in a transfer (or
  1516.     both) can easily be added.
  1517.  
  1518.     The QLB versions of the protocols automatically call this routine, but
  1519.     when you receive the LIB version, you can easily change this by removing
  1520.     it from the LIB and replacing it with a sub that either does your own
  1521.     bidding or disable it by replacing it with an empty sub such as this:
  1522.  
  1523.     SUB XferMsg(Proto%, Fil$, SRFlag%, BlkCnt%, BSiz%, Retry%, ErrT%) STATIC
  1524.     END SUB
  1525.  
  1526.     Of course if you purchase a source code license. you can edit it to your
  1527.     heart's content.
  1528.  
  1529.     Parameters:
  1530.           Bps: Modem speed for time calcs
  1531.         Proto: Protocol Type Identifier 1=X, 2=CRC, 3=Y, 4=A...
  1532.     Filename$: Name of file in transit
  1533.        SRFlag: Sending (# Blocks in File), or Recieving(0)
  1534.      BlockCnt: Current block number in transaction
  1535.      RetryCnt: Current Block Retry Count
  1536.       ErrType: Coded error type seen
  1537.  
  1538.  
  1539.  
  1540.     Name: XmitTextFile            Type: Function             Source: BAS
  1541.     Syntax: retcode = XmitTextFile(fil$, pcount)
  1542.  
  1543.     This is similar to a SendASCII type transfer except it is tailored to
  1544.     fit the needs as would be required in displaying a text file or
  1545.     bulletin to a remote user.  PCount indicates the number of lines to
  1546.     display before the first 'More?' prompt, this would typically be read
  1547.     from a users profile record or be a global variable.
  1548.  
  1549.     After PCount number of lines have been transmitted, the remote user is
  1550.     displayed the following prompt:
  1551.     More? (Y)es, (N)o, (C)ontinuous (Enter = YES)
  1552.  
  1553.     After this 'More?' prompt is sent, the routine waits 30 seconds for the
  1554.     response, if none is forthcoming either from the active comport or the
  1555.     keyboard, the routine exits with a return of -1.
  1556.  
  1557.     If "N" is received, the routine closes the file being sent/displayed
  1558.     and exits to the calling module.
  1559.  
  1560.     In spite of the prompt's suggestion to hit Enter or 'Y', virtually any
  1561.     other key sends another PCount of lines from the file.  In responding to
  1562.     any other key, a loop can be removed from the code.
  1563.  
  1564.     Should a "C" be returned, the routine sends out another prompt to
  1565.     inform them that [Ctrl-S] suspends transmissions and [Ctrl-X] aborts.
  1566.     XmitTextFile then begins a continous send mode resonding only to a
  1567.     [Ctrl-X] from the comport or local keyboard to abort the process, or a
  1568.     [Ctrl-S] to pause.  Note that due to the way BASIC buffers the comport
  1569.     I/O, up to 5 or so lines may be transmitted before the [Ctrl-S] or
  1570.     [Ctrl-X] is perceived as actted upon.
  1571.  
  1572.     If a [Ctrl-S] is received, the transmission pauses and again waits 30
  1573.     seconds for a response, if more than that passes, while waiting for a
  1574.     response, the routine exits with an error code of -1.
  1575.  
  1576.     Example:
  1577.     errc = XmitTextFile("BLTN8", 23)        ' send a bulletin, in 23 line sets
  1578.     IF errc THEN
  1579.        IF CarrierDetect(ComPort) = 0 THEN
  1580.             GOSUB HangUp
  1581.        END IF
  1582.     END IF
  1583.  
  1584.                     * * * * * * * * * * * * * * * *
  1585.      The LIB is all done and ready to go, but it looks like I should have
  1586.      added a parameter for you to set the time to more than 30 secs for
  1587.      slower readers.  This will be corrected in a future version.
  1588.  
  1589.