home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / APCLU.ZIP / APCLU.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1980-01-01  |  16.3 KB  |  508 lines

  1. program LibraryUtility;
  2.  
  3. {
  4.                 written 10/09/84 by Steve Freeman
  5.  
  6.   This program was written to function as Gary Novosielski's LU.  As such it
  7.   will function as a utility to manipulate library members under any operating
  8.   system which will support TURBO Pascal.  Minor rewrites may be necessary for
  9.   other versions of Pascal.
  10.  
  11.   This program is placed into the Public Domain by the author and, as a Public
  12.   Domain program, may NOT be used for commercial purposes.
  13.  
  14.   This program was originally written by Steve Freeman and Upgraded to Version
  15.   1.24 by John Plochner.  This version was converted by John Bingel to run
  16.   exclusively on the NEC-APC, The IBM specific stuff was stripped out and all
  17.   of the (yuk!!!) GO TO's were gotten rid of along with many other structural
  18.   and programming problems.  This version is renamed APCLU  v1.00 to denote
  19.   that it is for a specfic machine.
  20.  
  21.   The program only uses a subset of the info stored in the library:
  22.  
  23.           --- Makeup of a library entry header ---
  24.       status           :  (Unused, in use, and deleted)
  25.       name             :  (Name of member stored in library)
  26.       ext              :  (Type "    "      "    "    "    )
  27.       index            :  (where in lib this member is stored)
  28.       length_of_member :  (it's length )
  29.       CRC              :  (Cyclic Redundancy Check value)
  30.       CreationDate     :  *** NOT IMPLEMENTED ***
  31.       LastChangeDate   :  *** NOT IMPLEMENTED ***
  32.       CreationTime     :  *** NOT IMPLEMENTED ***
  33.       LastChangeTime   :  *** NOT IMPLEMENTED ***
  34.       PadCount         : (used internally by LU)
  35.       filler           : ( room for expansion )
  36.  
  37.  
  38.  
  39.         Modification history
  40.  
  41.        Version    Date       Who            Comments
  42.        -------    ----       ---            --------
  43.        1.01       12/10/85   John Bingel    Added CRC computation for added
  44.                                             files.
  45.        1.00       12/03/85   John Bingel    Made to work on NEC-APC. Changed
  46.                                             so many things that it isn't
  47.                                             feasible to mention them.
  48. }
  49.  
  50. const V {ersion}       = '1.01';
  51.       BufferSize       =  127;      { maximum size of data buffer - 1 }
  52.       EntriesPerBuffer =  4;        { (BufferSize+1)/32 }
  53.       maxent           =  128;      { maximum dir entries this program will take }
  54.       Hell_Freezes_Over= False;     { Main driver loop termination... }
  55.       esc              =  ^[;
  56.       BS               =  ^H;
  57.       CEOL             =  ^['[0K';
  58.       CEOS             =  ^['[0J';
  59.       HI               =  ^['[22m';
  60.       LO               =  ^['[23m';
  61.       CURSOR_OFF       =  ^['[>5h';
  62.       CURSOR_ON        =  ^['[>5l';
  63.  
  64. type TimeType     = integer;
  65.      FileNameType = array[1..11] of char;
  66.      LibFileType  = file;
  67.  
  68.      EntryType    = record
  69.                    status         : byte;
  70.                    name           : array[1..8] of char;
  71.                    ext            : array[1..3] of char;
  72.                    index          : integer;
  73.                    length_of_member         : integer;
  74.                    CRC            : integer;
  75.                    CreationDate   : integer;
  76.                    LastChangeDate : integer;
  77.                    CreationTime   : TimeType;
  78.                    LastChangeTime : TimeType;
  79.                    PadCount       : byte;
  80.                    filler         : array[27..31] of byte;
  81.      end;
  82.      EntryPtr     = ^EntryType;
  83.  
  84.      hexstr       = string[4];
  85.      string10     = string[10];
  86.      filename     = string[14];
  87.      maxstr       = string[255];
  88.  
  89. var buffer           : array[0..BufferSize] of byte;
  90.     buff             : array[0..20479] of byte;
  91.     library,
  92.     file2            : file;
  93.     SizeFile         : file of byte;
  94.     DirectoryChanged : boolean;
  95.     LibName,
  96.     fname            : filename;
  97.     LibSize,
  98.     NumEntries       : integer;
  99.     LibEntry         : EntryType;
  100.     Dir              : array[0..maxent] of EntryPtr;
  101.     active,
  102.     unused,
  103.     deleted          : integer;
  104.     w_table : record x1,x2,y1,y2,
  105.                    currx,curry : integer;
  106.                    overwrote   : array[0..2048] of integer;
  107.             end;
  108.     screen : array[0..2048] of integer absolute $F000:0000;
  109.  
  110. {$I apclu-1.inc }   {      Window handlers and status line drivers }
  111.  
  112.   function Confirm: boolean;
  113.     var c: char;
  114.   begin
  115.       w_write_s(' Confirm operation (Y/N): ');
  116.       repeat
  117.           read(kbd,c);
  118.           c := upcase(c);
  119.       until (c in ['Y','N']);
  120.       w_write_c(c);
  121.       confirm := (c = 'Y')
  122.   end;
  123.  
  124.   function hex(num: integer): hexstr;
  125.   var i, j: integer;
  126.       h: string[16];
  127.       str: hexstr;
  128.   begin
  129.       str := '0000';   h := '0123456789ABCDEF';   j := num;
  130.       for i:=4 downto 1 do begin
  131.           str[i] := h[(j and 15)+1];
  132.           j := j shr 4;
  133.       end;
  134.       hex := str;
  135.   end;
  136.  
  137.   procedure MakeName(f: filename; var name: FileNameType);
  138.   var dotpos,
  139.       endname,
  140.       i       : integer;
  141.   begin
  142.       name := '           ';
  143.       for i:=1 to length(f) do
  144.           f[i] := upcase(f[i]);
  145.       dotpos := pos('.',f);
  146.       if dotpos > 0 then begin
  147.           endname := dotpos-1;
  148.           for i:=1 to 3 do
  149.               if (f[ dotpos+i ] <> ' ')
  150.               AND (DOTPOS + I <= LENGTH(F))then (* ONLY copy chars if they   *)
  151.                                                 (* are actually there! - jmp *)
  152.                      name[8+i] := f[dotpos+i];
  153.       end
  154.       else
  155.           endname := length(f);
  156.       for i:=1 to endname do
  157.           name[i] := f[i];
  158.   end;
  159.  
  160.   procedure PutName(f: filename; n: integer);
  161.   var i: integer;
  162.       name: FileNameType;
  163.   begin
  164.       MakeName(f,name);
  165.       for i:=1 to 8 do
  166.           Dir[n]^.name[i] := name[i];
  167.       for i:=1 to 3 do
  168.           Dir[n]^.ext[i]  := name[i+8];
  169.   end;
  170.  
  171.   function FindMember(f: filename): integer;
  172.   var member, dotpos, endname, i, k: integer;
  173.       lookup: FileNameType;
  174.       found: boolean;
  175.  
  176.     function NamesMatch(entry: integer): boolean;
  177.     var match: boolean;
  178.     begin
  179.         NamesMatch := true;
  180.         with Dir[entry]^ do begin
  181.             for k:=1 to 8 do
  182.                 if name[k]<>lookup[k] then
  183.                     NamesMatch := false;
  184.             for k:=1 to 3 do
  185.                 if ext[k]<>lookup[8+k] then
  186.                     NamesMatch := false;
  187.         end;
  188.     end;
  189.  
  190.   begin
  191.       MakeName(f,lookup);
  192.       found := false;   i := 1;
  193.       while not(found) and (i<NumEntries) do
  194.           if NamesMatch(i) then
  195.               found := true
  196.           else
  197.               i := i + 1;
  198.  
  199.       if (active=1) or not(found) then
  200.           FindMember := 0
  201.       else
  202.           FindMember := i
  203.   end;
  204.  
  205.   function Parse(f: filename): filename;
  206.   var i: integer;
  207.   begin
  208.       if f <> '' then begin
  209.           for i:=1 to length(f) do
  210.               f[i]:=upcase(f[i]);
  211.           i := pos('.',f);
  212.           if i>0 then
  213.               f:=copy(f,1,i-1);
  214.           f := f + '.LBR';
  215.       end;
  216.       Parse := f;
  217.   end;
  218.  
  219.   procedure WriteDirectoryToDisk(var lib: LibFileType);
  220.   var member, i: integer;
  221.   begin
  222.       reset(lib);
  223.       member := 0;
  224.       while member < NumEntries do begin
  225.           for i:=0 to EntriesPerBuffer-1 do
  226.               move(Dir[member+i]^,buffer[32*i],32);
  227.           blockwrite(lib,buffer,1);
  228.           member := member + 4
  229.       end;
  230.       DirectoryChanged := false
  231.   end;
  232.  
  233.   procedure ZeroEntry(n: integer);
  234.   begin
  235.       fillchar(Dir[n]^,32,chr(0));      {clear the record}
  236.       fillchar(Dir[n]^.name[1],11,' '); {clear file name}
  237.       Dir[n]^.status := -1;             {mark unused}
  238.   end;
  239.  
  240.   procedure SortDir;
  241.   var i, j: integer;
  242.  
  243.     function larger(a, b: integer): boolean;
  244.     var ok, x: integer;
  245.         c1, c2: char;
  246.     begin
  247.         ok := 0;   x := 1;
  248.         if (Dir[a]^.status <> 0) and (Dir[b]^.status <> 0) then ok := 2;
  249.         if (Dir[a]^.status <> 0) and (ok = 0)              then ok := 1;
  250.         if (Dir[b]^.status <> 0) and (ok = 0)              then ok := 2;
  251.         while (x < 12) and (ok=0) do begin
  252.             c1 := Dir[a]^.name[x];
  253.             c2 := Dir[b]^.name[x];
  254.             if c1 > c2 then ok := 1;
  255.             if c1 < c2 then ok := 2;
  256.             x := x + 1
  257.         end;
  258.         if ok=1 then
  259.             larger := true
  260.         else
  261.             larger := false
  262.     end;
  263.  
  264.     procedure swap(x, y: integer);
  265.     var temp: EntryPtr;
  266.     begin
  267.         temp   := Dir[x];
  268.         Dir[x] := Dir[y];
  269.         Dir[y] := temp
  270.     end;
  271.  
  272.   begin
  273.       for i:=1 to NumEntries-1 do
  274.           if Dir[i]^.status <> 0 then
  275.               ZeroEntry(i);
  276.       for i:=1 to NumEntries-2 do begin
  277.           for j:=i+1 to NumEntries-1 do
  278.               if larger(i,j) then
  279.                   swap(i,j);
  280.       end;
  281.   end;
  282.  
  283.   procedure CreateDirectory;
  284.   var i: integer;
  285.   begin
  286.       w_make(15,65,10,14);
  287.       rewrite(library);
  288.       w_write_s(' Creating a new library.  Name = ');
  289.       w_write_s(LibName); w_writeln;
  290.       w_write_s(' How many entries? ');  readln(i); w_writeln;
  291.       NumEntries := i + 1;        {add 1 for Directory entry}
  292.       i := NumEntries MOD 4;
  293.       if i <> 0 then
  294.           NumEntries := NumEntries + (4 - i);
  295.  
  296.       for i:=0 to NumEntries-1 do begin
  297.           new(Dir[i]);
  298.           ZeroEntry(i);
  299.       end;
  300.  
  301.       Dir[0]^.status := 0; {directory entry is always used}
  302.       Dir[0]^.length_of_member := NumEntries DIV 4;
  303.       active         := 1;
  304.       unused         := NumEntries - 1;
  305.       deleted        := 0;
  306.       WriteDirectoryToDisk(library);
  307.       w_write_s(' Library created and initialized.');
  308.       delay(250);
  309.       LibSize := (1 + filesize(library)) DIV 8;  {in kilobytes}
  310.       w_delete;
  311.   end;
  312.  
  313.   procedure GetDirectory;
  314.   var i, offset: integer;
  315.   begin
  316.       offset := 0;
  317.       DirectoryChanged := false;
  318.       LibSize := (1 + filesize(library)) DIV 8;  {in kilobytes}
  319.       blockread(library,buffer,1);
  320.       new(Dir[0]);                 {make space for directory header}
  321.       move(buffer[0],Dir[0]^,32);  {move header entry}
  322.       NumEntries := (128 * Dir[0]^.length_of_member) DIV 32;
  323.       for i:=1 to NumEntries-1 do begin
  324.           if (i MOD EntriesPerBuffer) = 0 then begin {read next block}
  325.               blockread(library,buffer,1);
  326.               offset := offset + EntriesPerBuffer;
  327.           end;
  328.           new(Dir[i]);
  329.           move(buffer[32*(i-offset)],Dir[i]^,32);
  330.       end;
  331.       active  := 1;
  332.       unused  := 0;
  333.       deleted := 0;
  334.       for i:=1 to NumEntries-1 do
  335.           if Dir[i]^.status=0 then
  336.               active := active + 1
  337.           else
  338.               if Dir[i]^.status=$FE then
  339.                   deleted := deleted + 1
  340.               else
  341.                   unused := unused + 1;
  342.   end;
  343.  
  344.   procedure OpenLibrary;
  345.   begin
  346.       assign(library,LibName);
  347.       {$I-} reset(library) {$I+};
  348.       if IOresult=0 then
  349.           GetDirectory
  350.       else
  351.           CreateDirectory;
  352.   end;
  353.  
  354.   procedure Directory;
  355.   var i, j: integer;
  356.   begin
  357.       gotoxy(3,6);  write(ceos,#$96,'  name          index  length    CRC ');
  358.       gotoxy(41,6); write(#$96,'  name          index  length    CRC ',#$96);
  359.       gotoxy(3,7);  write(#$93); for i := 5 to 79 do write(#$95); write(#$92);
  360.       gotoxy(41,7); write(#$8F);
  361.       gotoxy(41,5); write(#$91);
  362.       for i:=1 to NumEntries-1 do
  363.           with Dir[i]^ do begin
  364.               if odd(i) then begin
  365.                 gotoxy(3,8+(i-1) div 2);
  366.                 write(#$96,ceol);
  367.                 end
  368.               else begin
  369.                 gotoxy(41,8+ (i-1) div 2);
  370.                  write(#$96,ceol);
  371.               end;
  372.               if status <> $FF then begin
  373.                   if status=$FE then
  374.                       write('*')
  375.                   else write(' ');
  376.                   for j:=1 to 8 do
  377.                       write(name[j]);
  378.                   write('.');
  379.                   for j:=1 to 3 do
  380.                       write(ext[j]);
  381.                   write(' ',index:8,length_of_member:8,'   ',hex(CRC));
  382.               end
  383.               else write('  <empty>                            ');
  384.               gotoxy(79,8+(i-1) div 2);
  385.               write(#$96);
  386.           end;  (* with *)
  387.       gotoxy(41,8+(i-1) div 2);
  388.       write(#$96);
  389.       gotoxy(79,8+(i-1) div 2);
  390.       write(#$96);
  391.       gotoxy(3,9+(i-1) div 2);  write(#$9A);
  392.       for i := 5 to 41 do write(#$95);
  393.       write(#$90);
  394.       for i := 43 to 79 do write(#$95);
  395.       write(#$9B);
  396.   end;
  397.  
  398. {$I apclu-2.inc } { command handlers - removed to include file for space reasons }
  399.  
  400.   procedure NewLib;
  401.   var str : filename;
  402.       x : integer;
  403.   begin
  404.       clrscr;
  405.       gotoxy(3,1);
  406.       write(#$98); for x := 4 to 25 do write(#$95); write(#$99);
  407.       gotoxy(3,2); write(#$96,' Library Utility (LU) ',   #$96);
  408.       gotoxy(3,3); write(#$96);gotoxy(26,3);        write(#$96);
  409.       gotoxy(3,4); write(#$96,' APC version ',V,'     ',  #$96);
  410.       gotoxy(3,5); write(#$9A);
  411.       for x := 4 to 25 do write(#$95); write(#$9B);
  412.       w_make(10,70,6,15);
  413.       w_gotoxy(2,2);
  414.       w_write_s('What library file do you want to use?              ');
  415.       w_writeln;
  416.       w_writeln;
  417.       w_write_s('  Library name format is <filename>[.lbr]'); w_writeln;
  418.       w_writeln;
  419.       w_write_s('  The extention ".LBR" is assumed in all cases'); w_writeln;
  420.       w_write_s('  A null filename (just press <CR>) exits the program.');
  421.       w_gotoxy(40,2);
  422.       write(cursor_on);
  423.       readln(str);
  424.       w_writeln;
  425.       LibName := Parse(str);
  426.       if length(LibName)=0 then begin
  427.           gotoxy(1,23);
  428.           halt;
  429.       end;
  430.       w_delete;
  431.   end;
  432.  
  433.   procedure Menu;
  434.   var selection: char;
  435.       x : integer;
  436.   begin
  437.       OpenLibrary;
  438.  
  439.       {    draw character graphics on screen  --  set up display 'form' }
  440.  
  441.       gotoxy(26,1); write(#$91); for x :=27 to 78 do write(#$95); write(#$99);
  442.       gotoxy(27,2);
  443.       write('  Name: ',LibName,'':14-length(LibName),#$96);
  444.       gotoxy(79,2); write(#$96);
  445.       gotoxy(26,3);write(#$93);gotoxy(79,3);write(#$92);
  446.       gotoxy(27,3); for x := 27 to 78 do write(#$95);
  447.       gotoxy(79,4); write(#$96); gotoxy(3,5); write(#$93);
  448.       for x := 4 to 25 do write(#$95); write(#$90);
  449.       for x :=27 to 78 do write(#$95); write(#$92);
  450.       gotoxy(49,1); write(#$91); gotoxy(63,1); write(#$91);
  451.       gotoxy(49,3); write(#$8F); gotoxy(63,3); write(#$8F);
  452.       gotoxy(49,5); write(#$90); gotoxy(63,5); write(#$90);
  453.  
  454.       repeat
  455.           write(CURSOR_OFF);
  456.           if w_table.x1 <> -1 then begin
  457.               delay(250);
  458.               w_delete;
  459.           end;
  460.           LibSize := (1 + filesize(library)) DIV 8;  {in kilobytes}
  461.  
  462.           { Update info on screen which could have changed cuz of last cmd }
  463.  
  464.           gotoxy(27,4);
  465.           write(     '  Size: ',LibSize:3,'K bytes    ',#$96);
  466.           gotoxy(50,2);
  467.           write(' Total: ',active+deleted+unused - 1:3,'  ',#$96);
  468.           gotoxy(50,4);
  469.           write(     ' Active: ',active - 1:3,' ',#$96);
  470.           gotoxy(64,2);
  471.           write(' Erased: ',deleted:3,'  ');
  472.           gotoxy(64,4);
  473.           write(     ' Unused: ',unused:3);
  474.  
  475.           { turn on status line for function key input }
  476.  
  477.           Directory; { show updated library directory }
  478.           set_status('X eXtract ','A Add     ','E Erase   ',
  479.                      'U Unerase ','P Pack    ','H Help    ','Q Quit    ');
  480.           repeat
  481.               read(kbd,selection);
  482.               selection := upcase(selection);
  483.           until (selection in ['X','A','E','U','P','?','H','Q']);
  484.           clear_status;
  485.           write(CURSOR_ON);
  486.           case selection of
  487.                 'A': Add;
  488.                 'X': Extract;
  489.             'H','?': Help;
  490.                 'E': Delete; (* erase *)
  491.                 'P': Reorganize; (* pack *)
  492.                 'U': Undelete;
  493.                 'Q':;
  494.           end;
  495.       until selection='Q';
  496.       if DirectoryChanged then WriteDirectoryToDisk(library);
  497.       close(library);
  498.   end;
  499.  
  500. begin {Main}
  501.       write(LO);
  502.       w_table.x1 := -1;
  503.       repeat
  504.             NewLib;
  505.             Menu;
  506.       until Hell_Freezes_Over;
  507. end.
  508.