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

  1. (* TBTree13             Copyright (c)  1988            Dean H. Farwell II    *)
  2.  
  3. unit FileBuff;
  4.  
  5. (*****************************************************************************)
  6. (*                                                                           *)
  7. (*      O P E N  F I L E  B U F F E R  H A N D L I N G  R O U T I N E S      *)
  8. (*                                                                           *)
  9. (*****************************************************************************)
  10.  
  11. (*  This unit handles the opening and closing of files.  It allows a user to
  12.     set a parameter on how many files can be open at a given time and then
  13.     keeps a buffer of open files.  Each time a user wants to access a file a
  14.     routine is called to open the file.  If the file is already open then the
  15.     file id is returned.  If it is not open, it will be opened and the id will
  16.     be returned. Otherwise, the file is opened.  It the max number of files is
  17.     already open the least recently accessed file will be closed first.
  18.  
  19.     The primary advantage to using this unit is that the user does not have
  20.     to worry about opening too many files and causing a runtime error.  If all
  21.     routines which open and close files use this unit instead of explicitly
  22.     opening and closing files then the user can not accidently open too
  23.     many files.  Unfortunately, this unit presently only handles Untyped and
  24.     Text files.  It will not handle Typed files.  This is mainly due to the
  25.     strong type checking of Turbo Pascal.  There are ways around it but
  26.     for now they seem a little unwieldy.  I may work on adding it later.
  27.     For now, this unit can and should be used for all files of type
  28.     File (untyped) and Text.  These routines have been thoroughly tested for
  29.     untyped files and are used extensively.  i have only done limited testing
  30.     with text files.  The are some peculiarities associated with using these
  31.     routines with text files.  This is mainly due to the fact that when a
  32.     call is made to open the a file using OpenTextFile the file id is
  33.     returned to your program.  All is well, except that as you write to the
  34.     file, you are changing the values in the record represented by the file
  35.     id.  These changes are not being reflected in the file id which is in the
  36.     open files list.  Specifically, the id on the open files list does not
  37.     know about any characters in the text buffer.  To alleviate this, do a
  38.     Flush after every write operation.  This needs to be accomplished prior
  39.     to every call to OpenTextFile or any close file operation.  Always
  40.     flushing will alleviate problems.
  41.  
  42.     Given the fact that many files can now be open at the same time, the need
  43.     to arbitrarily close files is alleviated.  This should reduce overhead from
  44.     opening and closing files too often.
  45.  
  46.     The user allocates a number of files to this unit (in other words the user
  47.     sets the maximum number of files which can be in the file open buffer.
  48.     Obviously, the user must not allocate more files to this unit than DOS can
  49.     handle.  This DOS parameter is set in the Config.Sys file at bootup time.
  50.     Normally, the user could just set the number of files allowed open by this
  51.     to the same number allowed by DOS.  Unfortuantely, this would preclude the
  52.     user from opening any files outside of this unit.  Since this unit doesn't
  53.     allow typed files, this would preclude the use of any typed files.  The
  54.     best way to handle this is figure out the DOS limit.  I wanted to include
  55.     a routine to do that but haven't figured out how to do it.  Anyway, once
  56.     you figure out the DOS limit, figure out the maximum number of Typed files
  57.     which will be open at any given time.  Now allocate the difference between
  58.     the DOS limit and the number of Typed files to this unit.  In that way, you
  59.     do not have to worry about exceeding the DOS limit.  Again, if I could
  60.     figureout the DOS limit at run time, then this could be calculated easily.
  61.  
  62.     The scenario for use of these routines is as follows:
  63.  
  64.         1.  Call SetMaxOpenFiles(n) where n is the maximum number of files
  65.             which can be open at one time.  n must be less than or equal to
  66.             then value for 'files' in the config.sys file.  See the DOS manual
  67.             for details.  If SetMaxOpenFiles is not called, the max number of
  68.             open files will default to one (1).  This will not cause any
  69.             errors but it will probably cause a large performance degradation.
  70.  
  71.         2.  When you want to create a file use RewriteTextFile(xxxxxxxx.xxx,fId)
  72.             or RewriteUntypedFile(xxxxxxxx.xxx,fId) where xxxxxxxx.xxx is the
  73.             file name for the file to create and fId is a file id (file
  74.             variable) you have declared.  The OpenUntypedFile routine will
  75.             open your file (if it is not open) and return the appropriate
  76.             file id in fId.  You can now use fId as a file variable.  For text
  77.             files use OpenTextFile for reading and AppendTextFile for writing.
  78.             For example:
  79.  
  80.                 var myFile : Text;
  81.                     str : String;
  82.  
  83.                 begin
  84.                 RewriteTextFile('autoexec.bat',myfile);
  85.                 Writeln(myFile,'verify on');
  86.                 Flush(myFile);
  87.                 CloseFile('autoexec.bat');
  88.                       .
  89.                       .   { to access the file see below }
  90.                       .
  91.                 OpenTextFile('autoexec.bat',myFile);
  92.                 Readln(myFile,str);
  93.                       .
  94.                       .
  95.                       .
  96.                 CloseAllFiles;     { see note 4 below }
  97.                 end;
  98.  
  99.         3.  As noted above, to access the file use
  100.             OpenUntypedFile(xxxxxxxx.xxx,fId) or OpenTextFile(xxxxxxxx.xxx,fId)
  101.             or AppendTextFile(xxxxxxxx.xxx,fId) depending on file type, etc.
  102.             This will ensure that the file will be open and the routine will
  103.             open it if it is not.  It is only necessary to call OpenUntypedFile
  104.             if there is a possibility that the file may not be open or that
  105.             fId is not current.  For example, in the above example,
  106.             AppendTextFile did not have to be called to access autoexec.bat
  107.             immediately  after executing the RewriteFile routine.  To be safe,
  108.             always call one of the open file routines prior to accessing the
  109.             file.  For all the routines except for RewriteUntypedFile and
  110.             RewriteTextFile, the file must exist.
  111.  
  112.         4.  Do not use CLOSE to close myfile.  Use CloseFile(fName) or
  113.             CloseAllFiles instead.  See notes 5 and 6 below.
  114.  
  115.         5.  To ensure that a particular file is closed use
  116.             CloseFile(xxxxxxxx.xxx).  When you call this the file will be
  117.             closed if it is not already closed.  If it is closed then
  118.             nothing happens.
  119.  
  120.         6.  To ensure all files are closed use CloseAllFiles.                *)
  121.  
  122.  
  123. (* Version Information
  124.  
  125.    Version 1.1 - No Changes
  126.  
  127.    Version 1.2 - No Changes
  128.  
  129.    Version 1.3 - No Changes                                                  *)
  130.  
  131.  
  132.  
  133. (*\*)
  134. (*////////////////////////// I N T E R F A C E //////////////////////////////*)
  135.  
  136. interface
  137.  
  138. uses
  139.     Compare,
  140.     FileDecs,
  141.     Numbers,
  142.     Time;
  143.  
  144. type
  145.     OpenFileRange = Byte;
  146.  
  147.  
  148. (* This routine will close the given file and delete its entry from the
  149.    open files buffer.                                                        *)
  150.  
  151. procedure CloseFile(fName : FnString);
  152.  
  153.  
  154. (*  This routine will return the file id (fId) for a file after rewriting it.
  155.     It's operation is equivalent to the REWRITE routine of TURBO.  It will
  156.     create a new file or rewrite an existing file.  It then adds this file
  157.     to the files open buffer in the same manner as OpenFiles would.
  158.  
  159.     note - This routine is for use with Text files only.                     *)
  160.  
  161. procedure RewriteTextFile(fName : FnString;
  162.                           var fId : Text);
  163.  
  164.  
  165. (*  This routine will return the file id (fId) for a file after rewriting it.
  166.     It's operation is equivalent to the REWRITE routine of TURBO.  It will
  167.     create a new file or rewrie an existing file.  It then adds this file
  168.     to the files open buffer in the same manner as OpenFiles would.
  169.  
  170.     note - This routine is for use with Untyped files only.  Unlike with the
  171.     Turbo Pascal routine Rewrite, the user must supply recSize.  It will
  172.     not default to 128.                                                      *)
  173.  
  174. procedure RewriteUntypedFile(fName : FnString;
  175.                              var fId: File;
  176.                              recSize : Word);
  177.  
  178. (*\*)
  179. (*  This routine will return the file id (fId) for the given file.  It will
  180.     also open the file if it is not open.  If the file is not open the routine
  181.     will open it and place the file name in the file open buffer.  If the
  182.     buffer is full showing that the maximum number of files is open, the
  183.     routine will close the least recently used file prior to opening this one.
  184.     The maximum number of files which can be open is set by calling the
  185.     procedure SetMaxOpenFiles which is part of this unit.
  186.  
  187.     Note : This routine uses the TURBO routine RESET.  Therefore the
  188.            restrictions that apply to RESET apply to OpenFile.  For Example,
  189.            an error will result if OpenFile is used on a file that does not
  190.            exist.  Use RewriteTextFile first!
  191.  
  192.     note - This routine is for use with Text files only.                     *)
  193.  
  194. procedure OpenTextFile(fName : FnString;
  195.                        var fId : Text);
  196.  
  197.  
  198. (*  This routine will return the file id (fId) for the given file.  It will
  199.     also open the file if it is not open.  If the file is not open the routine
  200.     will open it and place the file name in the file open buffer.  If the
  201.     buffer is full showing that the maximum number of files is open, the
  202.     routine will close the least recently used file prior to opening this one.
  203.     The maximum number of files which can be open is set by calling the
  204.     procedure SetMaxOpenFiles which is part of this unit.
  205.  
  206.     Note : This routine uses the TURBO routine APPEND.  Therefore the
  207.            restrictions that apply to APEND apply to OpenFile.  For Example,
  208.            an error will result if OpenFile is used on a file that does not
  209.            exist.  Use RewriteTextFile first!
  210.  
  211.     note - This routine is for use with Text files only.                     *)
  212.  
  213. procedure AppendTextFile(fName : FnString;
  214.                        var fId : Text);
  215.  
  216. (*\*)
  217. (*  This routine will return the file id (fId) for the given file.  It will
  218.     also open the file if it is not open.  If the file is not open the routine
  219.     will open it and place the file name in the file open buffer.  If the
  220.     buffer is full showing that the maximum number of files is open, the
  221.     routine will close the least recently used file prior to opening this one.
  222.     The maximum number of files which can be open is set by calling the
  223.     procedure SetMaxOpenFiles which is part of this unit.
  224.  
  225.     Note : This routine uses the TURBO routine RESET.  Therefore the
  226.            restrictions that apply to RESET apply to OpenFile.  For Example,
  227.            an error will result if OpenFile is used on a file that does not
  228.            exist.  Use RewriteUntypedFile first!
  229.  
  230.     note - This routine is for use with Untyped files only.  Unlike with the
  231.     Turbo Pascal routine Rewrite, the user must supply recSize.  It will
  232.     not default to 128.                                                      *)
  233.  
  234. procedure OpenUntypedFile(fName : FnString;
  235.                           var fId : File;
  236.                           recSize : Word);
  237.  
  238.  
  239. (* This routine will Close all files that are open and empty the open file
  240.    buffer.                                                                   *)
  241.  
  242. procedure CloseAllFiles;
  243.  
  244.  
  245. (* This routine will set the maximum files that can be open at a time.  It is
  246.    important that this not exceed the number of files DOS will allow to be
  247.    open.  The number DOS will allow is set in the CONFIG.SYS file.  See the
  248.    appropriate DOS manual for details on the FILES command.  The value is
  249.    initially set to one (1).  This routine should be called BEFORE using the
  250.    buffer.  You can call this routine any time but do not set the value to a
  251.    number lower than the number of files open.  The number open can be checked
  252.    using the GetNumberOpenFiles routine.                                   *)
  253.  
  254. procedure SetMaxOpenFiles(n : OpenFileRange);
  255.  
  256.  
  257. (* This routine will return the number of files which are presently open.    *)
  258.  
  259. function GetNumberOpenFiles : OpenFileRange;
  260.  
  261. (*\*)
  262. (*///////////////////// I M P L E M E N T A T I O N /////////////////////////*)
  263.  
  264. implementation
  265.  
  266. type     FilesType = (TEXTFILE,UNTYPEDFILE);
  267.  
  268.     FileOpenRecPtr = ^FileOpenRec;
  269.     FileOpenRec = record
  270.                   fName : FnString;
  271.                   timeUsed : TimeArr;
  272.                   prev : FileOpenRecPtr;
  273.                   next : FileOpenRecPtr;
  274.                   case fType : FilesType of
  275.                       TEXTFILE    : (fIdText : Text);
  276.                       UNTYPEDFILE : (fIdUntyped : File);
  277.                   end;
  278.  
  279.     FileOpenList = record
  280.                    head : FileOpenRecPtr;
  281.                    count : OpenFileRange;
  282.                    end;
  283. var
  284.     maxOpenFiles : OpenFileRange;
  285.     fileList : FileOpenList;
  286.  
  287. (*\*)
  288. (* This routine will close the given file and delete its entry from the
  289.    open files buffer.                                                        *)
  290.  
  291. procedure CloseFile(fName : FnString);
  292.  
  293. var
  294.     fPtr : FileOpenRecPtr;
  295.     found : Boolean;
  296.  
  297.     begin
  298.     fPtr := fileList.head^.next;
  299.     found := FALSE;
  300.     while (fPtr <> NIL) and (not found) do
  301.         begin
  302.         if fPtr^.fName = fName then
  303.             begin
  304.             case fPtr^.fType of                                  (* close it *)
  305.                 TEXTFILE : Close(fPtr^.fIdText);
  306.                 UNTYPEDFILE : Close(fPtr^.fIdUntyped);
  307.                 end;                                (* end of case statement *)
  308.             fileList.count := fileList.count - 1;
  309.             found := TRUE;
  310.             fPtr^.prev^.next := fPtr^.next;
  311.             if fPtr^.next <> NIL then
  312.                 begin
  313.                 fPtr^.next^.prev := fPtr^.prev;
  314.                 end;
  315.             Dispose(fPtr);
  316.             end
  317.         else
  318.             begin                               (* not found  keep searching *)
  319.             fPtr := fPtr^.next;
  320.             end;
  321.         end;
  322.     end;                                         (* end of CloseFile routine *)
  323.  
  324. (*\*)
  325. (* This routine find the file that was least recently accessed last and returns
  326.    the appropriate pointer.  The calling routine must then close this file
  327.    before opening another.                                                   *)
  328.  
  329. function LRUFile : FileOpenRecPtr;
  330.  
  331. var
  332.     oldPtr,                            (* points to least recently used file *)
  333.     fPtr : FileOpenRecPtr;
  334.     minTime : TimeArr;        (* time least recently used file was last used *)
  335.  
  336.     begin
  337.     fPtr := fileList.head^.next;               (* point to first 'real' cell *)
  338.     oldPtr := fPtr;
  339.     SetMaxTime(minTime);
  340.     while fPtr <> NIL do                        (* go through all open files *)
  341.         begin
  342.         if CompareTime(fPtr^.timeUsed,minTime) = LESSTHAN then
  343.             begin
  344.             minTime := fPtr^.timeUsed;
  345.             oldPtr := fPtr;
  346.             end;
  347.         fPtr := fPtr^.next;
  348.         end;
  349.     LRUFile := oldPtr;
  350.     end;                                           (* end of LRUFile routine *)
  351.  
  352. (*\*)
  353. (*  This routine will return the file id (fId) for a file after rewriting it.
  354.     It's operation is equivalent to the REWRITE routine of TURBO.  It will
  355.     create a new file or rewrite an existing file.  It then adds this file
  356.     to the files open buffer in the same manner as OpenFiles would.
  357.  
  358.     note - This routine is for use with Text files only.                     *)
  359.  
  360. procedure RewriteTextFile(fName : FnString;
  361.                           var fId : Text);
  362.  
  363.  
  364. var
  365.     fPtr : FileOpenRecPtr;
  366.  
  367.     begin
  368.     CloseFile(fName);                                (* make sure its closed *)
  369.     if fileList.count = maxOpenFiles then
  370.         begin                       (* no more files avail - close one first *)
  371.         fPtr := LRUFile;
  372.         CloseFile(fPtr^.fName);
  373.         end;
  374.     New(fPtr);                                     (* create new buffer cell *)
  375.     fPtr^.fName := fName;
  376.     fPtr^.fType := TEXTFILE;
  377.     fPtr^.prev := fileList.head;
  378.     fPtr^.next := fileList.head^.next;                (* put at head of list *)
  379.     fileList.head^.next := fPtr;
  380.     if fPtr^.next <> NIL then
  381.         begin
  382.         fPtr^.next^.prev := fPtr;
  383.         end;
  384.     fileList.count := fileList.count + 1;
  385.     Assign(fPtr^.fIdText,fName);
  386.     Rewrite(fPtr^.fIdText);                               (* create the file *)
  387.     GetTime(fPtr^.timeUsed);                            (* set the time used *)
  388.     Move(fPtr^.fIdText,fId,SizeOf(fId));      (* pass back file id to caller *)
  389.     end;                                   (* end of RewriteTextFile routine *)
  390.  
  391.  
  392. (*\*)
  393. (*  This routine will return the file id (fId) for a file after rewriting it.
  394.     It's operation is equivalent to the REWRITE routine of TURBO.  It will
  395.     create a new file or rewrie an existing file.  It then adds this file
  396.     to the files open buffer in the same manner as OpenFiles would.
  397.  
  398.     note - This routine is for use with Untyped files only.  Unlike with the
  399.     Turbo Pascal routine Rewrite, the user must supply recSize.  It will
  400.     not default to 128.                                                      *)
  401.  
  402. procedure RewriteUntypedFile(fName : FnString;
  403.                              var fId: File;
  404.                              recSize : Word);
  405.  
  406. var
  407.     fPtr : FileOpenRecPtr;
  408.  
  409.     begin
  410.     CloseFile(fName);                                (* make sure its closed *)
  411.     if fileList.count = maxOpenFiles then
  412.         begin                       (* no more files avail - close one first *)
  413.         fPtr := LRUFile;
  414.         CloseFile(fPtr^.fName);
  415.         end;
  416.     New(fPtr);                                     (* create new buffer cell *)
  417.     fPtr^.fName := fName;
  418.     fPtr^.fType := UNTYPEDFILE;
  419.     fPtr^.prev := fileList.head;
  420.     fPtr^.next := fileList.head^.next;                (* put at head of list *)
  421.     fileList.head^.next := fPtr;
  422.     if fPtr^.next <> NIL then
  423.         begin
  424.         fPtr^.next^.prev := fPtr;
  425.         end;
  426.     fileList.count := fileList.count + 1;
  427.     Assign(fPtr^.fIdUntyped,fName);
  428.     Rewrite(fPtr^.fIdUntyped,recSize);                      (* open the file *)
  429.     GetTime(fPtr^.timeUsed);                            (* set the time used *)
  430.     Move(fPtr^.fIdUntyped,fId,SizeOf(fId));   (* pass back file id to caller *)
  431.     end;                                (* end of RewriteUntypedFile routine *)
  432.  
  433. (*\*)
  434. (*  This routine will return the file id (fId) for the given file.  It will
  435.     also open the file if it is not open.  If the file is not open the routine
  436.     will open it and place the file name in the file open buffer.  If the
  437.     buffer is full showing that the maximum number of files is open, the
  438.     routine will close the least recently used file prior to opening this one.
  439.     The maximum number of files which can be open is set by calling the
  440.     procedure SetMaxOpenFiles which is part of this unit.
  441.  
  442.     Note : This routine uses the TURBO routine RESET.  Therefore the
  443.            restrictions that apply to RESET apply to OpenFile.  For Example,
  444.            an error will result if OpenFile is used on a file that does not
  445.            exist.  Use RewriteTextFile first!
  446.  
  447.     note - This routine is for use with Text files only.                     *)
  448.  
  449. procedure OpenTextFile(fName : FnString;
  450.                        var fId : Text);
  451.  
  452.  
  453. var
  454.     found : Boolean;
  455.     fPtr : FileOpenRecPtr;
  456.  
  457.     begin
  458.     fPtr := fileList.head^.next;              (* points to first 'real' cell *)
  459.     found := FALSE;
  460.     while (not found) and (fPtr <> NIL) do
  461.         begin
  462.         if fPtr^.fName = fName then
  463.             begin
  464.             found := TRUE;
  465.             end
  466.         else
  467.             begin
  468.             fPtr := fptr^.next;
  469.             end;
  470.         end;
  471.     if not found then
  472.         begin
  473.         if fileList.count = maxOpenFiles then
  474.             begin                   (* no more files avail - close one first *)
  475.             fPtr := LRUFile;
  476.             CloseFile(fPtr^.fName);
  477.             end;
  478.         New(fPtr);                                 (* create new buffer cell *)
  479.         fPtr^.fName := fName;
  480.         fPtr^.fType := TEXTFILE;
  481.         fPtr^.prev := fileList.head;
  482.         fPtr^.next := fileList.head^.next;            (* put at head of list *)
  483.         fileList.head^.next := fPtr;
  484.         if fPtr^.next <> NIL then
  485.             begin
  486.             fPtr^.next^.prev := fPtr;
  487.             end;
  488.        fileList.count := fileList.count + 1;
  489.        Assign(fPtr^.fIdText,fName);
  490.        Reset(fPtr^.fIdText);                                (* open the file *)
  491.        end;
  492.     GetTime(fPtr^.timeUsed);                            (* set the time used *)
  493.     Move(fPtr^.fIdText,fId,SizeOf(fId));      (* pass back file id to caller *)
  494.     end;                                      (* end of OpenTextFile routine *)
  495.  
  496. (*\*)
  497. (*  This routine will return the file id (fId) for the given file.  It will
  498.     also open the file if it is not open.  If the file is not open the routine
  499.     will open it and place the file name in the file open buffer.  If the
  500.     buffer is full showing that the maximum number of files is open, the
  501.     routine will close the least recently used file prior to opening this one.
  502.     The maximum number of files which can be open is set by calling the
  503.     procedure SetMaxOpenFiles which is part of this unit.
  504.  
  505.     Note : This routine uses the TURBO routine APPEND.  Therefore the
  506.            restrictions that apply to APEND apply to OpenFile.  For Example,
  507.            an error will result if OpenFile is used on a file that does not
  508.            exist.  Use RewriteTextFile first!
  509.  
  510.     note - This routine is for use with Text files only.                     *)
  511.  
  512. procedure AppendTextFile(fName : FnString;
  513.                        var fId : Text);
  514.  
  515.  
  516. var
  517.     found : Boolean;
  518.     fPtr : FileOpenRecPtr;
  519.  
  520.     begin
  521.     fPtr := fileList.head^.next;              (* points to first 'real' cell *)
  522.     found := FALSE;
  523.     while (not found) and (fPtr <> NIL) do
  524.         begin
  525.         if fPtr^.fName = fName then
  526.             begin
  527.             found := TRUE;
  528.             end
  529.         else
  530.             begin
  531.             fPtr := fptr^.next;
  532.             end;
  533.         end;
  534.     if not found then
  535.         begin
  536.         if fileList.count = maxOpenFiles then
  537.             begin                   (* no more files avail - close one first *)
  538.             fPtr := LRUFile;
  539.             CloseFile(fPtr^.fName);
  540.             end;
  541.         New(fPtr);                                 (* create new buffer cell *)
  542.         fPtr^.fName := fName;
  543.         fPtr^.fType := TEXTFILE;
  544.         fPtr^.prev := fileList.head;
  545.         fPtr^.next := fileList.head^.next;            (* put at head of list *)
  546.         fileList.head^.next := fPtr;
  547.         if fPtr^.next <> NIL then
  548.             begin
  549.             fPtr^.next^.prev := fPtr;
  550.             end;
  551.        fileList.count := fileList.count + 1;
  552.        Assign(fPtr^.fIdText,fName);
  553.        Append(fPtr^.fIdText);                               (* open the file *)
  554.        end;
  555.     GetTime(fPtr^.timeUsed);                            (* set the time used *)
  556.     Move(fPtr^.fIdText,fId,SizeOf(fId));      (* pass back file id to caller *)
  557.     end;                                      (* end of OpenTextFile routine *)
  558.  
  559. (*\*)
  560. (*  This routine will return the file id (fId) for the given file.  It will
  561.     also open the file if it is not open.  If the file is not open the routine
  562.     will open it and place the file name in the file open buffer.  If the
  563.     buffer is full showing that the maximum number of files is open, the
  564.     routine will close the least recently used file prior to opening this one.
  565.     The maximum number of files which can be open is set by calling the
  566.     procedure SetMaxOpenFiles which is part of this unit.
  567.  
  568.     Note : This routine uses the TURBO routine RESET.  Therefore the
  569.            restrictions that apply to RESET apply to OpenFile.  For Example,
  570.            an error will result if OpenFile is used on a file that does not
  571.            exist.  Use RewriteUntypedFile first!
  572.  
  573.     note - This routine is for use with Untyped files only.  Unlike with the
  574.     Turbo Pascal routine Rewrite, the user must supply recSize.  It will
  575.     not default to 128.                                                      *)
  576.  
  577. procedure OpenUntypedFile(fName : FnString;
  578.                           var fId : File;
  579.                           recSize : Word);
  580.  
  581.  
  582. var
  583.     found : Boolean;
  584.     fPtr : FileOpenRecPtr;
  585.  
  586.     begin
  587.     fPtr := fileList.head^.next;              (* points to first 'real' cell *)
  588.     found := FALSE;
  589.     while (not found) and (fPtr <> NIL) do
  590.         begin
  591.         if fPtr^.fName = fName then
  592.             begin
  593.             found := TRUE;
  594.             end
  595.         else
  596.             begin
  597.             fPtr := fptr^.next;
  598.             end;
  599.         end;
  600.     if not found then
  601.         begin
  602.         if fileList.count = maxOpenFiles then
  603.             begin                   (* no more files avail - close one first *)
  604.             fPtr := LRUFile;
  605.             CloseFile(fPtr^.fName);
  606.             end;
  607.         New(fPtr);                                 (* create new buffer cell *)
  608.         fPtr^.fName := fName;
  609.         fPtr^.fType := UNTYPEDFILE;
  610.         fPtr^.prev := fileList.head;
  611.         fPtr^.next := fileList.head^.next;            (* put at head of list *)
  612.         fileList.head^.next := fPtr;
  613.         if fPtr^.next <> NIL then
  614.             begin
  615.             fPtr^.next^.prev := fPtr;
  616.             end;
  617.        fileList.count := fileList.count + 1;
  618.        Assign(fPtr^.fIdUntyped,fName);
  619.        Reset(fPtr^.fIdUntyped,recSize);                     (* open the file *)
  620.        end;
  621.     GetTime(fPtr^.timeUsed);                            (* set the time used *)
  622.     Move(fPtr^.fIdUntyped,fId,SizeOf(fId));   (* pass back file id to caller *)
  623.     end;                                   (* end of OpenUntypedFile routine *)
  624.  
  625.  
  626. (*\*)
  627. (* This routine will Close all files that are open and empty the open file
  628.    buffer.                                                                   *)
  629.  
  630. procedure CloseAllFiles;
  631.  
  632.     begin
  633.     while fileList.count <> 0 do
  634.         begin
  635.         CloseFile(fileList.head^.next^.fName);
  636.         end;
  637.     end;                                     (* end of CloseAllFiles routine *)
  638.  
  639.  
  640. (* This routine will set the maximum files that can be open at a time.  It is
  641.    important that this not exceed the number of files DOS will allow to be
  642.    open.  The number DOS will allow is set in the CONFIG.SYS file.  See the
  643.    appropriate DOS manual for details on the FILES command.  The value is
  644.    initially set to one (1).  This routine should be called BEFORE using the
  645.    buffer.  You can call this routine any time but do not set the value to a
  646.    number lower than the number of files open.  The number open can be checked
  647.    using the GetNumberOpenFiles routine.                                   *)
  648.  
  649. procedure SetMaxOpenFiles(n : OpenFileRange);
  650.  
  651.     begin
  652.     maxOpenFiles := n;
  653.     end;                                   (* end of SetMaxOpenFiles routine *)
  654.  
  655.  
  656. (* This routine will return the number of files which are presently open.    *)
  657.  
  658. function GetNumberOpenFiles : OpenFileRange;
  659.  
  660.     begin
  661.     GetNumberOpenFiles := fileList.count;
  662.     end;                                (* end of GetNumberOpenFiles routine *)
  663.  
  664. (*\*)
  665. begin
  666. SetMaxOpenFiles(1);               (* initially, only one open file at a time *)
  667. New(fileList.head);                 (* create an empty cell .. easier to use *)
  668. fileList.count := 0;                                     (* set in-use count *)
  669. fileList.head^.fName := '';                 (* this line not really required *)
  670. fileList.head^.prev := NIL;                           (* neither is this one *)
  671. fileList.head^.next := NIL;
  672. end.
  673.