home *** CD-ROM | disk | FTP | other *** search
/ PC Open 19 / pcopen19.iso / Zipped / CALMIR21.ZIP / SOURCE.ZIP / SRC / FOURDOS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-02-20  |  7.2 KB  |  240 lines

  1. {**************************************************************************}
  2. {                                                                          }
  3. {    Calmira shell for Microsoft« Windows(TM) 3.1                          }
  4. {    Source Release 2.1                                                    }
  5. {    Copyright (C) 1997-1998 Li-Hsin Huang                                 }
  6. {                                                                          }
  7. {    This program is free software; you can redistribute it and/or modify  }
  8. {    it under the terms of the GNU General Public License as published by  }
  9. {    the Free Software Foundation; either version 2 of the License, or     }
  10. {    (at your option) any later version.                                   }
  11. {                                                                          }
  12. {    This program is distributed in the hope that it will be useful,       }
  13. {    but WITHOUT ANY WARRANTY; without even the implied warranty of        }
  14. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         }
  15. {    GNU General Public License for more details.                          }
  16. {                                                                          }
  17. {    You should have received a copy of the GNU General Public License     }
  18. {    along with this program; if not, write to the Free Software           }
  19. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             }
  20. {                                                                          }
  21. {**************************************************************************}
  22.  
  23. unit FourDOS;
  24.  
  25. { 4DOS file descriptions
  26.  
  27.   The main problem with supporting descriptions is maintaining consistency.
  28.   An obvious solution would be to associate a PString with each TDirItem
  29.   object.  But considering the turmoil during copying and moving, keeping
  30.   track of everything would be very difficult during updating. Also, not
  31.   all files are shown at once (depending on the filter), so the need to
  32.   reconcile the disk file with the memory descriptions would complicate
  33.   matters.
  34.  
  35.   Hence the current implementation uses a centralized approach.  The
  36.   entire set of descriptions is kept inside a TStringList, one for each
  37.   TDirectory.  When we need to find a description, the list must be
  38.   searched, but updating is OK since there are no pointers floating around
  39.   as with the PString approach, and consistency is guaranteed because each
  40.   TStringList exactly mirrors a descript.ion file.
  41.  
  42.   The Directry unit contains optimizations to avoid accessing the list
  43.   when it is already known that an object doesn't have a description.  A
  44.   further speedup is obtained by storing a pointer to the TDirItem
  45.   object so that a full string search occurs rarely.
  46.  
  47.   This unit assumes that a "description" is the entire string following the
  48.   first space character.  Actually, there may be 04 markers (Ctrl-D) in the
  49.   text which indicates extra data maintained by programs other than 4DOS.
  50.   These are filtered and maintained by each TDirItem because it would be
  51.   too complicated to regard the data as another "column" when replacing the
  52.   strings in the list.
  53.  
  54.   4DOS is a registered trademark of JP Software Inc.
  55. }
  56.  
  57. interface
  58.  
  59. uses Classes, SysUtils;
  60.  
  61. const
  62.   DescriptionFile : string[15] = 'descript.ion';
  63.  
  64. type
  65.   TDescriptions = class(TStringList)
  66.   private
  67.     FModified : Boolean;
  68.   protected
  69.     procedure Changed; override;
  70.   public
  71.     function Get(const filename: string; Item: TObject): string;
  72.     procedure Put(const filename: string; Item: TObject;
  73.       const value: string);
  74.     procedure LoadFromPath(const path: TFilename);
  75.     procedure SaveToPath(const path : TFilename);
  76.     property Modified : Boolean read FModified;
  77.   end;
  78.  
  79. procedure MergeDescriptionFiles(TargetDir, SourceDir : TFilename);
  80.  
  81. var
  82.   SharedDesc : TDescriptions;
  83.  
  84.   { SharedDesc is a special shared description file used during copying }
  85.  
  86. implementation
  87.  
  88. uses Directry, Strings;
  89.  
  90.  
  91. procedure TDescriptions.Changed;
  92. begin
  93.   inherited Changed;
  94.   FModified := True;
  95. end;
  96.  
  97.  
  98. function TDescriptions.Get(const filename: string;
  99.   Item: TObject): string;
  100. var
  101.   i, p, compare: Integer;
  102.   s: string;
  103. begin
  104.   { Retrieves a file description.  If the Item parameter is nil,
  105.     the object pointers are ignored. }
  106.  
  107.   Result := '';
  108.   if Count = 0 then Exit;
  109.  
  110.   if Item = nil then i := -1
  111.   else i:= IndexOfObject(Item);
  112.  
  113.   if i > -1 then begin
  114.     { found an object match }
  115.     s := Strings[i];
  116.     p := Pos(' ', s);
  117.     Result := Copy(s, p+1, 255);
  118.   end
  119.   else begin
  120.     { must do a string search }
  121.     for i := 0 to Count-1 do begin
  122.       s := Strings[i];
  123.       p := Pos(' ', s);
  124.       if CompareText(Copy(s, 1, p-1), filename)= 0 then begin
  125.         Objects[i] := Item;
  126.         Result := Copy(s, p+1, 255);
  127.         Exit;
  128.       end
  129.     end;
  130.   end;
  131. end;
  132.  
  133.  
  134. procedure TDescriptions.Put(const filename: string; Item: TObject;
  135.   const value: string);
  136. var
  137.   i, p: Integer;
  138.   s: string;
  139. begin
  140.   if Item = nil then i := -1
  141.   else i := IndexOfObject(Item);
  142.  
  143.   if i > -1 then
  144.     { found an object match }
  145.     if value = '' then Delete(i)
  146.     else Strings[i] := Format('%s %s', [filename, value])
  147.  
  148.   else begin
  149.     { must do a string search }
  150.     for i := 0 to Count-1 do begin
  151.       s := Strings[i];
  152.       p := Pos(' ', s);
  153.       if CompareText(Copy(s, 1, p-1), filename) = 0 then begin
  154.         if value = '' then Delete(i)
  155.         else begin
  156.           Objects[i] := Item;
  157.           Strings[i] := Format('%s %s', [filename, value]);
  158.         end;
  159.         Exit;
  160.       end;
  161.     end;
  162.  
  163.     if value > '' then
  164.       AddObject(filename + ' ' + value, Item);
  165.   end;
  166. end;
  167.  
  168.  
  169. procedure TDescriptions.LoadFromPath(const path: TFilename);
  170. var
  171.   rec : TSearchRec;
  172.   code : Integer;
  173. begin
  174.   Clear;
  175.   FModified := False;
  176.  
  177.   code := FindFirst(path + DescriptionFile, faHidden, rec);
  178.   if code = -3 then
  179.     raise EScanError.CreateFmt('Cannot open %s', [MakeDirname(path)])
  180.   else if code = 0 then
  181.     inherited LoadFromFile(path + DescriptionFile);
  182. end;
  183.  
  184.  
  185. procedure TDescriptions.SaveToPath(const path : TFilename);
  186. var
  187.   filename : TFilename;
  188. begin
  189.   if FModified then begin
  190.     filename := path + DescriptionFile;
  191.     if Count= 0 then DeleteFile(filename)
  192.     else begin
  193.       FileSetAttr(filename, faArchive);
  194.       inherited SaveToFile(filename);
  195.       FileSetAttr(filename, faHidden);
  196.     end;
  197.     FModified := False;
  198.   end;
  199. end;
  200.  
  201.  
  202. procedure MergeDescriptionFiles(TargetDir, SourceDir : TFilename);
  203. var
  204.   src, dest : TDescriptions;
  205.   s : string;
  206.   i, p : Integer;
  207. begin
  208.   src := TDescriptions.Create;
  209.   dest := TDescriptions.Create;
  210.   AppendStr(TargetDir, '\');
  211.   AppendStr(SourceDir, '\');
  212.   try
  213.     src.LoadFromPath(SourceDir);
  214.     dest.LoadFromPath(TargetDir);
  215.  
  216.     for i := src.Count-1 downto 0 do begin
  217.       s := src[i];
  218.       p := Pos(' ', s);
  219.       if p > 0 then dest.Put(Copy(s, 1, p-1), nil, Copy(s, p+1, 255));
  220.     end;
  221.  
  222.     dest.SaveToPath(TargetDir);
  223.   finally
  224.     src.Free;
  225.     dest.Free;
  226.   end;
  227. end;
  228.  
  229.  
  230. procedure DoneFourDOS; far;
  231. begin
  232.   SharedDesc.Free;
  233. end;
  234.  
  235.  
  236. initialization
  237.   AddExitProc(DoneFourDOS);
  238.   SharedDesc := TDescriptions.Create;
  239. end.
  240.