/*
 * Tree Package Version 1.0, April 25, 1989.
 * Implementation by Eric Giguere.  This code is in the public domain.
 *
 * hprint.c
 *
 * This file implements a routine for printing binary trees in a
 * horizontal direction.  It can be used with any of the trees
 * (simple, splay or AVL) implemented in this package.  See the
 * external documentation for details.
 */

#define _NO_HPRINT_PROTOTYPES_

#include <stdio.h>
#include "hprint.h"

#define NLCHAR '\n'

static void h_pr_node(), h_pr_indent();

/*
 * For portability these routines used malloc() and free().
 * Amiga users should feel free to substitute AllocMem and
 * FreeMem if they wish.
 */

extern void *malloc(), free();

/*
 * h_pr_tree -- Print the binary tree rooted at the given node.
 *              Output goes to stdout.  The width of the page/screen
 *              must be given as well as a pointer to a function
 *              for printing the contents of a node.  This routine
 *              does not handle trees larger than the page width.
 *              Returns TRUE if printing was successful.
 */

int h_pr_tree( root, len, func )
  tree_node  *root;
  int         len;
  void      (*func)();
  {
    unsigned char *h_line;
    int            indent;

    if( root == NULL || func == NULL || len <= 0 )
        return( FALSE );

    h_line = malloc( sizeof( unsigned char ) * len );

    if( h_line == NULL )
        return( FALSE );

    indent = len;

    while( --indent >= 0 )
        h_line[ indent ] = FALSE;

    putchar( NLCHAR );

    h_pr_node( 0, root, len, h_line, func );

    putchar( NLCHAR );

    free( h_line );

    return( TRUE );
  }

/*
 * h_pr_node -- Print the contents of a node.
 */

static void h_pr_node( indent, node, len, h_line, func )
  int             indent, len;
  unsigned char  *h_line;
  tree_node      *node;
  void          (*func)();
  {
    indent %= len;

    if( node != NULL )
      {
        h_pr_node( indent + 5, node->right, len, h_line, func );

        h_pr_indent( indent, h_line );
        (*func)( node, len, indent );
        putchar( NLCHAR );

        if( node->parent != NULL )
            h_line[ indent ] = !h_line[ indent ];

        h_pr_node( indent + 5, node->left, len, h_line, func );
      }
    else
      {
        h_pr_indent( indent, h_line );
        h_line[ indent ] = !h_line[ indent ];
        (*func)( NULL, len, indent );
        putchar( NLCHAR );
      }
  }

/*
 * h_pr_indent -- Indent the current node.
 */

static void h_pr_indent( indent, h_line )
  int            indent;
  unsigned char *h_line;
  {
    int start;

    if( indent != 0 )
      {
        for( start = indent; indent > 0; --indent )
          {
            if( h_line[ start - indent ] )
                putchar( '|' );
            else
                putchar( ' ' );
          }

        fputs( "-----", stdout );
      }
    else
        fputs( "root=", stdout );
  }
