---------------------------------------------------------------------------
---------------------------------------------------------------------------
        NNNNNNNNNNNN        NNNNNNNNNNNN NNNNNNN    NNNNNN NNNNNNN   NNNNNN
       NNNNNNNNNNNNNN    NNNNNNNNNNNNNN NNNNNNNN   NNNNNN NNNNNNNN  NNNNNNN
      NNNNNN    NNNNN  NNNNNNNNNN      NNNNNNNNN  NNNNNN NNNNNNNNN NNNNNNN
     NNNNNN    NNNNN NNNNNNNN         NNNNNNNNNN NNNNNN NNNNNNNNNNNNNNNNN
    NNNNNNNNNNNN    NNNNNN           NNNNNNNNNNNNNNNNN NNNNNNNNNNNNNNNNN
   NNNNNN   NNNNNN NNNNNNN          NNNNNN NNNNNNNNNN NNNNNN NNNNNNNNNN
  NNNNNN   NNNNNN  NNNNNNNN        NNNNNN   NNNNNNNN NNNNNN   NNNNNNNN
 NNNNNNNNNNNNNN     NNNNNNNNNNNNN NNNNNN    NNNNNNN NNNNNN    NNNNNNN
NNNNNNNNNNNNN        NNNNNNNNNNN NNNNNN     NNNNNN NNNNNN     NNNNNN
---------------------------------------------------------------------------
---------------------------------------------------------------------------
Boston Computer News Network                                September, 1994
A Service of the Boston Computer Society, USA                   Vol.3  No.9
Sponsored by the Xbase Language Group                       Clipper Version
---------------------------------------------------------------------------
 1. ** Developer Poll ** What's Your Assessment of New Orleans Technicon?
    -----------------------------------------------------------------------
    ReplyTo:    Les Squires bcnn@WJI.Com  [73020,3435]
    Reminders:  Expect one reminder.

    Visual Objects, Clipper 5.3, Client/Server . . .  What did you think
    about this year's Technicon?  I heard all kinds of opinions, from
    'think thoughts, 30 lines max.  Next month BCNN/Clipper will
    publish 15-20 of the most representative statements.  Be sure to praise
    where praise is due and to criticize where criticism is due.  And, as
    always, please distinguish between for-publication and not-for-
    publication remarks.

    By the way, I learned at Technicon that a single Bulletin Board in
    South America logs 2,000 downloads of the BCNN monthly.  I'd like to
    ask a big favor.  If you do NOT receive the BCNN directly to your
    email mail box, but receive it through a secondary source such as a
    BBS, please find the most beautiful postcard you can of your homeland
    and send it to BCNN/Clipper at P. O. Box 126, Center Harbor, New
    Hampshire 03226-0126 USA.  Perhaps we'll digitize the photographs and
    make them available via FTP! <g>  At least we can make better estimates
    of readership.


 2. New CompuServe Forum for Visual Objects.                 (c) CompuServe
    -----------------------------------------------------------------------
    ReplyTo:  Ginny Caughey, External Sysop [70714,1741]

    Welcome to the new CA-Visual Objects Forum!

    CA is presently shipping the pre-release version of CA-Visual Objects.
    If you're attending one of our Technicon conferences, you can purchase
    the pre-release software at the conference.  If you prefer, you can
    call .
    Comments and suggestions regarding CA-Visual Objects or this forum
    should be directed to "Sysop" or to one of the individual sysops listed
    in the Sysop Roster for this forum.


 3. A Tour of CA-Visual Objects (September Meeting).
    --------------------------------------------------------------------------
    ReplyTo:  Chris Pels <73777.3562@compuserve.com>
    ReplyTo:  Darren J Forcier  djf@WJI.Com
    Meeting:  September 20, 1994, 6:30 p.m.
    Place:    Boston Computer Society, Waltham, MA USA 617-290-5700

    Now is your chance to see the "Pre-Release" version of Computer
    Associate's Visual Objects (VO).  Darren Forcier and Chris Pels will
    share their experiences with this much anticipated object-oriented
    Windows programming tool for our September meeting.  A small
    application will be created and the major features of the product will
    be reviewed (System repository, Application browser, Module browser,
    Entity browser, Class browser, Error browser, GUI classes, DBF classes,
    SQL classes, Report classes, and System classes).

    The presentation will emphasize the strengths and weaknesses of VO,
    compared to other currently available Windows development tools.  In
    addition, we'll discuss the transition from Clipper S87 or 5.2 to VO.
    Come see if VO will be the right tool for your Windows development.

    Not---------------------------------------------
    ReplyTo:  David Debus <100241.1325@compuserve.com>

    I have found a solution for the problem I reported when trying to save
    BCNN Newsletters to the Filing cabinet using Compuserve WINCIM.  It has
    been acknowledged that the WINCIM filing cabinet has problems handling
    message files that approach 30K.

    The solution is very simple.  Create a BCNN-News subdirectory and save
    all newsletters to it by opening the file in the In-Basket and Choosing
    File-SaveAs-Text.  Giving each file a month and serial name actually
    makes it easy to locate individual issues.  Is is also handy for
    cutting and pasting.  The original layout/format of the incoming file
    is preserved.


 5. New Book Due Later this Fall:  Windows Multi-DBMS Programming.
    -----------------------------------------------------------------------
    ReplyTo:  Ken North of Oceanside California USA  <71301,1306>

    I'm finishing a book that may be of interest to you.  The title is
    Windows Multi-DBMS Programming (John Wiley & Sons, 1994). It includes
    programming with C++, Visual Basic, Access, SQLWindows, PowerBuilder,
    ObjectView, Visual AppBuilder and other client tools. It covers ODBC,
    Q+E Database Library, Oracle Glue and a variety of SQL servers and
    engines. I've got lots of source code, SQL scripts , evaluaBoduch  72610.444@Compuserve.Com
    ReplyTo:  Hans Conzett of Oberwil-lieli, Switzerland <100015,146>
    Re:       BCNN August UDF showcase EndOfMonth() function problem.

    >> function EndOfMonth(Date)     //--Returns last day of month.
    >>    return BegOfMonth(Date+45) - day(BegOfMonth(Date+45))

    The original function definition for EndOfMonth() shown above will
    produce incorrect results for dates already at or near the end of the
    month.  For example, EndOfMonth(ctod("01/30/94")) would result in
    ctod("02/28/94").  Here are two ways to code this without running into
    this problem:

    o Making use of both the BegOfMonth() and the Clipper sample function
      AddMonth():

       function EndOfMonth(Date)
          return ( AddMonth(BegOfMonth(Date),1) - 1 )

    o Using the built-in Month() function only:

      function EndOfMonth(Date)
         LOCAL d := Date, nMonth := Month(Date)
         while Month(++d) == nMonth ; end
         return --d


 7. Internet UseNet NewsGroups Now Available via CompuServe.
    -----------------------------------------------------------------------
    ReplyTo:  Steve Silverwood [CA] 76703,3035
    Replyto:  Pierce Reid, CompuServe Incorporated, 614/538-4571.
    Forum:    GO INETFORUM

    COLUMBUS, Ohio, August 15, 1994 -- Access to one of the Internet's most
    popular services, USENET Newsgrouer (CIM) graphical user
    interface, making it easy for members to interact with millions of
    Internet users.

    Newsgroup topics range from applied research and academic subjects such
    as quantum physics, weather forecasting and astronomy to social,
    recreational and entertainment areas such as gardening, music and
    current events.  Participants in USENET Newsgroups contribute knowledge
    and opinions to create discussions that are both up-to-the-minute and
    worldwide in scope.

    The USENET service has been under test at CompuServe since early this
    summer and user feedback has been very positive.  "CompuServe's USENET
    interface compares very favorably with the more powerful UNIX
    newsreaders," said Bryan Pfaffenberger, beta-tester and author of The
    USENET Book: The Definitive Guide to Finding, Using and Surviving
    Electronic Newsgroups on the Internet, to be published by Addison
    Wesley this fall.  "For anyone interested in accessing USENET
    discussion areas on the Internet -- from beginners to experienced net
    surfers -- CompuServe is an excellent choice!"

    Editor's Note.  More enhancements to follow.

8.  UDF Showcase.  Improvements to Color String UDF.
    -----------------------------------------------------------------------
    ReplyTo:  Roy Corneloues, xWare Solutions Limited <100016,63>
    ReplyTo:  Ocizing the sample functions that people submit to BCNN, I'm
    sorry.  It's just that after spending so long at Nantucket/CA I find it
    difficult not to comment when I can see a better way to do something!

    Using the supplied sample functions and the settings from "COLOR.CH"
    the following function is more generic and will return any of the
    colour attributes.  This function uses the sample function
    ListAsArray(), found in SAMPLES.LIB and the ability to reference arrays
    returned by functions.  COLOR.CH starts at 0 and CA-Clipper arrays
    start at 1.  So as long as the parameter passed is between 0 and 4 we
    can add 1 to it to get the correct colour setting from the array.

    #include "Color.Ch"
    #include "Common.Ch"

    FUNCTION ClrExtract( nAttr )
       LOCAL cColor

       DEFAULT cColor TO CLR_STANDARD

       IF nAttr >= CLR_STANDARD .AND. nAttr <= CLR_UNSELECTED
          cColor := ListAsArray(SETCOLOR())[nAttr + 1]
       ENDIF
       RETURN (cColor)


 9. UDF Showcase.  Determine Row and Column of TBrowse Mouse-Click.
    -----------------------------------------------------------------------
    * File......: SETTBRC.PRG
    * Author....: Luca Monteleone, CH-8038 Zurich, Switzerland
    * CIS.......: 100140,1545
    * Internet..: GLM@ezinfo.vmsmail.ethz.ch
    * Date......: 20.02.1994
    * Revision..: 1.0
    * Compind col of a TBrowse according to a mouse-click
    *  $SYNTAX$
    *     SetTbRowCol( oTb )
    *  $ARGUMENTS$
    *     oTb : TBrowse-object
    *  $DESCRIPTION$
    *     The function sets oTb:rowPos and oTb:colPos according to a
    *     mouse-click on a TBrowse. It needs a TBrowse _with_ column-
    *     separators, the type of column-separator is not important.
    *     It also sets oTb:refreshAll() if a full-stabilize will be
    *     necessary. As well it can handle "frozen" columns.
    *  $EXAMPLES$
    *     IF nKey == K_MOUSE
    *        oTb := SetTbRowCol( oTb )
    *     ENDIF
    *  $INCLUDE$
    *
    *  $SEEALSO$
    *     NUMTOKEN(), ATTOKEN() [Clipper Tools]
    *  $END$
    */

    *--------------------------
    FUNCTION SetTbRowCol( oTb )
    *--------------------------
    //Determine in which row and column of a TBrowse a mouse-click happend

    LOCAL nBrTop   := oTb:nTop + IIF( oTb:headSep # NIL, 2, 1 )
    LOCAL nBrLeft  := oTb:nLeft
    LOCAL nBrBot   := oTb:nBottom - IIF( oTb:footSep # NIL, 3, 2 )
    LOCAL nBrRight := oTb:nRight - 3
    //-Adjust the above four coordinates to your specific needs. I'm using
    //-scroll-bars and other fancy stuff, so I had to adjust them _this_
    //-way! Maybe you want to pass them as parameters ? No problem!

    LOCAL nFrozen  := oTb:freeze   //-how many col's were frozen
    LOCAL nMsew := .F.          //-was mouse-click on same row ?
    LOCAL lSameCol := .F.          //-was mouse-click on same col ?
    LOCAL cLine                    //-the TB-row where the mouse-click was
    LOCAL cColSep                  //-oTb:colSep without spaces and others
    LOCAL nColBefore               //-where have we been before
    LOCAL nFrom, nTo               //-"segments" of cLine q= col's
    LOCAL nWidth                   //-width of token from nBrLeft
    LOCAL nXCol                    //-this is it ! the new col
    LOCAL i                        //-a counter, just that

    //-Calculate new row, if necessary
    IF ( nMseRow - nBrTop ) + 1 = oTb:rowPos
        lSameRow := .T.
     ENDIF

     IF ! lSameRow
        oTb:rowPos := ( nMseRow - nBrTop ) + 1
     ENDIF

    //-Calculate new col:
    //-Get the TB-row of the mouse-click (we get it _double_ as long as
    //-it really is, because of SAVESCREEN, remember this further down)
    cLine := SAVESCREEN( nMseRow, nBrLeft, nMseRow, nBrRight )

    //-Get the colSep from the TB-object without spaces or others
    cColSep := SUBSTR( oTb:colSep, 2, 1 )

    //-Save the column before the mouse-click
    nColBefore := oTb:colPos

    //-Start and initialize
    nFrom := nBrLeft
    nTo   := 0

    /*
    //- Do this as many times as there are colSep's (#) in cLine (...)

          i = 1         i =     ^-----------------------------^nBrLeft+nWidth<2>
       nBrLeft
    */

     FOR i  := 1 TO NUMTOKEN( cLine, cColSep )
         IF i > 1
            //-for i=1 nFrom is initialized as nBrLeft
            nFrom := nTo + 1     //-take next one _after_ colSep
         ENDIF
         nWidth := INT( ( ATTOKEN( cLine, cColSep, i+1 ) ) / 2 )
         /*
          if we're looking for the last token and we
          don't find it, set nWidth equal to nBrRight
         */
         nWidth := IIF( nWidth = 0, nBrRight, nWidth )
         nTo := nBrLeft + nWidth
         /*
          And now the deciding part: if the mouse-click was
          _between_ our nFrom and nTo, take that column !
         */
         IF nMseCol >= nFrom .AND. nMseCol <= nTo
            nXCol := oTb:leftVisible - nFrozen + i - 1
            //-Did user hit a frozen col ?
            IF nXCol < oTb:leftVisible .AND. nFrozen > 0
               nXCol = nXCol - oTb:leftVisible + nFrozen + 1
            ENDIF
            oTb:colPos := nXCol
            lSameCol := IIF( i = nColBefore, .T., .F. )
            EXIT
         ENDIF
     NEXT i
     //-Stabilize next time oTb ?
     IF ! ( lSameRow .AND. lSameCol )
        oTb:refreshAll()
     ENDIF
    RETURN( oTb )


10. Tips in Indexing, FOR's, and TBrowse.
    -----------------------------------------------------------------------
    ReplyToition to obtain the
    top of the file each time an index is opened.

      set index to emplbadg, emplname, emplssn
      set filter to badge > '099999'
      dbGoTop()

    is preferable to:

       set filter to badge > '099999'
       set index to emplbadg, emplname, emplssn
       // in this case dbGoTop() is unnecessary...

    o FOR Conditions.  When performing operations on multiple records based
    upon a 'FOR' condition, set the index order to an index beginning with
    the key field of the 'FOR' condition, and perform the operation 'WHILE'
    the key is true.   For example:

       dbselectarea(0)          // grab open work area...
       use PUNCHES
       set index to punchbdg, punchdat
       // set order to 1 ... not necessary
       select EMPLOYEE
       DbSetOrder(1)                            // Employee Badge
       DbGoTop()
       Do While !EMPLOYEE->( EOF() )
          select PUNCHES
          nHours := 0
          DbSeek( EMPLOYEE->Badge, .f. )        // Seek badge, not soft
          SUM PUNCHES->Hours TO nHours ;
              WHILE PUNCHES->Badge = cBadge ;
              FOR   PUNCHES->Badge = cBadge ;
              .and. !Deleted()
          Select EMPLOYEE
          Replace EMPLOYEE->Hours with nHours
          EMPLOYEE->( DbSkip(1) )
       EndDo

    This is much faster on a large database (i.e. "PUNCHES") since it will

    o ReFreshAll().  The current implementation of the
    tBrowse()::refreshAll() operation will update the screen immediately,
    not waiting for the next ::stabilize() operation.

    o Current TBROWSE Row.  To reset the current tBrowse() row to the
    current record after a non-browse movement, create a function which
    will reposition the tbrowse row to the current record.  Note#1:  It is
    advisable to disable screen output to decrease the time and to better
    'feel' via the Clipper DISPBEGIN() and DISPEND() functions.  Note#2:
    It is easier to set the tBrowse()::row to the top row of the browse,
    then redisplay the rest of the rows.

    *-----------------------------------------------------------
    Function TBrRecPos( oBr, nRec, lRefresh, lStabilize, lHide )
    *-----------------------------------------------------------
      Local nTmp1     // oBr      = Browse object
                      // nRec     = current record number
      If lHide        // lRefresh = Do we need to invoke refresh?
         DispBegin()  // lStabilize = Do we want to stabilize?
      EndIf           // lHide    = Do we want to hide operation

      oBr:RowPos := 1                // Force to top row

      If lRefresh
         oBr:RefreshAll()
      EndIf

      Do While RecNo() != nRec
         oBr:Down()
         If lStabilize
            ForceStable( oBr )
----------------------------
    ReplyTo:  Roy Corneloues, xWare Solutions Limied <100016,63>

    Maybe its just me, but I am concerned about the number of third parties
    distributing their add-ons as .DLLs.  Why?  Because .DLLs have to
    distributed with the application.  This in effect is like giving the
    product away to all of your clients.  If you develop an app for a
    company which also has its own development team, as soon as you hand
    over the final build, what's to stop them from re-using the .DLLs.  All
    they need is the documentation, they don't even need to have a
    particular development product, most Windows IDEs support .DLLs

    The use of electronic documentation is also an issue.  Its far easier
    to copy than printed docs, easier to hide from watching eyes and is
    literally a copy of the original docs.

    In the CA-Clipper world everyone raves about .DLLs because they will be
    able to create smaller .EXEs.  Big Deal.  That was only an issue when
    memory was a problem.  This is no longer the case with Windows.

    Don't get me wrong.  I think that .DLLs are cool if used for the right
    reasons.  I myself will probably use a .DLL for common routines, which
    aren't damaging to my company, so that updates become much easier if I
    were to find a bug in one of them.  Code which can be exchanged
    transparently, s protect my own investment.

    Lets take an example of how I feel it should be done.  Let's take
    Microsoft (they should know what they're doing) and one of their
    products Word for Windows.  If .DLLs are so magical why is the .EXE
    nearly 2Mb in size?  Because all the proprietary code is in the .EXE.
    Microsoft don't want to give any clues away to its competition.  The
    only parts provided as .DLLs are replaceable components; drivers or
    third party tools such as spelling checkers.  If Microsoft were to
    place all their code in a .DLL it wouldn't be long before everyone else
    ripped it off for their own use.

    Windows is a perfect example of this, and this is how its meant to be.
    By making all the Windows API calls available from Windows own .DLLs it
    enables the rest of us the ability to develop Windows apps.  Without
    this we would all be cursing Microsoft.

    Are you developing a vertical market product?  How would you feel
    having to provide a multitude of .DLLs with every installation?  What
    happens if they are already using the same .DLLs but different
    versions?

    Are we back to the days of royalties for every application we install?
    Will we have to purchase runtimes so that sites are able to use these
    third party .DLLs?

    Until someone proves me otherwise, I am not convinced that .DLLs are
     personal.


12. Clipper Printing Problem.
    -----------------------------------------------------------------------
    ReplyTo:  Douglas Schwarz <70474.2520@compuserve.com>

    I'm in need of a brilliant idea.  I've inherited a Clipper program (v
    5.0) which prints forms on a bubblejet printer.  (The program is used
    on laptops in the field, and the client is committed to the bubblejet
    for its portability and clarity.)  The program compiles a form and
    outputs it as an ascii file, with embedded format control codes for the
    bubblejet.  Then the program calls the Clipper Tools function
    SpoolAdd(<filename>), which places the file in the DOS PRINT queue.
    The DOS PRINT command (issued in a batch file before the Clipper
    program is launched) then takes care of printing the form in the
    background, while the user contines to work with the program.

    The problem is that the print process itself is too slow -- about 2
    minutes for a single page form, with minimal graphics and occasional
    bolding.  If the same form is created in and printed from Word Perfect,
    it emerges from the printer in about half the time, so we know the
    printer itself is not causing the problem.

    I have tried using the Clipper TYPE TO PRINTER command to print the
    file, but the embedded formatting codes do not seem to work right, and
    in any rameters of the DOS PRINT command --
    increasing /M (the number of ticks the PRINT command uses before
    turning control back to the foreground program) to the max, and /B (the
    buffer size) to greater than the size of the file to be printed.  None
    of this seems to have any effect on the print speed.

    So . . . why can't Clipper and/or DOS commands print the file at a
    speed comparable to Word Perfect?  Any suggestions for how to approach
    this problem?


13. Usability Testing at Kodak (Massachusetts).
    -----------------------------------------------------------------------
    ReplyTo:  Alyse Tartell <alyse_tartell@alewife.kodak.com>

    Kodak is seeking interested computer users to come to our facility to
    "test-drive" our prototype software.  Testing offers computer users the
    opportunity to determine how well the software meets their needs, and
    to provide valuable feedback before beta testing.

    The Kodak Usability Lab is located in Billerica, just a mile and a half
    northwest of the Burlington Mall on the Middlesex Turnpike.  All
    usability tests take place at the usability lab.  Interested users will
    be asked to sign a non-disclosure agreement, complete a brief
    questionnaire, and to be open and honest in their response.  Right now
    we especially need Windows users, but Mac folks are encouraged to call
    tuse state of the
    art hardware and software, which may involve the Kodak Photo CD, image
    editing or OCR.  Usability testing is fun and a fascinating process to
    be involved in. If you, or an associate, is interested in learning more
    about this opportunity, please call me at 508-262-2048, or send E-mail.
    -----------------------------------------------------------------------


14. UDF Showcase.  SeekLast () Seeks Last Record Matching a Given Index Key.
    -----------------------------------------------------------------------
    ReplyTo:  O. Douglas Schwarz of Penacook, NH 03303 < 70474,2520>

    *-----------------------
    FUNCTION SEEKLAST(s_key)
    *-----------------------
    *Seek last record matching a given index key.
    *If found, position on that record; if not, position on EOF.
    * PARAMS:  S_KEY = Search key
    *
    * Example:  use orders
    *           set index to custdate // on custno + dtos(orderdate)
    *           seeklast(thiscust)    // find last order received from
    *                                  // customer # THISCUST
    *
    *Notes:  Assumes the current dbf is indexed such that a normal SEEK
    *        for S_KEY would succeed.  Works only for character keys.
    * RETURNS:  .T. if found, else .F.

    *-----------------------
    FUNCTION SEEKLAST(s_key)
    *-----------------------
    local len_key,if &(indexkey(0)) = s_key
       return (.t.)
    else
       go lastrec() + 1
       return (.f.)
    endif


15. UDF Showcase.  vDate() Auto Fills Current Year on GET.
    -----------------------------------------------------------------------
    ReplyTo:  Andre Roy <ANDRE@EINSTEIN.UNIPISSING.CA> Programmer/Analyst
              Nipissing University, North Bay Ontario, Canada

    vDate() adds the current year to a date input on a read.  This way, if
    the date format is set to mm/dd/yy, the user would only have to type in
    01/27, and this function defaults the year to the current year.

    For example:

    dDate := ctod( "" )

    @10,10 get dDate valid { | oGet | vDate( oGet ) }
    read

    Yes, you have to call it as a code block.  This only works if the date
    format is one in which the year is the last field, so it's not to good
    for ANSI style dates.  Also, any other validation should take place in
    another function.

    #translate sz( <n>, <p> ) =>  padl( ltrim( str( <n> )), <p>, "0" )

    *---------------------
    function vDate( oGet )
    *---------------------
      local dd := oGet:varGet()
      local rr := ""
      local sCent, sDate, m, d, y

      if oGet:changed                      //-never mind if no change
         sCent := __SetCentury( .t. )      //-!!  INTERNAL  !!//-nothing entered
            rr := ""
          else
            rr := sz( d, 2 ) + "." + sz( m, 2 ) + "."
            if sCent
              rr += sz( year( date()), 4 )
            else
              rr += sz( int( year( date()) % 100 ), 2 )
            endif
          endif
          oGet:varPut( ctod( rr ))      //-put the new value into the get
        endif
        set( _SET_DATEFORMAT, sDate )   //-restore this stuff
        __SetCentury( sCent )           //-!!  INTERNAL  !!
      endif                             //-oGet:changed
    return .t.                          //-Always


16. BCNN Statement of Ownership, Copyright, and Responsibility.
    --------------------------------------------------------------------------
    The BCNN Newsletter is sponsored by the Xbase User Group of the Boston
    Computer Society.  BCNN is dedicated to keeping professional database
    developers (both consultants and corporate employees) informed about
    educational events, meetings, job openings, world events, notable
    articles, technical tips, new and 'must have' products, etc.

    As an electronic network, organized by interest rather than geography,
    BCNN is also a hub where developers can address world class issues to
    fellow developers around the world.  Recipients agree to respond via
    Email to periodic polls of their directions, opinions, and nescussions
    on CA-Clipper, Microsoft Access, FoxPro, Gupta SQLWindows, and
    Suiteware.

    The newsletter is distributed monthly by electronic mail via CompuServe,
    Internet, FidoNet, and other electronic gateways.  It is free of charge
    to individual developers.  Modest fees are charged to corporations for
    job placement and third-party announcements.  Opinions expressed are
    solely expressed by the authors or by the Xbase Language Group of the
    Boston Computer Society, even in cases where 'Xbase Language Group'
    is abbreviated to 'BCS'.  All materials are copyrighted by the BCS,
    unless otherwise indicated, and free for any user group to
    redistribute via BBS or newsletter on the condition that a by-line
    referencing the BCNN and the individual author are included.

    Les Squires, Director
    Xbase User Group
    c/o Word Jenny, Incorporated
    P. O. Box 126
    29 Brick Kiln Road, Kilnwood
    Center Harbor, New Hampshire 03226-0126 USA
    603-253-6109                  //-Primary Phone & Messages 24 hours
    603-253-7214                  //-Messages Only 24 hours
    603-253-9864                  //-Fax 24 hours a day
    INTERNET:LSquires@WJI.Com     //-First choice for Email.
    CIS:73020,3435                //-Second choice for Email.

    Boston Computer Society, Inc.
    101 First Avenue, Suite 2
    Waltham, MA 0215s@WJI.Com.
    Address Change:         Email using OLD Address. Indicate New Address.
    Back Issues:            FTP WJI.Com, Login as FTP, use your ID as the
                            password, cd clipper, copy all back issues.

    BCNN Email Services donated by Word Jenny, Inc. LSquires@WJI.Com

    (c) 1994 Boston Computer Society, Inc.

