home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBII / ECO_TREE.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-03-03  |  37.2 KB  |  1,132 lines

  1. (*
  2.  
  3.          ┌────────────────[ file information report ]────────────────┐
  4.          │                                                           │
  5.          │   Sourcefile for The Fast Commander, v3.51 and higher.    │
  6.          │   All material is protected and licensed.                 │
  7.          │   (C) Copyright 1992 by EUROCON PANATIONAL CORPORATION.   │
  8.          │   Written exclusively by Floor Naaijkens for              │
  9.          │   UltiHouse Software / The ECO Group All Rights Reserved. │
  10.          │   See various documentory files for further information   │
  11.          │   on how to handle these files.                           │
  12.          │                                                           │
  13.          │   Filename:      ECO_TREE.PAS                             │
  14.          │   Version:       3.51                                     │
  15.          │   Last change:   August 30, 1991, 18:51                   │
  16.          │   Dependencies:  KEY·, SUP·, STR·, SCN·, EXT·, WIN·,      │
  17.          │                  DOS·, ····, ····, ····, ····, ····.      │
  18.          │                                                           │
  19.          │   Features/Remarks: Object Oriented Unit.                 │
  20.          │                     Uses extended syntax.                 │
  21.          │                                                           │
  22.          └───────────────────────────────────────────────────────────┘
  23.  
  24.  
  25. *)
  26.  
  27. {$A-,B-,D-,E-,F-,I-,L-,N-,O-,R-,S-,V-}
  28. unit eco_tree;
  29.  
  30. interface
  31.  
  32. uses
  33.   dos, eco_lib
  34.  
  35.   ;
  36.  
  37.  
  38. const
  39.   mainsize : word    =   512;
  40.   debug    : boolean = false;
  41.  
  42.  
  43. type
  44.   srec_ptr = ^srec_chain;
  45.   srec_chain = record
  46.     srec : searchrec;
  47.     bid  :   longint;
  48.     prev :      word;
  49.     link :  srec_ptr;
  50.   end;
  51.  
  52.   str_ptrar = array[0..511] of string[78];
  53.   str_ptr = ^str_ptrar;
  54.  
  55.   nodes = record
  56.     name    : string[12];
  57.     bid     :    longint; { bytes in directory }
  58.     parent  :       word;
  59.   end;
  60.  
  61.   nodearraytype =  array[0..511] of nodes;
  62.   nodearraytypeptr = ^nodearraytype;
  63.  
  64.  
  65.  
  66.   treepanelobj = object { data must not be altered directly }
  67.     autoscan, fullwide        : boolean;
  68.     boxtype,
  69.     x1, y1, x2, y2,
  70.     panel_f, panel_b,
  71.     header_f, header_b        :    byte;
  72.     footer_f, footer_b        :    byte;
  73.     showscan                  : boolean;
  74.     x3, y3, x4, y4,
  75.     popup_f, popup_b,
  76.     tagnocsr_f, tagnocsr_b,
  77.     tagcsr_f, tagcsr_b,
  78.     scrollbar_f, scrollbar_b,
  79.     curactbar_f, curactbar_b  :    byte;
  80.  
  81.     {=================================}
  82.     nodedispptr     :          str_ptr;
  83.     nodearray       : nodearraytypeptr;
  84.     walkcsr,
  85.     walkoffset      :             word;
  86.     newtreeoff      :          boolean;
  87.     checkdriv,
  88.     drivechar       :             char;
  89.     nodenumber      :             word;
  90.     prevparent      :             word;
  91.     sizedir         :          boolean;
  92.     adjwidth        :          boolean;
  93.     widetree        :          boolean;
  94.     showdirnum      :          boolean;
  95.     showpath        :          boolean;
  96.     treeinfofile    :          pathstr;
  97.     horspace        :           string;
  98.     horbar          :           string;
  99.  
  100.     {============================== external =================================}
  101.     procedure init                                                            ;
  102.     procedure done                                                            ;
  103.     procedure setdrive(dr: char)                                              ;
  104.     procedure trace_tree                                                      ;
  105.     procedure draw                      { not needed when walk_tree is run }  ;
  106.     procedure putdefaults                                                     ;
  107.     procedure increase_bar;
  108.     procedure decrease_bar;
  109.     procedure getoptions(
  110.       var
  111.         auto,
  112.         treefullwide , treeshowpath        : boolean;
  113.       var
  114.         bt,
  115.         treex1, treey1, treex2, treey2,
  116.         treepanel_f, treepanel_b,
  117.         treeheader_f, treeheader_b         :    byte;
  118.         treefooter_f, treefooter_b         :    byte;
  119.       var
  120.         treeshowscan                       : boolean;
  121.       var
  122.         treex3, treey3, treex4, treey4,
  123.         treepopup_f, treepopup_b,
  124.         treetagnocsr_f, treetagnocsr_b,
  125.         treetagcsr_f, treetagcsr_b,
  126.         treescrollbar_f, treescrollbar_b,
  127.         treecuractbar_f, treecuractbar_b   :    byte
  128.     );
  129.     procedure setoptions(
  130.       auto,
  131.       treefullwide , treeshowpath          : boolean;
  132.       bt,
  133.       treex1, treey1, treex2, treey2,
  134.       treepanel_f, treepanel_b,
  135.       treeheader_f, treeheader_b           :    byte;
  136.       treefooter_f, treefooter_b           :    byte;
  137.       treeshowscan                         : boolean;
  138.       treex3, treey3, treex4, treey4,
  139.       treepopup_f, treepopup_b,
  140.       treetagnocsr_f, treetagnocsr_b,
  141.       treetagcsr_f, treetagcsr_b,
  142.       treescrollbar_f, treescrollbar_b,
  143.       treecuractbar_f, treecuractbar_b     :    byte
  144.     );
  145.     function  walk_tree_(
  146.       returnkeys : pointer; numberofretkeys: byte; var retkey  : word
  147.     ): pathstr;
  148.     {============================== internal ================================ }
  149.     procedure search_tree(level: word)                                        ;
  150.     procedure save_tree(fname: pathstr)                                       ;
  151.     procedure load_tree(fname: pathstr)                                       ;
  152.     procedure del_subtree(b: word)                                            ;
  153.     procedure jump_curpath                                                    ;
  154.     procedure build_tree(complete: boolean)                                   ;
  155.     function  trace_path(temphead: integer) :                          pathstr;
  156.     function  succpresent(j: word) :                                   boolean;
  157.     function  prevpresent(j: word) :                                   boolean;
  158.     function  calcsucc(j: word) :                                         word;
  159.     function  calcprev(j: word) :                                         word;
  160.     function  calccurpath(var notfound: boolean):                         word;
  161.     function  calc_lvl(j: word) :                                         word;
  162.   end; { treepanelobj }
  163.  
  164.  
  165.  
  166. var
  167.   node_file       : file of nodes;
  168.   srec            :     searchrec;
  169.   s, r            :        string;
  170.   notfound        :       boolean;
  171.   i, j, levels    :          word;
  172.  
  173.  
  174.  
  175. implementation
  176.  
  177.  
  178.  
  179.   procedure treepanelobj.init;
  180.   begin
  181.     nodedispptr := nil; nodearray := nil;
  182.     new(nodearray); new(nodedispptr);
  183.     s := ''; getdir(0, _doscurpath); drivechar := _doscurpath[1];
  184.     walkoffset := 0; { walkcsr := calccurpath(notfound); }
  185.     walkcsr := 0; walkoffset := 0; prevparent := 0; nodenumber := 1;
  186.   end;
  187.  
  188.  
  189.  
  190.   procedure treepanelobj.putdefaults;
  191.   begin
  192.     drivechar    :=              'C';
  193.     checkdriv    :=              'C';
  194.     sizedir      :=             true;
  195.     adjwidth     :=            false;
  196.     widetree     :=             true;
  197.     showdirnum   :=             true;
  198.     showpath     :=             true;
  199.     boxtype      :=               15;
  200.     treeinfofile :=  ':\TREEINFO.DR';
  201.     horspace     :=          {1} ' ';
  202.     horbar       :=          {1} '─';
  203.   end;
  204.  
  205.  
  206.   procedure treepanelobj.increase_bar;
  207.   begin
  208.     case length(horspace) of
  209.       0: begin horspace := ' ';    horbar := '─'    end;
  210.       1: begin horspace := '  ';   horbar := '──'   end;
  211.       2: begin horspace := '   ';  horbar := '───'  end;
  212.       3: begin horspace := '    '; horbar := '────' end;
  213.       else begin horspace := '';     horbar := ''     end;
  214.     end; build_tree(true); newtreeoff := true; draw
  215.   end;
  216.  
  217.  
  218.   procedure treepanelobj.decrease_bar;
  219.   begin
  220.     case length(horspace) of
  221.       0: begin horspace := '    ';    horbar := '────'    end;
  222.       1: begin horspace := '';   horbar := ''   end;
  223.       2: begin horspace := ' ';  horbar := '─'  end;
  224.       3: begin horspace := '  '; horbar := '──' end;
  225.       else begin horspace := '   ';     horbar := '───'     end;
  226.     end; build_tree(true); newtreeoff := true; draw;
  227.   end;
  228.  
  229.  
  230.   procedure treepanelobj.setoptions(
  231.     auto,
  232.     treefullwide , treeshowpath        : boolean;
  233.     bt,
  234.     treex1, treey1, treex2, treey2,
  235.     treepanel_f, treepanel_b,
  236.     treeheader_f, treeheader_b         :    byte;
  237.     treefooter_f, treefooter_b         :    byte;
  238.     treeshowscan                        : boolean;
  239.     treex3, treey3, treex4, treey4,
  240.     treepopup_f, treepopup_b,
  241.     treetagnocsr_f, treetagnocsr_b,
  242.     treetagcsr_f, treetagcsr_b,
  243.     treescrollbar_f, treescrollbar_b,
  244.     treecuractbar_f, treecuractbar_b   :    byte
  245.   );
  246.  
  247.   begin
  248.     autoscan := auto;
  249.     fullwide := treefullwide; showpath := treeshowpath;
  250.     x1 := treex1; y1 := treey1; x2 := treex2; y2 := treey2;
  251.     panel_f := treepanel_f; panel_b := treepanel_b;
  252.     header_f := treeheader_f; header_b := treeheader_b;
  253.     footer_f := treefooter_f; footer_b := treefooter_b;
  254.     showscan := treeshowscan; boxtype := bt;
  255.     x3 := treex3; y3 := treey3; x4 := treex4; y4 := treey4;
  256.     popup_f := treepopup_f; popup_b := treepopup_b;
  257.     tagnocsr_f := treetagnocsr_f; tagnocsr_b := treetagnocsr_b;
  258.     tagcsr_f := treetagcsr_f; tagcsr_b := treetagcsr_b;
  259.     scrollbar_f := treescrollbar_f; scrollbar_b := treescrollbar_b;
  260.     curactbar_f := treecuractbar_f; curactbar_b := treecuractbar_b;
  261.   end;
  262.  
  263.  
  264.  
  265.   procedure treepanelobj.getoptions(
  266.     var
  267.       auto,
  268.       treefullwide , treeshowpath        : boolean;
  269.     var
  270.       bt,
  271.       treex1, treey1, treex2, treey2,
  272.       treepanel_f, treepanel_b,
  273.       treeheader_f, treeheader_b         :    byte;
  274.       treefooter_f, treefooter_b         :    byte;
  275.     var
  276.       treeshowscan                       : boolean;
  277.     var
  278.       treex3, treey3, treex4, treey4,
  279.       treepopup_f, treepopup_b,
  280.       treetagnocsr_f, treetagnocsr_b,
  281.       treetagcsr_f, treetagcsr_b,
  282.       treescrollbar_f, treescrollbar_b,
  283.       treecuractbar_f, treecuractbar_b   :    byte
  284.   );
  285.  
  286.   begin
  287.     auto := autoscan;
  288.     treefullwide := fullwide; treeshowpath := showpath;
  289.     treex1 := x1; treey1 := y1; treex2 := x2; treey2 := y2;
  290.     treepanel_f := panel_f; treepanel_b := panel_b;
  291.     treeheader_f := header_f; treeheader_b := header_b;
  292.     treefooter_f := footer_f; treefooter_b := footer_b;
  293.     treeshowscan := showscan; bt := boxtype;
  294.     treex3 := x3; treey3 := y3; treex4 := x4; treey4 := y4;
  295.     treepopup_f := popup_f; treepopup_b := popup_b;
  296.     treetagnocsr_f := tagnocsr_f; treetagnocsr_b := tagnocsr_b;
  297.     treetagcsr_f := tagcsr_f; treetagcsr_b := tagcsr_b;
  298.     treescrollbar_f := scrollbar_f; treescrollbar_b := scrollbar_b;
  299.     treecuractbar_f := curactbar_f; treecuractbar_b := curactbar_b;
  300.   end;
  301.  
  302.  
  303.  
  304.  
  305.   procedure treepanelobj.done;
  306.   begin
  307.     nodenumber := 1;
  308.     if nodedispptr <> nil then dispose(nodedispptr);
  309.     if nodearray <> nil then dispose(nodearray);
  310.     nodedispptr := nil; nodearray := nil;
  311.   end;
  312.  
  313.  
  314.  
  315.   procedure treepanelobj.setdrive(dr: char);
  316.   begin
  317.     drivechar := upcase(dr); trace_tree;
  318.   end;
  319.  
  320.  
  321.  
  322.   procedure treepanelobj.draw;
  323.   const
  324.     onlyshow : word = $0000;
  325.  
  326.   var
  327.     dkey :   word;
  328.  
  329.   begin
  330.     newtreeoff := true;
  331.     walk_tree_(@onlyshow, 1, dkey);
  332.   end;
  333.  
  334.  
  335.  
  336.  
  337.   function treepanelobj.trace_path(temphead: integer): pathstr;
  338.   var
  339.     off      :                    word;
  340.     st       :                  string;
  341.     i        :                    word;
  342.     tmp      : array[1..50] of integer;
  343.  
  344.   begin
  345.     off := 0;
  346.     while temphead>0 do begin
  347.       inc(off); tmp[off] := temphead;
  348.       temphead := nodearray^[temphead].parent;
  349.     end; st := '\';
  350.     if off>0 then for i := off downto 1 do st := st +
  351.       __cvtstr(nodearray^[tmp[i]].name, _dircase) + _dirslash;
  352.     off := 0; fillchar(tmp, sizeof(tmp), chr(48));
  353.     trace_path := st;
  354.   end;
  355.  
  356.  
  357.  
  358.  
  359.   procedure treepanelobj.search_tree(level: word);
  360.   var
  361.     i         :  integer;
  362.     s         :   string;
  363.     srec_root,
  364.     srec_link : srec_ptr;
  365.  
  366.  
  367.     { not much subdirs in one dir, so no efficiency taken into account }
  368.     procedure sort(srec_root: srec_ptr);
  369.     var
  370.       srec1, srec2, srec3 :  srec_ptr;
  371.       srec                : searchrec;
  372.  
  373.     begin
  374.       srec1 := srec_root;
  375.       while srec1^.link <> nil do begin
  376.         srec2 := srec1^.link; srec3 := srec1;
  377.         repeat { assume we are already sorted properly }
  378.           if srec2^.srec.name < srec3^.srec.name then srec3 := srec2;
  379.           srec2 := srec2^.link;
  380.         until srec2 = nil;
  381.         if srec3 <> srec1 then begin
  382.           srec := srec1^.srec; srec1^.srec := srec3^.srec; srec3^.srec := srec;
  383.         end; srec1 := srec1^.link;
  384.       end;
  385.     end;
  386.  
  387.  
  388.   begin
  389.     srec_root := nil;
  390.     if sizedir then
  391.       findfirst('*.*', anyfile, srec) else findfirst('*.*', directory, srec);
  392.     nodearray^[nodenumber].bid := 0;
  393.     while doserror=0 do begin
  394.       inc(nodearray^[nodenumber].bid, __main(srec.size, mainsize));
  395.       if (((srec.attr and directory)>0) and (srec.name[1]<>'.')) then begin
  396.         if srec_root = nil then begin
  397.           new(srec_root); srec_link := srec_root;
  398.         end else begin
  399.           new(srec_link^.link); srec_link := srec_link^.link;
  400.         end; srec_link^.srec := srec; srec_link^.link := nil;
  401.         srec_link^.prev := prevparent;
  402.       end;
  403.       findnext(srec);
  404.     end; inc(prevparent);
  405.     if srec_root <> nil then begin
  406.       sort(srec_root);
  407.       if (srec_root^.link = nil) and (level = 0) and showscan then __betwscn(
  408.         x3, x4, y3+1, popup_f, popup_b, '\'
  409.       );
  410.       repeat
  411.         s := srec_root^.srec.name;
  412.         with nodearray^[nodenumber] do begin
  413.           name := __lo(s); parent := srec_root^.prev;
  414.         end;
  415.         if showscan then __betwscn(
  416.           x3, x4, y3+1, popup_f, popup_b, __rep(12, ' ')
  417.         );
  418.         if showscan then __betwscn(x3, x4, y3+1, popup_f, popup_b, s);
  419.         inc(nodenumber);
  420.         chdir(s); search_tree(level+1); chdir('..');
  421.         srec_link := srec_root; srec_root := srec_root^.link;
  422.         dispose(srec_link);
  423.       until srec_root = nil;
  424.     end else if (level = 0) and showscan then __betwscn(
  425.       x3, x4, y3+1, popup_f, popup_b, 'No <DIR>''s'
  426.     );
  427.   end; { search_tree }
  428.  
  429.  
  430.  
  431.  
  432.   procedure treepanelobj.trace_tree;
  433.   begin
  434.     chdir(drivechar+':\'); nodenumber :=  1; prevparent :=  0;
  435.     fillchar(nodearray^, sizeof(nodearray^), ' ');
  436.     search_tree(0); chdir(_doscurpath);
  437.     for i := 0 to nodenumber do nodearray^[i].bid := nodearray^[i+1].bid;
  438.   end;
  439.  
  440.  
  441.  
  442.   procedure treepanelobj.save_tree(fname: pathstr);
  443.   begin
  444.     assign(node_file, fname); rewrite(node_file);
  445.     for i := 1 to nodenumber-1 do write(node_file, nodearray^[i]);
  446.     close(node_file);
  447.   end;
  448.  
  449.  
  450.  
  451.   procedure treepanelobj.load_tree(fname: pathstr);
  452.   var
  453.     rec: searchrec;
  454.  
  455.   begin
  456.     nodenumber := 1;
  457.     assign(node_file, fname); reset(node_file);
  458.     while not(eof(node_file)) do begin
  459.       read(node_file, nodearray^[nodenumber]); inc(nodenumber)
  460.     end; close(node_file);
  461.     nodearray^[0].bid := 0;
  462.     findfirst('\*.*', anyfile, rec);
  463.     while doserror=0 do begin
  464.       inc(nodearray^[0].bid, __main(rec.size, 8192)); findnext(rec)
  465.     end;
  466.   end;
  467.  
  468.  
  469.  
  470.  
  471.     { int functions, also used by walk_tree }
  472.     function treepanelobj.succpresent(j: word): boolean;
  473.     var
  474.       nevdl : boolean;
  475.       ll    :    word;
  476.  
  477.     begin
  478.       nevdl := false;
  479.         for ll := j+1 to nodenumber-1 do nevdl :=
  480.           (nodearray^[ll].parent = nodearray^[j].parent) or nevdl;
  481.       succpresent := nevdl;
  482.     end;
  483.  
  484.  
  485.     function treepanelobj.prevpresent(j: word): boolean;
  486.     var
  487.       nevdl : boolean;
  488.       ll    :    word;
  489.  
  490.     begin
  491.       nevdl := false;
  492.         for ll := j-1 downto 1 do nevdl :=
  493.           (nodearray^[ll].parent = nodearray^[j].parent) or nevdl;
  494.       prevpresent := nevdl;
  495.     end;
  496.  
  497.  
  498.     function treepanelobj.calcsucc(j: word): word;
  499.     {use succpresent first to check}
  500.     var
  501.       ll: word;
  502.  
  503.     begin
  504.       ll := j+1;
  505.       while (
  506.         (nodearray^[ll].parent <> nodearray^[j].parent) and (ll<nodenumber)
  507.       ) do inc(ll); calcsucc := ll
  508.     end;
  509.  
  510.  
  511.     function treepanelobj.calcprev(j: word): word;
  512.     {use prevpresent first to check}
  513.     var
  514.       ll: word;
  515.  
  516.     begin
  517.       ll := j-1;
  518.       while (
  519.         (nodearray^[ll].parent<>nodearray^[j].parent) and (ll>1)
  520.       ) do dec(ll);
  521.       calcprev := ll
  522.     end;
  523.  
  524.  
  525.     function treepanelobj.calc_lvl(j: word): word;
  526.     var
  527.       off: word;
  528.  
  529.     begin
  530.       off := 0; while j>0 do begin inc(off); j := nodearray^[j].parent end;
  531.       calc_lvl := off
  532.     end;
  533.  
  534.     {============================================}
  535.  
  536.  
  537.  
  538.   procedure treepanelobj.build_tree;
  539.   var
  540.     s          : string;
  541.     i, hor, k,
  542.     jj, j, pnt :   word;
  543.  
  544.   begin
  545.     chdir(drivechar + ':\');
  546.     nodedispptr^[0] := '\'; hor := length(horspace);
  547.     with nodearray^[0] do begin name := _dirslash; parent := 0 end;
  548.  
  549.     if nodenumber>0 then begin
  550.       s := ''; levels := 1;
  551.       for i := 1 to nodenumber do begin
  552.         if nodearray^[i].parent < nodearray^[i - 1].parent then begin  { down }
  553.           if widetree then
  554.             s := copy(s, 1, calc_lvl(i) * (hor + hor + 2) - hor - 1) else
  555.             s := copy(s, 1, length(s) - (levels - calc_lvl(i) +1) * (hor+1));
  556.           if succpresent(i) then s := s + '├' else s := s + '└';
  557.           s := s + horbar;
  558.           levels := calc_lvl(i);
  559.         end else if (nodearray^[i].parent>nodearray^[i - 1].parent) then begin
  560.           s := copy(s, 1, length(s) - hor - 1);                          { up }
  561.           if succpresent(nodearray^[i].parent) then
  562.             s := s + '│' + horspace else s := s + ' ' + horspace;
  563.           if succpresent(i) then s := s + '├' else s := s + '└';
  564.           s := s + horbar; inc(levels);
  565.         end else begin                                                 { next }
  566.           s := copy(s, 1, length(s) - hor - 1);
  567.           if succpresent(i) then s := s + '├' else s := s + '└';
  568.           s := s + horbar;
  569.         end;
  570.         {▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄ wide }
  571.         if widetree then begin
  572.           if i = 2 then for jj := 1 to hor+1 do s[jj] := ' ';
  573.           if (i = nodearray^[i].parent + 1) and (i > 0) then begin
  574.             s := copy(s, 1, length(s) - hor - 1);
  575.             s := s + '└' + horbar;
  576.             if succpresent(i) then s := s + '┬' else s := s + '─';
  577.             s := s + horbar;
  578.           end;
  579.           if (nodearray^[i - 1].parent = i - 2) and (i > 1) then begin
  580.             if (
  581.               (nodearray^[i - 1].parent = nodearray^[i].parent)
  582.             ) then begin
  583.               for j := hor + hor + 1 downto 1 do if length(s) - j - hor>0 then
  584.                 s[length(s) - j - hor] := ' ';
  585.             end else if (nodearray^[i].parent = i - 1) and (i > 2) then begin
  586.               if not(succpresent(i-2)) then begin
  587.                 for j := (calc_lvl(i))*(hor+1)-1 downto 1 do
  588.                   s[j+hor+3-1] := ' ';
  589.               end else
  590.               if succpresent(i-1) then begin
  591.                 {
  592.                 for j := (calc_lvl(i)-1)*hor+1 downto 1 do s[j+hor+3-1] := st[1];
  593.                 }
  594.                 j := (calc_lvl(i)-1)*hor+1;
  595.                 while s[j] <> '└' do inc(j);
  596.                 while not(s[j] in [' ', '│']) do begin s[j] := ' '; inc(j) end;
  597.               end else begin
  598.                 k:=length(s); while (k>1) and (s[k]<>'└') do dec(k); dec(k);
  599.                 for j := k downto k-hor*2-1 do s[j] := ' '
  600.               end; { multilevel down }
  601.             end; { parent check }
  602.           end; { previous parent check }
  603.           if i = 2 then s[hor * 2 + 3] := '└';
  604.         end; { wide }
  605.         nodearray^[i].name := __cvtstr(nodearray^[i].name, _dircase);
  606.         pnt := pos('.', nodearray^[i].name);
  607.         if pnt = 0 then r := nodearray^[i].name else
  608.           r := copy(nodearray^[i].name, 1, pnt - 1) +
  609.             copy(nodearray^[i].name, pnt + 1, 3);
  610.         nodedispptr^[i] := s + r;
  611.       end; { i }
  612.     end; { else "no <DIR>'s" }
  613.  
  614.     chdir(_doscurpath);
  615.     if sizedir then for i := 0 to nodenumber+1 do
  616.       if nodearray^[i].bid div 1024 div 1024 > 4 then nodedispptr^[i] :=
  617.         __juststr(__num(nodearray^[i].bid div 1024 div 1024),
  618.           ' ', 4, _right_just_str) + 'M ' + nodedispptr^[i] else
  619.         nodedispptr^[i] := __juststr(__num(nodearray^[i].bid div 1024),
  620.           ' ', 4, _right_just_str) + 'K ' + nodedispptr^[i];
  621.   end; { build_tree }
  622.  
  623.  
  624.  
  625.  
  626.   procedure treepanelobj.del_subtree(b: word);
  627.   var
  628.     i,j: word;
  629.  
  630.  
  631.     function node_in_other(ii: word): boolean;
  632.     var bytset : set of byte;
  633.     begin
  634.       bytset := [];
  635.       while ii<>0 do begin
  636.         bytset := bytset + [nodearray^[ii].parent];
  637.         ii := nodearray^[ii].parent;
  638.       end;
  639.       node_in_other := (b in bytset);
  640.     end;
  641.  
  642.  
  643.   begin
  644.     i := b+1;
  645.     while node_in_other(i) and (i<nodenumber) do inc(i);
  646.     move(nodearray^[i], nodearray^[b], (nodenumber-i+1)*sizeof(nodes));
  647.     dec(nodenumber, i-b-1-1);
  648.   end; { del }
  649.  
  650.  
  651.  
  652.  
  653.   function treepanelobj.calccurpath(var notfound: boolean): word;
  654.   var
  655.     i,j      :    word;
  656.     curpath  : pathstr;
  657.     chops    :  string;
  658.  
  659.   begin
  660.     getdir(0, curpath); notfound := false;
  661.     curpath := __normfil(__backapp(curpath));
  662.     if length(curpath) = 3 then calccurpath := 0 else begin
  663.       i := length(curpath)-1; j := i;
  664.       while not (curpath[i] in ['\', '/']) do dec(i);
  665.       inc(i); chops := copy(curpath, i, j-i+1);
  666.  
  667.       j := 0; i := nodenumber - 1;
  668.       while i > 0 do begin
  669.         if debug then writeln(nodearray^[i].name:12, '  ', chops);
  670.         if __comp(nodearray^[i].name, chops) then begin
  671.           if debug then writeln('MATCH level 1');
  672.           if __normfil(__backapp(trace_path(i))) = curpath then begin
  673.             if debug then writeln('MATCH level 2');
  674.             j := i; i := 1; { wordt nog een keer verlaagd = 0 }
  675.           end;
  676.         end;
  677.         dec(i);
  678.       end;
  679.       if j=0 then notfound := true;
  680.       calccurpath := j;
  681.     end;
  682.   end;
  683.  
  684.  
  685.  
  686.  
  687.   procedure treepanelobj.jump_curpath;
  688.   var
  689.     error, check :      boolean;
  690.     scnerr       :         word;
  691.     tmpscn       : _scnimageptr;
  692.  
  693.   begin
  694.     walkcsr := calccurpath(error);
  695.     if error then begin
  696.       new(tmpscn); __savscn(tmpscn);
  697.       done; init;
  698.       __bandwin(true, x3, y3, x4, y4, popup_f, popup_b, sh_default, 2);
  699.       newtreeoff := true; walkoffset := 0; walkcsr := 0;
  700.       __betwscn(x3, x4, y3, popup_f, popup_b, ' Autoscanning ');
  701.       trace_tree;
  702.       save_tree(checkdriv + treeinfofile + drivechar);
  703.       if debug then writeln('Saving: ' + checkdriv + treeinfofile + drivechar);
  704.       build_tree(true);
  705.       walkcsr := calccurpath(error);
  706.       __resscn(tmpscn); dispose(tmpscn);
  707.     end;
  708.     if nodenumber < (y2-y1-1-2) then walkoffset := 0 else begin
  709.       if walkcsr>=(y2-y1-1-2) then walkoffset := walkcsr-(y2-y1-1-2)+1;
  710.       if walkcsr+(y2-y1-1-2) < nodenumber then walkoffset := walkcsr else
  711.         walkoffset := nodenumber - (y2-y1-1-2);
  712.       if walkoffset < 0 then walkoffset := 0;
  713.     end;
  714.   end;
  715.  
  716.  
  717.  
  718.  
  719.  
  720.   function treepanelobj.walk_tree_(
  721.     returnkeys  : pointer; numberofretkeys: byte; var retkey  : word
  722.   ): pathstr;              { key 1: pad  2: drive scan  3: confirm }
  723.  
  724.   type
  725.     arr = array[1..128] of word;
  726.     ar  = ^arr;
  727.  
  728.   var
  729.     check,
  730.     retkeypressed :    boolean;
  731.     fullscnlen,
  732.     scan, bb, cl  :       word;
  733.     jj, h, page,
  734.     key, scnerr   :       word;
  735.     statusbits    :    longint;
  736.     st            :     string;
  737.     pathpointer   :    pathstr;
  738.     statusflags   : _keystatus;
  739.  
  740.  
  741.  
  742.  
  743.     procedure disptreepart(offset: word);
  744.     var i: word;
  745.     begin
  746.       newtreeoff := false;
  747.       __boxscn(x1, y1, x2, y2, boxtype, panel_f, panel_b);
  748.       __betwscn(x1, x2, y1, panel_b, panel_f, ' Tree ');
  749.       __write(x1+1, y2-1, panel_f, panel_b, __rep(x2-x1-1, ' '));
  750.       if boxtype = bt_double then
  751.         __write(x1, y2-2, panel_f, panel_b, '╟'+__rep(x2-x1-1, '─')+'╢') else
  752.         __write(x1, y2-2, panel_f, panel_b, '├'+__rep(x2-x1-1, '─')+'┤');
  753.       __write(x1+1, y2-1, footer_f, footer_b,
  754.         __juststr(
  755.           __slashfil(
  756.             __packfil(
  757.               __cvtstr(
  758.                 __xlatestr(
  759.                   _doscurpath,
  760.                   '.', ' '
  761.                 ),
  762.                 _rem_white_str
  763.               ),
  764.               x2-x1-1
  765.             )
  766.           ),
  767.           ' ', x2-x1-1, _left_just_str
  768.         )
  769.       );
  770.  
  771.       if nodenumber >= page then begin
  772.         for i := 0 to page-1 do
  773.           __write(x1+1, y1+1+i, panel_f, panel_b, __juststr(' ' +
  774.             copy(nodedispptr^[i+offset], 1, x2-x1-1), ' ', x2-x1-1,
  775.             _left_just_str)
  776.           )
  777.       end else begin
  778.         for i := 0 to nodenumber-1 do
  779.           __write(x1+1, y1+1+i, panel_f, panel_b,
  780.             __juststr(' ' + copy(nodedispptr^[i],
  781.             1, x2-x1-1), ' ', x2-x1-1, _left_just_str)
  782.           );
  783.         for i := nodenumber to page-1 do
  784.           __write(x1+1, y1+1+i, panel_f, panel_b, __rep(x2-x1-1, ' '));
  785.       end;
  786.     end;
  787.  
  788.  
  789.  
  790.  
  791.     function disptreecursor(loc: word; out: boolean): pathstr;
  792.     var
  793.       ff, bb, cl, hor :   word;
  794.       st              : string;
  795.  
  796.     begin
  797.       st := nodedispptr^[loc]; bb := length(st);
  798.       if sizedir then cl := 6 else cl := 1;
  799.       while (st[cl] in [' ', '─', '│', '└', '├', '┬']) and
  800.         (cl<=bb) do inc(cl); dec(cl);
  801.       hor := length(horbar); st := '';
  802.       if out then begin
  803.         ff := curactbar_f; bb := curactbar_b
  804.       end else begin
  805.         ff := scrollbar_f; bb := scrollbar_b
  806.       end;
  807.       if showdirnum then st := __juststr(__num(loc), '0', 4, _right_just_str);
  808.       __write(x2 - 5, y1 + 1 + loc - walkoffset , panel_f, panel_b,
  809.         chr(17) + st
  810.       );
  811.       if out then begin
  812.         if hor > 0 then
  813.           __write(x1+1+cl, y1 + 1 + loc - walkoffset, ff, bb, '▌');
  814.         if (walkoffset + walkcsr=0) then __write(
  815.           x1 + 1 + cl + 2,
  816.           y1 + 1 + loc - walkoffset, ff, bb, '▐'
  817.         ) else __write(__min(x1 + 1 + cl + 12, x2 - 6),
  818.           y1 + 1 + loc - walkoffset, ff, bb, '▐'
  819.         )
  820.       end else if (hor>0) and (walkoffset + walkcsr > 0) then __write(
  821.         x1 + 1 + cl, y1 + 1 + loc - walkoffset, bb, ff, '█'
  822.       );
  823.       if (walkoffset + walkcsr = 0) then __attrib(
  824.         x1 + 1 + cl,
  825.         y1 + 1 + loc - walkoffset,
  826.         __min(x1 + 1 + cl + 2, x2 - 6),
  827.         y1 + 1 + loc - walkoffset, ff, bb
  828.       ) else __attrib(
  829.         x1 + 1 + cl + 1,
  830.         y1 + 1 + loc - walkoffset,
  831.         __min(x1 + 1 + cl + 12, x2 - 6),
  832.         y1 + 1 + loc - walkoffset, ff, bb
  833.       ); disptreecursor := nodearray^[walkcsr].name
  834.     end;
  835.  
  836.  
  837.  
  838.  
  839.     procedure undisptreecursor(loc: word);
  840.     var
  841.       cl, hor, bb : word;
  842.       st          : string;
  843.  
  844.     begin
  845.       st := nodedispptr^[loc]; bb := length(st);
  846.       if sizedir then cl := 6 else cl := 1;
  847.       while (st[cl] in [' ', '─', '│', '└', '├', '┬']) and
  848.         (cl<=bb) do inc(cl); dec(cl);
  849.       hor := length(horbar);
  850.       __write(x2 - 6, y1 + 1 + loc - walkoffset , panel_f, panel_b, '      ');
  851.       if walkcsr<>0 then begin
  852.         if hor > 0 then
  853.           __write(x1 +1+cl, y1 + 1 + loc - walkoffset, panel_f, panel_b, '─');
  854.         __attrib(
  855.           __min(x1 + 1 + cl, x2 - 4),
  856.           y1 + 1 + loc - walkoffset,
  857.           __min(x1 + 1 + cl + 12, x2 - 4),
  858.           y1 + 1 + loc - walkoffset, panel_f, panel_b
  859.         )
  860.       end else begin
  861.         if (hor>0) or (walkcsr + walkoffset=0) then __write(
  862.           x1 + 1 + cl,
  863.           y1 + 1 + loc - walkoffset, panel_f, panel_b, ' '
  864.         );
  865.         __attrib(
  866.           __min(x1 + cl, x2 - 4),
  867.           y1 + 1 + loc - walkoffset,
  868.           __min(x1 + 1 + cl + 12, x2 - 4),
  869.           y1 + 1 + loc - walkoffset, panel_f, panel_b
  870.         )
  871.       end;
  872.     end;
  873.  
  874.   var
  875.     tmpscn : _scnimageptr;
  876.  
  877.   begin
  878.     retkeypressed := false; page := y2 - y1 - 1 - 2;
  879.     fullscnlen := x2 - x1 - 1;
  880.  
  881.     if (word((ar(returnkeys)^[1])) = $0000) or newtreeoff then begin
  882.       newtreeoff := false; disptreepart(walkoffset);
  883.       pathpointer := disptreecursor(walkcsr, true);
  884.       __betwscn(x1, x2, y1, panel_f, panel_b, ' Tree '); exit;
  885.     end; { just getting a nice picture and leave }
  886.  
  887.     st := nodedispptr^[walkcsr]; bb := length(st);
  888.     if sizedir then cl := 7 else cl := 1;
  889.     while (st[cl] in [' ','─','│','└','├','┬']) and (cl <= bb) do inc(cl);
  890.     dec(cl);
  891.  
  892.     if (walkoffset+walkcsr=0) then __write(
  893.       x1 - 1 + 4 + 4, y1 + 1 - walkoffset, panel_f, panel_b, ' \ '
  894.     ) else __write(
  895.       x1 - 1 + 2 + 12 + cl, y1+1 + walkcsr - walkoffset, panel_f, panel_b, ' '
  896.     );
  897.  
  898.     __betwscn(x1, x2, y1, panel_b, panel_f, ' Tree ');
  899.  
  900.     repeat
  901.       if newtreeoff then disptreepart(walkoffset); newtreeoff := false;
  902.       pathpointer := disptreecursor(walkcsr, retkeypressed);
  903.       newtreeoff := false;
  904.       if showpath then __write(
  905.         x1 + 1, y2 - 1, footer_f, footer_b,
  906.         __lo(
  907.           __juststr(
  908.             __packfil(
  909.               __cvtstr(
  910.                 __xlatestr(
  911.                   __normfil(
  912.                     trace_path(walkcsr)
  913.                   ),
  914.                   '.\', ' /'
  915.                 ),
  916.                 _rem_white_str
  917.               ),
  918.               x2 - x1 - 1
  919.             ),
  920.             ' ', x2 - x1 - 1, _left_just_str + _to_lowcase_str
  921.           )
  922.         )
  923.       );
  924.  
  925.  
  926.       if retkey=$0000 then key := __retkey else key := retkey;
  927.       statusbits := __statkey(statusflags); retkey := $0000;
  928.       undisptreecursor(walkcsr);
  929.  
  930.       case key of
  931.  
  932.         _up, _padup: begin
  933.           if statusflags._scrollstate then begin
  934.             if statusflags._capsstate then begin
  935.               if (y1>1) then begin
  936.                 __copyscn(x1, y1, x2, y2, x1, y1 - 1);
  937.                 {__partscn(scn4, x1, y2, x2, y2, true);}
  938.                 dec(y1); dec(y2);
  939.               end else {smallbeep};
  940.             end else begin
  941.               if y2 - y1 - 1 > 5 then begin
  942.                 __copyscn(x1, y2 - 2, x2, y2, x1, y2 - 3);
  943.                 __write(x1, y2 + 0, panel_f, panel_b, __rep(x2-x1 + 1,' '));
  944.                 dec(y2); newtreeoff := true; dec(page); jump_curpath;
  945.                 {__partscn(scn4, x1, y2 + 1, x2, y2 + 1, true);}
  946.               end else {smallbeep};
  947.             end;
  948.           end else begin
  949.             if walkcsr>0 then dec(walkcsr);
  950.             if walkcsr<walkoffset then begin
  951.               dec(walkoffset); __copyscn(
  952.                 x1 + 1, y1 + 1, x2 - 1, y2 - 4, x1 + 1, y1 + 2
  953.               );
  954.               __write(x1 + 1, y1 + 1, panel_f, panel_b,
  955.                 __juststr(' ' + copy(nodedispptr^[walkoffset], 1, x2 - x1 - 1),
  956.                 ' ', x2 - x1 - 1, _left_just_str)
  957.               )
  958.             end;
  959.           end; { status }
  960.         end;
  961.  
  962.  
  963.         _down, _paddown: begin
  964.           if statusflags._scrollstate then begin
  965.             if statusflags._capsstate then begin
  966.               if (y2<_currows - 2) then begin
  967.                 __copyscn(x1, y1, x2, y2, x1, y1 + 1);
  968.                 {__partscn(scn4, x1, y1, x2, y1, true);}
  969.                 inc(y1); inc(y2);
  970.               end else {smallbeep};
  971.             end else begin
  972.               if y2 < _currows - 2 then begin
  973.                 __copyscn(x1, y2 - 2, x2, y2, x1, y2 - 1);
  974.                 __write(x1, y2 - 2, panel_f, panel_b, '║');
  975.                 __write(x2, y2 - 2, panel_f, panel_b, '║');
  976.                 inc(y2); newtreeoff := true; inc(page); jump_curpath;
  977.               end else {smallbeep};
  978.             end;
  979.           end else begin
  980.             if walkcsr < nodenumber-1 then inc(walkcsr);
  981.             if walkcsr >= walkoffset + page then begin
  982.               inc(walkoffset);
  983.               __copyscn(x1 + 1, y1 + 2, x2 - 1, y2 - 3, x1 + 1, y1 + 1);
  984.               __write(x1 + 1, y2 - 3, panel_f, panel_b,
  985.                 __juststr(' ' + copy(nodedispptr^[walkoffset + page - 1],
  986.                   1, x2 - x1 - 1), ' ', x2 - x1 - 1, _left_just_str)
  987.                 )
  988.             end;
  989.           end; { status }
  990.         end;
  991.  
  992.  
  993.         _left, _padleft: begin
  994.           if statusflags._scrollstate then begin
  995.             if statusflags._capsstate then begin
  996.               if (x1>1) then begin
  997.                 __copyscn(x1, y1, x2, y2, x1 - 1, y1);
  998.                 {__partscn(scn4, x2, y1, x2, y2, true);}
  999.                 dec(x1); dec(x2);
  1000.               end else {smallbeep};
  1001.             end else begin
  1002.               if x2>x1 + 14 then begin
  1003.                 {__partscn(scn4, x2, y1, x2, y2, true);}
  1004.                 dec(x2); fullscnlen := x2 - x1 - 1;
  1005.                 if x2 - x1 + 1<30 then begin
  1006.                   fullwide := false; horspace := ' '; horbar := '─';
  1007.                 end;
  1008.                 newtreeoff := true; build_tree(true);
  1009.               end;
  1010.             end;
  1011.           end else begin
  1012.             walkcsr := nodearray^[walkcsr].parent;
  1013.             if walkcsr<walkoffset then walkoffset := walkcsr;
  1014.             newtreeoff := true;
  1015.           end;
  1016.         end;
  1017.  
  1018.         _right, _padright: begin
  1019.           if statusflags._scrollstate then begin
  1020.             if statusflags._capsstate then begin
  1021.               if (x2<_curcolumns) then begin
  1022.                 __copyscn(x1, y1, x2, y2, x1 + 1, y1);
  1023.                 {__partscn(scn4, x1, y1, x1, y2, true);}
  1024.                 inc(x1); inc(x2);
  1025.               end else {smallbeep};
  1026.             end else begin
  1027.               if x2<80 then begin
  1028.                 inc(x2); fullscnlen := x2 - x1 - 1; newtreeoff := true;
  1029.                 if x2 - x1 + 1>=30 then fullwide := true
  1030.               end;
  1031.             end;
  1032.           end else begin
  1033.             jj := 0;
  1034.             while (jj<=nodenumber) and (nodearray^[jj].parent<>walkcsr) do
  1035.               inc(jj);
  1036.             if (
  1037.               (jj>0) and (jj<nodenumber) and
  1038.               (nodearray^[jj].parent=walkcsr)
  1039.             ) then walkcsr := jj else
  1040.               if walkcsr < nodenumber-1 then inc(walkcsr);
  1041.             if walkcsr > walkoffset + page - 1 then
  1042.               walkoffset := walkcsr-page+1;
  1043.             newtreeoff := true;
  1044.           end;
  1045.         end;
  1046.  
  1047.         _pgdn, _padpgdn: begin
  1048.           inc(walkcsr, page div 2);
  1049.           if walkcsr = walkoffset + page then walkcsr := walkoffset + page - 1;
  1050.           if walkcsr >= nodenumber then begin
  1051.             walkcsr := nodenumber - 1;
  1052.             if nodenumber - 1 >= page then
  1053.               walkoffset := walkcsr - page + 1 else walkoffset := 0;
  1054.           end else if walkcsr > walkoffset + page - 1 then
  1055.             walkoffset := walkcsr - page + 1;
  1056.           newtreeoff := true;
  1057.           if walkcsr >= nodenumber then walkcsr := nodenumber - 1;
  1058.         end;
  1059.  
  1060.         _pgup, _padpgup: begin
  1061.           dec(walkcsr, page div 2);
  1062.           if walkcsr<walkoffset then walkoffset := walkcsr; newtreeoff := true;
  1063.           if walkcsr<1 then walkcsr := 1; if walkoffset<0 then walkoffset := 0;
  1064.         end;
  1065.  
  1066.         _end, _padend: begin
  1067.           walkcsr := nodenumber -1;
  1068.           walkoffset := nodenumber - page; newtreeoff := true;
  1069.           if nodenumber - 1 < page then walkoffset := 0;
  1070.         end;
  1071.  
  1072.         _home, _padhome: begin
  1073.           walkcsr := 0; walkoffset := 0; newtreeoff := true;
  1074.         end;
  1075.  
  1076.         _padminus: begin
  1077.           if walkcsr>0 then begin
  1078.             if prevpresent(walkcsr) then begin
  1079.               walkcsr := calcprev(walkcsr);
  1080.               if walkcsr<0 then begin walkcsr := 0; walkoffset := 0 end;
  1081.               if walkcsr<walkoffset then walkoffset := walkcsr;
  1082.               newtreeoff := true;
  1083.             end
  1084.           end else walkcsr := 0;
  1085.         end;
  1086.  
  1087.         _padplus: begin
  1088.           if succpresent(walkcsr) then begin
  1089.             walkcsr := calcsucc(walkcsr);
  1090.             if (walkcsr > nodenumber) then begin
  1091.               walkcsr := nodenumber;
  1092.               if nodenumber >= page then
  1093.                 walkoffset := walkcsr - page + 1 else
  1094.                 walkoffset := 0;
  1095.             end else if walkcsr>walkoffset + page - 1 then
  1096.               walkoffset := walkcsr - page + 1; newtreeoff := true;
  1097.             if walkcsr > nodenumber then walkcsr := nodenumber;
  1098.           end;
  1099.         end;
  1100.  
  1101.         { := (key <> __keyword(_keys(ar(returnkeys)^[2])));}
  1102.         else retkeypressed := (key <> ar(returnkeys)^[2]);
  1103.       end; { case }
  1104.  
  1105.       if key = ar(returnkeys)^[2] then begin
  1106.         new(tmpscn); __savscn(tmpscn); done; init;
  1107.         __bandwin(true, x3, y3, x4, y4, popup_f, popup_b, sh_default, 2);
  1108.         newtreeoff := true; walkoffset := 0; walkcsr := 0;
  1109.         __betwscn(x3, x4, y3, popup_f, popup_b, ' Scanning tree ');
  1110.         trace_tree; save_tree(checkdriv + treeinfofile + drivechar);
  1111.         build_tree(true);
  1112.         __resscn(tmpscn); dispose(tmpscn); jump_curpath;
  1113.       end;
  1114.       if autoscan and __direction(retkey) then begin
  1115.         retkeypressed := true; retkey := _enter;
  1116.       end;
  1117.  
  1118.     until retkeypressed;
  1119.  
  1120.     __betwscn(x1, x2, y1, panel_f, panel_b, ' Tree ');
  1121.     pathpointer := disptreecursor(walkcsr, true);
  1122.     if (key = ar(returnkeys)^[3]) or (autoscan) then
  1123.       walk_tree_ := pathpointer else walk_tree_ := '';
  1124.     retkey := key;
  1125.   end; { walk_tree_ }
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131. end. { unit }
  1132.