Changes in Halcyon 3.05:

      22 Jul 93 - Fixed problem with detecting a read-only file.  In the
                  Assign method, FileMode is set to ReadOnly if the read
                  only file attribute is set in the file.  If a network
                  file, SharedDenyWrite is also set.

      24 Jul 93 - Modified Find to go to the end of file if no match.  This
                  makes it compatible with the dBase Find procedure.

      24 Jul 93 - Modified Find to call object^.FindNear.  Now, the file
                  will be positioned at the record with the next greater
                  key if no match and the search did not go to end of file.
                  The programmer can call Found to see if there was a match,
                  and dEOF to see if the file is positioned at the end of
                  file (true), or at the next greater key (false).

      25 Jul 93 - Improved the speed of setting indexes in the Select
                  method.  Replaced routine to do a sequential search for the
                  index key with record number matching the current number.
                  New routine Finds matching record key and then confirms the
                  record number matches.  Provides significant reduction in
                  time required.

      25 Jul 93 - Improved the speed of switching indexes in the IndexOrder
                  method.  Replaced routine to do a sequential search for the
                  index key with record number matching the current number.
                  New routine Finds matching record key and then confirms the
                  record number matches.  Provides significant reduction in
                  time required.

      28 Jul 93 - Added the following call to allow user formula expression
                  processing for indexes:

                  Procedure  SetFormulaProcess(UserRoutine1 : FormulaProc;
                                               UserRoutine2: XtractFunc);

                  Assigns two user-supplied routines to process formulas to
                  be built and used by index files.  This call replaces the
                  default DefFormulaBuild and DefFormulaXtract with the
                  programmer's own routine via a call to SetFormulaProcess.

      28 Jul 93 - Added program GS_BUILD.PAS to automatically build the
                  TPUs for all units.

      02 Aug 93 - Fixed problem in the Use command that did not clear the
                  Object pointer when the used file changed.  This was no
                  problem except when the area was cleared (Use('')), and
                  then Use'd again.  Since the object pointer in the table
                  was invalid, an error occured.

      07 Aug 93 - Fixed Skip method to properly load the first record or the
                  ending record in the file if the skip count resulted in a
                  skip distance that caused access beyond file limits.

      07 Aug 93 - Added statement to clear IOResult before attempting to
                  make an IO call.  If IOResult is non-zero when a
                  command is issued, it is possible the routine will
                  get that result code instead of the valid result.


                             ADDED EXAMPLE PROGRAMS


program TestBrow;
                              DBase Browser

       TESTBROW.PAS Copyright (c)  Richard F. Griffin

       20 July 1993

       102 Molded Stone Pl
       Warner Robins, GA  31088

       -------------------------------------------------------------
       This program demonstrates how dBase files may be browsed using
       Griffin Solutions units.

       The program opens a dBase file and proceeds to browse the file.
       Pressing F1 displays a list of commands available.  The browse
       methods are in unit GSXT.BRO.

       Description:

          Procedure StartBrowse(lincnt, linwidth: integer);

             Initializes browse activity.  The lincnt argument is the
             number of lines that can be displayed on screen.  The
             linwidth argument is the line size to be displayed on
             screen.  Must be called before any other command.

          Procedure ResetBrowse;

             Resets the browse function by releasing memory.  Must be
             called to close the browse activity.

          Function GetBrowseHeader(bline: word): string;

             Returns the portion of the header line starting at bline
             for the maximum length that can be displayed on screen.

          Function GetBrowseLine(linnum, bline: word): string;

             Returns the portion of the data record to be displayed
             starting at bline position within the string array of the
             record.  The function will return a string of the length
             that can be displayed on screen.  Linnum is the row to be
             selected, based on the record's relative position in the
             display window.  UpdateBrowse must be called initially to
             select the range of records to be displayed.

          Function GetBrowseRecord(linnum: integer): longint;

             Returns the physical record number for the record at linnum.
             Linnum is the row to be selected, based on the record's
             relative position in the display window.  UpdateBrowse must
             be called initially to select the range of records to be
             displayed.

          Function GetBrowseBar(bline: word): string;

             Returns a separator line to be placed between the header and
             data records.  This line is created by scanning the portion
             of the header line starting at bline for the maximum length
             that can be displayed on screen.  If the position in the
             header contains the value in broSeparator, then the value
             from broIntersect is inserted in the line, otherwise the
             value in broHorizontal is inserted.

          Procedure MoveBrowseLeft(var posn: word);

             Used to compute the scroll position for a scroll left.
             Decrements posn by 1.  It then tests to see if posn is less
             than 1 and sets it to 1 if it is less.  This value is used
             by other calls to identify the starting scroll position for
             GetBrowseLine and GetBrowseHeader.

          Procedure MoveBrowseRight(var posn: word);

             Used to compute the scroll position for a scroll right.
             Increments posn by 1.  It then tests to see if posn is
             greater than (length of the record - max line that can
             be displayed), and adjusts to that length if greater.
             This prevents scrolling beyond the length of the record.
             The value returned in posn is used by other calls to
             identify the starting scroll position for GetBrowseLine
             and GetBrowseHeader.

          Procedure RenewBrowseLine(linnum: word);

             Rereads the physical record for the record displayed at
             linnum.  Linnum is the row to be selected, based on the
             record's relative position in the display window.
             UpdateBrowse must be called initially to select the range
             of records to be displayed.  This routine needs to be called
             if a record is updated during the browse activity.

          Procedure TabBrowseLeft(var posn: word);

             Used to compute the scroll position for a tab left.
             Decrements posn to the start of the previous field, unless
             already at field 1.  This value is used by other calls to
             identify the starting scroll position for GetBrowseLine and
             GetBrowseHeader.

          Procedure TabBrowseRight(var posn: word);

             Used to compute the scroll position for a tab right.
             Increments posn to the start of the next field.  It then
             tests to see if posn is greater than (length of the record -
             max line that can be displayed), and adjusts to that length
             if greater. This prevents scrolling beyond the length of
             the record.  The value returned in posn is used by other
             calls to identify the starting scroll position for
             GetBrowseLine and GetBrowseHeader.

          Procedure UpdateBrowse(action: longint);

             Retrieves records from the database file based on the command
             in action.  Valid commands are: broLnDn, broLnUp, broTop,
             broBttm, broPgDn, and broPgUp.  It retrieves as many records
             as is necessary to fill the number of lines specified in the
             StartBrowse command.

-------------------------------------------------------------------------------}

program TestFind;
                          DBase File Index Find

       TESTFIND.PAS Copyright (c)  Richard F. Griffin

       24 July 1993

       102 Molded Stone Pl
       Warner Robins, GA  31088

       -------------------------------------------------------------
       This program demonstrates how dBase files may use the Find call.

-------------------------------------------------------------------------------}


program TestFrm1;
                                Formula Routine

       TESTFRM1.PAS Copyright (c)  Richard F. Griffin

       27 July 1993

       102 Molded Stone Pl
       Warner Robins, GA  31088

       -------------------------------------------------------------

       The Formula routine in HALCYON only handles straight field names.
       However, the power of using objects is how simple it becomes to
       modify an ancestor object.  The following code, taken from demo
       program GSDMO_06.PAS, shows creating a child object with a virtual
       method Formula.  This method will be called anytime a formula is
       needed for an index action from anywhere within the ancestor
       object(s).

       In this example, the PAYMENT field is converted to a string of nine
       characters with two decimal places.  The BIRTHDATE field is then
       converted to a display format (YY/MM/DD) and appended to the string.
       The string is then returned as the formula's result.

       The IndexOn command must contain the correct formula; for example:
       "IndexOn('DEMOFRM1','STR(PAYMENT,9,2)+DTOC(BIRTHDATE)')", so
       it will be stored properly in the index header for use by other
       programs such as dBase, FoxPro, Clipper, etc.


      Description:
                  Added the following call to allow user formula expression
                  processing for indexes:

                  Procedure  SetFormulaProcess(UserRoutine1 : FormulaProc;
                                               UserRoutine2: XtractFunc);

                  Assigns two user-supplied routines to process formulas to
                  be built and used by index files.  This call replaces the
                  default DefFormulaBuild and DefFormulaXtract with the
                  programmer's own routine via a call to SetFormulaProcess.

                  The Formula routine in HALCYON only handles straight field
                  names.  However, the SetFormulaProcess allows a user-
                  supplied routine to be called anytime a formula is needed
                  for an index action from anywhere within the ancestor
                  object(s).

                  Two routines must be provided.  UserRoutine1 is a routine
                  that parses the expression and translates into paramaters
                  are understood by UserRoutine2.  UserRoutine2 is called
                  everytime a index key is to be extracted from a record.

                  In this example, substrings of the first five positions
                  of the LASTNAME and FIRSTNAME fields are combined in a
                  string that is then returned as the formula's result.

                  The IndexOn command must contain the correct formula;
                  for example:

                  IndexOn('DEMOFRM2',
                          'SUBSTR(LASTNAME,1,5)+SUBSTR(FIRSTNAME,1,5)');

                  so it will be stored properly in the index header for use
                  by other programs such as dBase, FoxPro, Clipper, etc.


                 ($F+)
                 Function UFormula(st:string;var fmrec:GSR_FormRec): boolean;
                 var FldCnt : integer;
                 begin
                    if (fmrec.FAlias = 'TESTFRM2') then  (Correct Index?)
                    begin                                (set extract table)
                       UFormula := true;
                       for FldCnt := 0 to 32 do fmrec.FPosn[FldCnt] := 0;
                       fmrec.FType := 'C';  (Character key)
                       fmrec.FDcml := 0;
                       fmrec.FSize := 10; (5 chars from LASTNAME & FIRSTNAME)
                    end
                    else UFormula := true;
                 end;

                 Function UFormXtract(var st:string;fmrec:GSR_FormRec):boolean;
                 begin
                    if (fmrec.FAlias = 'TESTFRM2') then    (Correct index?)
                    begin
                       UFormXtract := true;
                       st := SubStr(FieldGet('LASTNAME'),1,5) +
                       SubStr(FieldGet('FIRSTNAME'),1,5);
                    end
                    else UFormXtract := false;
                 end;
                 ($F-)
                                      .
                                      .
                                      .
                Select(1);
                Use('GSDMO_01');
                SetFormulaProcess(UFormula, UFormXtract);
                                      .
                                      .


                 To return to the default, simply use:

                 SetFormulaProcess(DefFormulaBuild, DefFormulaXtract);

                 Note that the assigned procedure must use far calls ($F+).
                 Also note that SetFormulaProcess should not be called until
                 a file has been assigned to the selected file area through
                 Use.  If no file has been assigned, Error 1008, Object is
                 not initialized in file area, will halt the program.

                 See TESTFRM1.PAS and TESTFRM2.PAS for demonstrations of
                 this function.

-------------------------------------------------------------------------------}

program TestFrm2;
                                Formula Routine

       TESTFRM2.PAS Copyright (c)  Richard F. Griffin

       27 July 1993

       102 Molded Stone Pl
       Warner Robins, GA  31088

       -------------------------------------------------------------

       The Formula routine in HALCYON only handles straight field names.
       However, the power of using objects is how simple it becomes to
       modifiy an ancestor object.  The following code, taken from demo
       program GSDMO_06.PAS, shows creating a child object with a virtual
       method Formula.  This method will be called anytime a formula is
       needed for an index action from anywhere within the ancestor
       object(s).

       In this example, substrings of the first five positions of the
       LASTNAME and FIRSTNAME fields are combined in a string that is
       then returned as the formula's result.

       The IndexOn command must contain the correct formula; for example:
       IndexOn('DEMOFRM2','SUBSTR(LASTNAME,1,5)+SUBSTR(FIRSTNAME,1,5)');
       so it will be stored properly in the index header for use by other
       programs such as dBase, FoxPro, Clipper, etc.

-------------------------------------------------------------------------------}

program TestPick;
                              DBase File Lister

       TESTPICK.PAS Copyright (c)  Richard F. Griffin

       20 July 1993

       102 Molded Stone Pl
       Warner Robins, GA  31088

       -------------------------------------------------------------
       This program demonstrates how dBase records may be selected using
       pick menus in Griffin Solutions units.

       See SHOWOFF.PAS for additional examples.

       ---  WILL NOT RUN UNDER WINDOWS ---

-------------------------------------------------------------------------------}


program TestSch1;
                              DBase Key Field Locator

       TESTSCH1.PAS Copyright (c)  Richard F. Griffin

       14 July 1993

       102 Molded Stone Pl
       Warner Robins, GA  31088

       -------------------------------------------------------------
       This program demonstrates how key strings may be located in dBase
       files.

       If the GSDMO_01.DBF file does not exist, the program will display a
       a message that the file was not found and to run GSDMO_01 to make
       the file.

       Upon execution, the program sets the size of the cache file to a
       maximum of 64512 bytes.  It will then ask for a LASTNAME field key to
       find.  Enter any portion of the string.

       The search routine is in GSXT_SCH.PAS

       Description:

       Procedure is called as follows:

          Result := SearchDBF(s, FNum, fromtop)

       Where:
              s          = The string to search for
              FNum       = The record field to search
              fromtop    = Boolean true to start from the top of the file,
                           false to continue from the current record.
              Result     = Starting position of the found string in the
                           field, or zero if the string is not found.

       The file in the selected file (using GSOBShel) will be searched for
       the record field that matches the string s.  Records will be read
       through whatever filters are set (deleted records ignored, etc.).
       When a match is found the starting location within the field is
       returned and the file is positioned with the matching record as
       the current record.  If no match, zero is returned and the current
       record is positioned to the initial position as when the call was
       made.

       NOTE THAT THIS TEST IS NOT CASE SENSITIVE!!

       See TESTSCH1.PAS and TESTSCH2.PAS for an example of how to use the
       routine.

-------------------------------------------------------------------------------}


program TestSch2;
                              DBase Key Field Locator

       TESTSCH2.PAS Copyright (c)  Richard F. Griffin

       14 July 1993

       102 Molded Stone Pl
       Warner Robins, GA  31088

       -------------------------------------------------------------
       This program demonstrates how status may be checked while running
       key string searches in dBase files.

       This example is an extension of the status reporting example that
       was demonstrated in GSDMO_17.PAS.

       If the GSDMO_17.DBF file does not exist, the program will display a
       a message that the file was not found and to run GSDMO_17 to make
       the file.

       The program opens a dBase file and will ask for a LASTNAME field
       key to search for.  Enter any portion of the string.  During the
       search, the current record being searched is reported.

-------------------------------------------------------------------------------}

