home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TOOL_INC.ZIP / TREELIB.INC < prev    next >
Encoding:
Text File  |  1988-01-29  |  5.9 KB  |  237 lines

  1.  
  2. (*
  3.  * treelib.inc - Utility library to build, sort and output trees
  4.  *               in a real visual "tree" format.
  5.  *
  6.  * Author: Samuel H. Smith, 5-Apr-86
  7.  *
  8.  *)
  9.  
  10. const
  11.    maxsubs = 150;                  {maximum number of subnodes for
  12.                                     any single node in the tree}
  13.  
  14.    ascii_tree: boolean = false;    {set to true for ASCII only tree
  15.                                     output; full IBM character set is
  16.                                     used by default}
  17.  
  18.  
  19. type
  20.    long_string = string[255];       {maximum length of an output line}
  21.  
  22.    subnode_index = 0..maxsubs;
  23.  
  24.    name_string = string[40];        {maximum length of the name of a single
  25.                                     tree node}
  26.  
  27.    subnode_table = ^subnode_tabletype;
  28.    node_ptr = ^node_rec;
  29.    subnode_tabletype = array[1..maxsubs] of node_ptr;
  30.  
  31.    node_rec = record
  32.       name:   name_string;          {the name of the node}
  33.  
  34.       count:  subnode_index;        {the count of subnodes}
  35.  
  36.       subs:   subnode_table;        {pointer to subnode table, if any}
  37.    end;
  38.  
  39.  
  40. type
  41.    connector_codes =
  42.      (horizontal, tee, top, cross, middle, bottom, vertical, spaces, empty);
  43.  
  44. const
  45.    connector_strings: array [boolean, connector_codes] of string[3] =
  46.      (('───', '─┬─', ' ┌─', '─┼─', ' ├─', ' └─', ' │ ', '   ', ''),
  47.  
  48.       ('---', '-+-', ' +-', '-|-', ' |-', ' +-', ' | ', '   ', ''));
  49.  
  50.  
  51.  
  52. (*
  53.  * new_node - create and return a new empty node
  54.  *
  55.  * note:  the subnode table node^.subs must be allocated
  56.  *        by the user before any subnodes can be
  57.  *        created.  this was done to eliminate the
  58.  *        space needed by the subnode table on the
  59.  *        terminal nodes in the tree.
  60.  *
  61.  *)
  62.  
  63. function new_node: node_ptr;
  64. var
  65.    node: node_ptr;
  66.    i:    subnode_index;
  67.  
  68. begin
  69.    new (node);
  70.    node^.name := '';
  71.    node^.count := 0;
  72.    node^.subs := nil;
  73.    new_node := node;
  74. end;
  75.  
  76.  
  77.  
  78. (*
  79.  * dispose_tree - dispose of a tree
  80.  *
  81.  *)
  82.  
  83. procedure dispose_tree(var node:  node_ptr);
  84. var
  85.    i:      subnode_index;
  86.  
  87. begin
  88.    if node <> nil then
  89.    begin
  90.       with node^ do
  91.          for i := 1 to count do
  92.             dispose_tree(subs^[i]);
  93.  
  94.       if node^.subs <> nil then
  95.          dispose(node^.subs);
  96.  
  97.       dispose(node);
  98.       node := nil;
  99.    end;
  100. end;
  101.  
  102.  
  103.  
  104. (*
  105.  * sort_node - sort the entries in a node
  106.  *
  107.  *)
  108.  
  109. procedure sort_node(node: node_ptr);
  110. var
  111.    i:        subnode_index;
  112.    swapped:  boolean;
  113.    temp:     node_ptr;
  114.  
  115. begin
  116.    with node^ do
  117.       repeat
  118.          swapped := false;
  119.  
  120.          for i := 1 to count-1 do
  121.             if subs^[i]^.name > subs^[i+1]^.name then
  122.             begin
  123.                temp := subs^[i];
  124.                subs^[i] := subs^[i+1];
  125.                subs^[i+1] := temp;
  126.                swapped := true;
  127.             end;
  128.  
  129.       until swapped = false;
  130. end;
  131.  
  132.  
  133.  
  134. function blanks (len: integer): long_string;
  135. var
  136.    str: long_string;
  137.  
  138. begin
  139.    str := '';
  140.  
  141.    while length (str) < len do
  142.       str := str + ' ';
  143.  
  144.    blanks := str;
  145. end;
  146.  
  147.  
  148.  
  149. function connector (code: connector_codes): long_string;
  150. begin
  151.    connector := connector_strings [ascii_tree, code];
  152. end;
  153.  
  154.  
  155.  
  156. procedure put_node (var fd:     text;              {output file}
  157.                     node:       node_ptr;          {node to output}
  158.                     beforetab:  long_string;       {tabs if before title}
  159.                     titletab:   long_string;       {tabs for title}
  160.                     aftertab:   long_string;       {tabs if after title}
  161.                     before:     connector_codes;   {next tab before title}
  162.                     title:      connector_codes;   {next tab for title}
  163.                     after:      connector_codes);  {next tab after title}
  164.  
  165. var
  166.    i:             subnode_index;
  167.    titlesub:      subnode_index;
  168.  
  169. begin
  170.    with node^ do
  171.    begin
  172.       beforetab := beforetab + connector (before) + blanks (length (name));
  173.       titletab  := titletab  + connector (title ) + name;
  174.       aftertab  := aftertab  + connector (after ) + blanks (length (name));
  175.  
  176.       case count of
  177.          0:     {terminal node with title only}
  178.             writeln (fd, titletab);
  179.  
  180.          1:     {node with 1 subnode}
  181.             put_node (fd, subs^[1], beforetab, titletab, aftertab,
  182.                                     spaces, horizontal, spaces);
  183.  
  184.          2:     {node with 2 subnodes}
  185.             begin
  186.                put_node (fd, subs^[1], beforetab, titletab, aftertab,
  187.                                        spaces, tee, vertical);
  188.  
  189.                put_node (fd, subs^[2], aftertab, aftertab, aftertab,
  190.                                        vertical, bottom, spaces);
  191.             end;
  192.  
  193.          else   {node with n subnodes}
  194.             begin
  195.                titlesub := (count+1) div 2;
  196.  
  197.                writeln (fd, beforetab);
  198.  
  199.                put_node (fd, subs^[1], beforetab, beforetab, beforetab,
  200.                                        spaces, top, vertical);
  201.  
  202.                for i := 2 to titlesub-1 do
  203.                   put_node (fd, subs^[i], beforetab, beforetab, beforetab,
  204.                                           vertical, middle, vertical);
  205.  
  206.                put_node (fd, subs^[titlesub], beforetab, titletab, aftertab,
  207.                                               vertical, cross, vertical);
  208.  
  209.                for i := titlesub+1 to count-1 do
  210.                   put_node (fd, subs^[i], aftertab, aftertab, aftertab,
  211.                                           vertical, middle, vertical);
  212.  
  213.                put_node (fd, subs^[count], aftertab, aftertab, aftertab,
  214.                                            vertical, bottom, spaces);
  215.             end;
  216.       end;
  217.  
  218.    end;
  219.  
  220. end;
  221.  
  222.  
  223.  
  224. (*
  225.  * put_tree - format a tree for output and write it to a file
  226.  *
  227.  *)
  228.  
  229. procedure put_tree (var fd:  text;
  230.                     root:    node_ptr);
  231. begin
  232.    put_node (fd, root, '', '', '', empty, empty, empty);
  233.    flush (fd);
  234. end;
  235.  
  236.  
  237.