home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TBTREE.ZIP / LRECLIST.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-07-25  |  26.8 KB  |  713 lines

  1. (* TBTree13             Copyright (c)  1988            Dean H. Farwell II    *)
  2.  
  3. unit LRecList;
  4.  
  5. (****************************************************************************)
  6. (*                                                                          *)
  7. (*                 L O G I C A L   L I S T   R O U T I N E S                *)
  8. (*                                                                          *)
  9. (****************************************************************************)
  10.  
  11. (* These routines handle logical record lists.  These lists are used to hold
  12.    a list of logical record numbers.  Once a list is created logical records
  13.    can be added to the list, the list can be traversed beginning to end or
  14.    back to front and the list can be destroyed. Additionally, entries can be
  15.    deleted from the list. This list, in conjunction with retrieval routines
  16.    in the BTREE unit allows a list to be built that fulfills some user
  17.    specified criteria. The list will exist until the user destroys it.  A
  18.    routine is provided for destroying a list and this should be done
  19.    explicitly for reasons which will become clear later.  A user can have
  20.    many lists in existence at once. Two list could be combined (intersection
  21.    or union) to create a third list if the user desires.  Presently, the user
  22.    would have to do things like combining lists explicitly (user's own
  23.    routines). I plan to add these capabilities in the next release.  These
  24.    lists give power that simply traversing the BTree does not.
  25.  
  26.    The implementation of these lists is not very straightforward.  I
  27.    first developed this unit by creating a giant linked list of
  28.    record numbers which would be kept on the heap.  It was extremely
  29.    straightforward but had the problem of being at the mercy of heap size.
  30.    In a large database these lists could easily overflow the heap.  I reworked
  31.    the problem and came up with this solution.  It stores the logical record
  32.    numbers in an array the size of a page in the page buffer.  If all the
  33.    record numbers will fit in one page then the list is kept in memory.  If
  34.    not then a current file is created and all but the current page is kept
  35.    in the page buffer (or out on disk if a page gets swapped out).  This is
  36.    all transparent to the user except that large lists will experience some
  37.    performance degredation.  The good news is that the logical record lists
  38.    can hold MAXLONGINT (over 2 billion) entries one for ever possible logical
  39.    record number.  (You would really run out of disk space sooner than
  40.    ever coming close to that limit).
  41.  
  42.    Since a file may be created it is important that the user call DestroyLrList
  43.    when completed with the list.  Any files created will be deleted.  Otherwise
  44.    some strange files might show up on the disk.
  45.  
  46.    note - Hopefully, I have given the user a rich set of routines which can
  47.    be used to use the lists.  It is not in the user's best interest to
  48.    access fields in the lists directly.  Use the routines provided.  This
  49.    will guard against problems if the implementation section is ever
  50.    changed.                                                                  *)
  51.  
  52. (* Version Information
  53.  
  54.    Version 1.1 - Added DeleteFromLrList routine to delete entries from
  55.                  logical records list
  56.  
  57.                - Changed the routines so that if a cursor is invalid (does
  58.                  not point to a valid entry, a 0 is returned when a
  59.                  record number is requested.  This is true for the GetNextLr,
  60.                  GetPrevLr and GetCurrLr routines.  This shouldn't affect
  61.                  anything that you were previously doing.
  62.  
  63.    Version 1.2 - Added LRArraySize type
  64.  
  65.                - Added FindLargestLr routine
  66.  
  67.                - Added DesiredPosition routine
  68.  
  69.                - Added DesiredPage routine
  70.  
  71.                - Made a couple of minor changes internally (simplified code
  72.                  using DesiredPosition and DesiredPage)
  73.  
  74.    Version 1.3 - Added FindLrInList routine                                  *)
  75.  
  76. (*\*)
  77. (*////////////////////////// I N T E R F A C E //////////////////////////////*)
  78.  
  79. interface
  80.  
  81. uses
  82.     FileDecs,
  83.     Files,
  84.     Page;
  85.  
  86. const
  87.     LRARRAYSIZE = 128;                (* This needs to be PAGESIZE / RNSIZE *)
  88.                                            (* it is presently 512 / 4 = 128 *)
  89.  
  90. type
  91.     LRArrayRange = 1 .. LRARRAYSIZE;
  92.  
  93.     LogicalRecordsArray = Array [LRArrayRange] of LrNumber;
  94.                                           (* this array must be same size (same
  95.                                              number of bytes) as a page in
  96.                                              the page buffer                 *)
  97.  
  98.     LrList = record            (* type which is used to hold a list of logical
  99.                                                               record numbers *)
  100.              fName    : FnString;            (* holds name of file if needed *)
  101.              currPage : PrNumber;                 (* current page in lrArray *)
  102.              current  : LrNumber;                   (* current place in list *)
  103.              count    : LrNumber;       (* number of logical records in list *)
  104.              case Boolean of
  105.              TRUE  : (lrArray  : LogicalRecordsArray);
  106.              FALSE : (page : SinglePage);
  107.              end;
  108.  
  109.  
  110. (* This routine will create a logical record list.  It will accomplish this by
  111.    initializing the logical record page to all zeros and will set the count to
  112.    zero, the current (cursor) to zero and the current page to one.  To create
  113.    an empty list simply call this with a variable declared as type LrList.   *)
  114.  
  115. procedure CreateLrList(var lrLst : LrList);
  116.  
  117.  
  118. (* This routine will add a logical record number to the end of a logical record
  119.    list.  It will update the cursor position to the newly added record.
  120.    It will increment the count by one.                                       *)
  121.  
  122. procedure AddToLrList(lrNum : LrNumber;
  123.                       var lrLst : LrList);
  124.  
  125. (*\*)
  126. (* This routine will delete an entry from a logical record list.  It is useful
  127.    when deleting records in the case where you do not want to have to recreate
  128.    a list after doing the delete.  It is important to realize two things when
  129.    using this routine.  The first is that it does nothing whatsoever to data
  130.    or index files.  It only affects the logical records list.  Secondly, it
  131.    is faster than recreating a list each time a delete is done, but for
  132.    large lists, it still takes time to perform the delete from the list.
  133.    If a large number of deletes are anticipated, it might be faster to do the
  134.    deletes on the data and index files and then do another retrieval thus
  135.    creating the new list only once.  This routine deletes the current entry
  136.    only ie entry at the cursor.
  137.  
  138.    One note before using this routine - You must be aware of what is
  139.    happening to the cursor.  When this routine deletes the current logical
  140.    record the cursor must be positioned somewhere.  The routine put the
  141.    cursor at the first entry past the deleted entry.  This is now the new
  142.    current entry.  To retrieve it use GetCurrLr not GetNextLr.  In other
  143.    words, when traversing a list from start to finish and deleting the
  144.    entries as you go, to get to the next entry use GetCurrLr.  Use GetPrevLr
  145.    if you are going from the end of the list to the front.                   *)
  146.  
  147. procedure DeleteFromLrList(var lrLst : LrList);
  148.  
  149.  
  150. (* This routine will destroy a logical record list.  It will delete the file
  151.    holding the logical record list if the file was ever created              *)
  152.  
  153. procedure DestroyLrList(var lrLst : LrList);
  154.  
  155.  
  156. (* This routine will return the first logical record in a logical record list
  157.    and set the cursor to the front of the list.  If the list is empty 0 will
  158.    be returned instead.                                                      *)
  159.  
  160. function GetFirstLr(var lrLst : LrList) : LrNumber;
  161.  
  162.  
  163. (* This routine will get the last logical record number in a logical record list
  164.    and set the cursor to the back of the list.  If the list is empty then
  165.    0 will be returned instead.  This routine should be used for traversing
  166.    the list in reverse order.                                                *)
  167.  
  168. function GetLastLr(var lrLst : LrList) : LrNumber;
  169.  
  170.  
  171. (* This routine is used to get the next logical record number in a logical list.
  172.    The cursor will be set to this record list cell as well.  This is used to
  173.    traverse the list in a forward manner.  The routine will return the logical
  174.    record number or 0 if the list is exhausted or the cursor position is
  175.    invalid.                                                                  *)
  176.  
  177. function GetNextLr(var lrLst : LrList) : LrNumber;
  178.  
  179. (*\*)
  180. (* This routine is used to get the previous logical record number in a logical
  181.    list.  The cursor will be updated to point to this entry.  This is used
  182.    to traverse the list in a backward manner.  The routine will return the
  183.    logical record number or 0 if the list is exhausted or the cursor position
  184.    is invalid.                                                               *)
  185.  
  186. function GetPrevLr(var lrLst : LrList) : LrNumber;
  187.  
  188.  
  189. (* This routine is used to get the current logical record in a logical list.
  190.    It will not update the cursor position.  It will return 0 if the cursor
  191.    position is not valid                                                     *)
  192.  
  193. function GetCurrLr(lrLst : LrList) : LrNumber;
  194.  
  195.  
  196. (* This routine returns the number of logical records currently in the logical
  197.    record list                                                               *)
  198.  
  199. function GetCountLr(lrLst : LrList) : LrNumber;
  200.  
  201.  
  202. (* This routine will return the correct physical record number (for the logical
  203.    record list) where the entry lrPos is found                               *)
  204.  
  205. function DesiredPage(lrPos : LrNumber) : PrNumber;
  206.  
  207.  
  208. (* This routine will return the position within a logical records array for
  209.    given lrPos                                                               *)
  210.  
  211. function DesiredPosition(lrPos : LrNumber) : LRArrayRange;
  212.  
  213.  
  214. (* This routine will return the largest logical record number within a logical
  215.    record list.                                                              *)
  216.  
  217. function FindLargestLr(lrLst : LrList) : LrNumber;
  218.  
  219.  
  220. (* This routine will look for a logical record number in a logical record list.
  221.    It will return TRUE if the record number is in the list and FALSE
  222.    otherwise.                                                                *)
  223.  
  224. function FindLrInList(lr : LrNumber;
  225.                       lrLst : LrList) : Boolean;
  226.  
  227. (*\*)
  228. (*///////////////////// I M P L E M E N T A T I O N /////////////////////////*)
  229.  
  230. implementation
  231.  
  232. const
  233.     MINFILENAME = 100;
  234.     MAXFILENAME = 199;
  235. type
  236.     FileNameCountRange = MINFILENAME .. MAXFILENAME;
  237.  
  238. var
  239.     fileNameArray : Array [FileNameCountRange] of Boolean;
  240.     cnt : FileNameCountRange;
  241.  
  242. (* This routine will return a file name which is not being used.  This routine
  243.    will fail (runtime error) if no file name are available.  It is unlikely
  244.    that all 100 are in use since this would mean that there are 100 lists
  245.    floating around someplace which is should nver reasonable happen.
  246.  
  247.    note - The routine only checks an array which keeps track of these file
  248.    names.  If there is a file on the disk with the name xxx???.lrf where ???
  249.    represents a three digit number then that file could get wiped out.
  250.    This seems like an extremely remote occurence which is not worth checking
  251.    for.
  252.  
  253.    note - the extension is not added here as that will be handle when the
  254.    file is created                                                           *)
  255.  
  256. function GetUnusedFileName : FnString;
  257.  
  258. var
  259.     cnt : FileNameCountRange;
  260.     temp : String[3];
  261.  
  262.     begin
  263.     cnt := MINFILENAME;
  264.     while fileNameArray[cnt] do
  265.         begin
  266.         cnt := cnt + 1;
  267.         end;
  268.     fileNameArray[cnt] := TRUE;
  269.     Str(cnt:3,temp);                                    (* convert to string *)
  270.     GetUnusedFileName := 'XXX' + temp;
  271.     end;
  272.  
  273. (*\*)
  274. procedure RecoverFileName(fName : FnString);
  275.  
  276. var
  277.     temp : FileNameCountRange;
  278.     dummy : Integer;
  279.  
  280.     begin
  281.     Val(Copy(fName,4,3),temp,dummy);
  282.     fileNameArray[temp] := FALSE;
  283.     end;
  284.  
  285.  
  286. (* This routine will create a logical record list.  It will accomplish this by
  287.    initializing the logical record page to all zeros and will set the count to
  288.    zero, the current (cursor) to zero and the current page to one.  To create
  289.    an empty list simply call this with a variable declared as type LrList.   *)
  290.  
  291. procedure CreateLrList(var lrLst : LrList);
  292.  
  293.     begin
  294.     lrLst.fName := '';        (* null file name since one does not yet exist *)
  295.     lrLst.currPage := 1;
  296.     lrLst.current := 0;
  297.     lrLst.count := 0;
  298.     FillChar(lrLst.page,PAGESIZE,0);
  299.     end;                                      (* end of CreateLrList routine *)
  300.  
  301. (*\*)
  302. (* This routine will add a logical record number to the end of a logical record
  303.    list.  It will update the cursor position to the newly added record.
  304.    It will increment the count by one.                                       *)
  305.  
  306. procedure AddToLrList(lrNum : LrNumber;
  307.                       var lrLst : LrList);
  308.  
  309. var
  310.     tempPage : PrNumber;
  311.  
  312.     begin
  313.     if lrLst.count = 0 then
  314.         begin                                           (* list is now empty *)
  315.         lrLst.count := 1;
  316.         lrLst.lrArray[1] := lrNum;
  317.         lrLst.current := 1;
  318.         end
  319.     else
  320.         begin
  321.         lrLst.current := lrLst.count;                   (* put cursor at end *)
  322.         tempPage := DesiredPage(lrLst.current);
  323.         if lrLst.currPage <> tempPage then    (* make sure last page current *)
  324.             begin
  325.             lrLst.currPage := tempPage;
  326.             FetchPage(lrLst.fName,lrLst.currPage,lrLst.page);
  327.             end;
  328.         if lrLst.current Mod LRARRAYSIZE = 0 then           (* check if full *)
  329.             begin
  330.             if lrLst.currPage = 1 then
  331.                 begin        (* create the file for the logical records list *)
  332.                 lrLst.fName := GetUnusedFileName;
  333.                 CreateFile(lrLst.fName,LLIST);
  334.                 StorePage(lrLst.fName,1,lrLst.page);
  335.                 end;
  336.             lrLst.currPage := lrLst.currPage + 1;
  337.             FillChar(lrLst.page,PAGESIZE,0);
  338.             end;
  339.         lrLst.current := lrLst.current + 1;
  340.         lrLst.count := lrLst.count + 1;
  341.         lrLst.lrArray[DesiredPosition(lrLst.current)] := lrNum;
  342.         if lrLst.currPage > 1 then
  343.             begin
  344.             StorePage(lrLst.fName,lrLst.currPage,lrLst.page);
  345.             end;
  346.         end;
  347.     end;                                       (* end of AddToLrList routine *)
  348.  
  349. (*\*)
  350. (* This routine will delete an entry from a logical record list.  It is useful
  351.    when deleting records in the case where you do not want to have to recreate
  352.    a list after doing the delete.  It is important to realize two things when
  353.    using this routine.  The first is that it does nothing whatsoever to data
  354.    or index files.  It only affects the logical records list.  Secondly, it
  355.    is faster than recreating a list each time a delete is done, but for
  356.    large lists, it still takes time to perform the delete from the list.
  357.    If a large number of deletes are anticipated, it might be faster to do the
  358.    deletes on the data and index files and then do another retrieval thus
  359.    creating the new list only once.  This deletes the current entry only ie
  360.    entry at the cursor.                                                      *)
  361.  
  362. procedure DeleteFromLrList(var lrLst : LrList);
  363.  
  364. var
  365.     tempLrNum : LrNumber;
  366.     newLst,
  367.     tempLst : LrList;
  368.  
  369.     begin
  370.     CreateLrList(newLst);
  371.     tempLst := lrLst;
  372.     tempLrNum := GetFirstLr(tempLst);
  373.     while tempLrNum <> 0 do                                (* build new list *)
  374.         begin
  375.         if tempLst.current <> lrLst.current then
  376.             begin
  377.             AddToLrList(tempLrNum,newLst);
  378.             end;
  379.         tempLrNum := GetNextLr(tempLst);
  380.         end;
  381.     if lrLst.current = lrLst.count then     (* check to see if deleted entry
  382.                                                is at the end of the list     *)
  383.         begin                                   (* if so make cursor invalid *)
  384.         newLst.currPage := 1;
  385.         newLst.current := 0;
  386.         end
  387.     else
  388.         begin
  389.         newLst.currPage := lrLst.currPage;        (* get new cursor position *)
  390.         newLst.current := lrLst.current;
  391.         end;
  392.     DestroyLrList(lrLst);                             (* get rid of old list *)
  393.     lrLst := newLst;                                      (* return new list *)
  394.     end;                                  (* end of DeleteFromLrList routine *)
  395.  
  396. (*\*)
  397. (* This routine will destroy a logical record list.  It will delete the file
  398.    holding the logical record list if the file was ever created              *)
  399.  
  400. procedure DestroyLrList(var lrLst : LrList);
  401.  
  402.     begin
  403.     lrLst.currPage := 1;
  404.     lrLst.current := 0;
  405.     lrLst.count := 0;
  406.     FillChar(lrLst.page,PAGESIZE,0);
  407.     if lrLst.fName <> '' then
  408.         begin
  409.         DeleteFile(lrLst.fName);
  410.         RecoverFileName(lrLst.fName);
  411.         lrLst.fName := '';
  412.         end;
  413.     end;                                     (* end of DestroyLrList routine *)
  414.  
  415.  
  416. (* This routine will return the first logical record in a logical record list
  417.    and set the cursor to the front of the list.  If the list is empty 0 will
  418.    be returned instead.                                                      *)
  419.  
  420. function GetFirstLr(var lrLst : LrList) : LrNumber;
  421.  
  422.     begin
  423.     if lrLst.count = 0 then
  424.         begin
  425.         GetFirstLr := 0;
  426.         end
  427.     else
  428.         begin
  429.         lrLst.current := 1;
  430.         if lrLst.currPage <> 1 then
  431.             begin
  432.             FetchPage(lrLst.fName,1,lrLst.page);
  433.             lrLst.currPage := 1;
  434.             end;
  435.         GetFirstLr := lrLst.lrArray[1];
  436.         end;
  437.     end;                                        (* end of GetFirstLr routine *)
  438.  
  439. (*\*)
  440. (* This routine will get the last logical record number in a logical record list
  441.    and set the cursor to the back of the list.  If the list is empty then
  442.    0 will be returned instead.  This routine should be used for traversing
  443.    the list in reverse order.                                                *)
  444.  
  445. function GetLastLr(var lrLst : LrList) : LrNumber;
  446.  
  447. var
  448.     temp : PrNumber;
  449.  
  450.     begin
  451.     if lrLst.count = 0 then
  452.         begin
  453.         GetLastLr := 0;
  454.         end
  455.     else
  456.         begin
  457.         lrLst.current := lrLst.count;
  458.         temp := DesiredPage(lrLst.current);
  459.         if lrLst.currPage <> temp then
  460.             begin
  461.             lrLst.currPage := temp;
  462.             FetchPage(lrLst.fName,lrLst.currPage,lrLst.page);
  463.             end;
  464.         GetLastLr := lrLst.lrArray[DesiredPosition(lrLst.current)];
  465.         end;
  466.     end;                                         (* end of GetLastLr routine *)
  467.  
  468.  
  469. (* This routine is used to get the next logical record number in a logical list.
  470.    The cursor will be set to this record list cell as well.  This is used to
  471.    traverse the list in a forward manner.  The routine will return the logical
  472.    record number or 0 if the list is exhausted.                              *)
  473.  
  474. function GetNextLr(var lrLst : LrList) : LrNumber;
  475.  
  476.     begin
  477.     if (lrLst.current = lrLst.count) or
  478.        (lrLst.current = 0) then
  479.         begin
  480.         GetNextLr := 0;
  481.         end
  482.     else
  483.         begin
  484.         if lrLst.current Mod LRARRAYSIZE  = 0 then
  485.             begin
  486.             lrLst.currPage := lrLst.currPage + 1;
  487.             FetchPage(lrLst.fName,lrLst.currPage,lrLst.page);
  488.             end;
  489.         lrLst.current := lrLst.current + 1;
  490.         GetNextLr := lrLst.lrArray[DesiredPosition(lrLst.current)];
  491.         end;
  492.     end;                                         (* end of GetNextLr routine *)
  493.  
  494. (*\*)
  495. (* This routine is used to get the previous logical record number in a logical
  496.    list.  The cursor will be updated to point to this entry.  This is used
  497.    to traverse the list in a backward manner.  The routine will return the
  498.    logical record number or 0 if the list is exhausted or the cursor position
  499.    is invalid.                                                               *)
  500.  
  501. function GetPrevLr(var lrLst : LrList) : LrNumber;
  502.  
  503.     begin
  504.     if (lrLst.current = 1) or
  505.        (lrLst.current = 0) then
  506.         begin
  507.         GetPrevLr := 0;
  508.         end
  509.     else
  510.         begin
  511.         if (lrLst.current - 1) Mod LRARRAYSIZE  = 0 then
  512.             begin
  513.             lrLst.currPage := lrLst.currPage - 1;
  514.             FetchPage(lrLst.fName,lrLst.currPage,lrLst.page);
  515.             end;
  516.         lrLst.current := lrLst.current - 1;
  517.         GetPrevLr := lrLst.lrArray[DesiredPosition(lrLst.current)];
  518.         end;
  519.     end;                                         (* end of GetPrevLr routine *)
  520.  
  521.  
  522. (* This routine is used to get the current logical record in a logical list.
  523.    It will not update the cursor position.  It will return 0 if the cursor
  524.    position is not valid                                                     *)
  525.  
  526. function GetCurrLr(lrLst : LrList) : LrNumber;
  527.  
  528.     begin
  529.     if lrLst.current = 0 then
  530.         begin
  531.         GetCurrLr := 0;
  532.         end
  533.     else
  534.         begin
  535.         GetCurrLr := lrLst.lrArray[DesiredPosition(lrLst.current)];
  536.         end;
  537.     end;                                         (* end of GetCurrLr routine *)
  538.  
  539. (*\*)
  540. (* This routine returns the number of logical records currently in the logical
  541.    record list                                                               *)
  542.  
  543. function GetCountLr(lrLst : LrList) : LrNumber;
  544.  
  545.     begin
  546.     GetCountLr := lrLst.count;
  547.     end;                                        (* end of GetCountLr routine *)
  548.  
  549.  
  550. (* This routine will return the correct physical record number (for the logical
  551.    record list) where the entry lrPos is found                               *)
  552.  
  553. function DesiredPage(lrPos : LrNumber) : PrNumber;
  554.  
  555.     begin
  556.     DesiredPage := ((lrPos - 1) DIV LRARRAYSIZE) + 1;
  557.     end;                                       (* end of DesiredPage routine *)
  558.  
  559.  
  560. (* This routine will return the position within a logical records array for
  561.    given lrPos                                                               *)
  562.  
  563. function DesiredPosition(lrPos : LrNumber) : LRArrayRange;
  564.  
  565.     begin
  566.     DesiredPosition := ((lrPos - 1) MOD LRARRAYSIZE) + 1;
  567.     end;                                   (* end of DesiredPosition routine *)
  568.  
  569.  
  570. (* This routine will return the largest logical record number within a logical
  571.    record list.                                                              *)
  572.  
  573. function FindLargestLr(lrLst : LrList) : LrNumber;
  574.  
  575. var
  576.     tempMax,
  577.     max : LrNumber;
  578.     pageCnt,
  579.     lastPage : PrNumber;
  580.  
  581.     function FindMaxLrInPage(cnt : LRArrayRange) : LrNumber;
  582.  
  583.     var
  584.         max : LrNumber;
  585.         tempCnt : LRArrayRange;
  586.  
  587.     begin
  588.     max := 0;
  589.     for tempCnt := 1 to cnt do
  590.         begin
  591.         if lrLst.lrArray[tempCnt] > max then
  592.             begin
  593.             max := lrLst.lrArray[tempCnt];
  594.             end;
  595.         end;
  596.     FindMaxLrInPage := max;
  597.     end;                                   (* end of FindMaxLrInPage routine *)
  598.  
  599.     begin
  600.     max := 0;
  601.     if lrLst.count <> 0 then
  602.         begin
  603.         if lrLst.fName = '' then
  604.             begin
  605.             max := FindMaxLrInPage(lrLst.count);
  606.             end
  607.         else
  608.             begin
  609.             lastPage := DesiredPage(lrLst.count);
  610.             for pageCnt := 1 to lastPage do
  611.                 begin
  612.                 FetchPage(lrLst.fName,pageCnt,lrLst.page);
  613.                 if pageCnt < lastPage then
  614.                     begin
  615.                     tempMax := FindMaxLrInPage(LRARRAYSIZE);
  616.                     end
  617.                 else
  618.                     begin
  619.                     tempMax := FindMaxLrInPage(lrLst.count -
  620.                                                ((pageCnt - 1) * LRARRAYSIZE));
  621.                     end;
  622.                 if tempMax > max then
  623.                     begin
  624.                     max := tempMax;
  625.                     end;
  626.                 end;
  627.             if LrLst.currPage <> lastPage then
  628.                 begin
  629.                 FetchPage(lrLst.fName,lrLst.currPage,lrLst.page);
  630.                 end;
  631.             end;
  632.         end;
  633.     FindLargestLr := max;
  634.     end;                                             (* end of FindLargestLr *)
  635.  
  636.  
  637. (* This routine will look for a logical record number in a logical record list.
  638.    It will return TRUE if the record number is in the list and FALSE
  639.    otherwise.                                                                *)
  640.  
  641. function FindLrInList(lr : LrNumber;
  642.                       lrLst : LrList) : Boolean;
  643.  
  644. var
  645.     pageEntries : LRArrayRange;
  646.     pageCnt,
  647.     lastPage : PrNumber;
  648.  
  649.     function FindLrInPage(pageEntries : LRArrayRange) : Boolean;
  650.  
  651.     var
  652.         tempCnt : LRArrayRange;
  653.  
  654.     begin
  655.     for tempCnt := 1 to pageEntries do
  656.         begin
  657.         if lrLst.lrArray[tempCnt] = lr then
  658.             begin
  659.             FindLrInPage := TRUE;
  660.             Exit;
  661.             end;
  662.         end;
  663.     FindLrInPage := FALSE;
  664.     end;                                   (* end of FindMaxLrInPage routine *)
  665.  
  666.     begin
  667.     if lrLst.count <> 0 then
  668.         begin
  669.         if lrLst.fName = '' then
  670.             begin
  671.             if FindLrInPage(lrLst.count) then
  672.                 begin
  673.                 FindLrInList := TRUE;
  674.                 Exit;
  675.                 end;
  676.             end
  677.         else
  678.             begin
  679.             lastPage := DesiredPage(lrLst.count);
  680.             for pageCnt := 1 to lastPage do
  681.                 begin
  682.                 FetchPage(lrLst.fName,pageCnt,lrLst.page);
  683.                 if pageCnt < lastPage then
  684.                     begin
  685.                     pageEntries := LRARRAYSIZE;
  686.                     end
  687.                 else
  688.                     begin
  689.                     pageEntries := lrLst.count - ((pageCnt - 1) * LRARRAYSIZE);
  690.                     end;
  691.                 if FindLrInPage(pageEntries) then
  692.                     begin
  693.                     FindLrinList := TRUE;
  694.                     Exit;
  695.                     end;
  696.                 end;
  697.             FetchPage(lrLst.fName,lrLst.currPage,lrLst.page);
  698.             end;
  699.         end;
  700.     FindLrInList := FALSE;
  701.     end;                                             (* end of FindLargestLr *)
  702.  
  703.  
  704.  
  705.  
  706. begin                                                (* initialization code *)
  707. for cnt := MINFILENAME to MAXFILENAME do
  708.     begin
  709.     fileNameArray[cnt] := FALSE;
  710.     end;
  711.  
  712. end.                                                 (* end or LRecList unit *)
  713.