/* Time-stamp: <96/11/27 17:36:30 john> */

/*
# Purpose: Outputs a streetplan as ASCII graphics.
 */

#include <stdio.h>
#include "attr.h"
#include "grid.h"
#include "style.h"
#include "anchor.h"
#include "ascii.h"

/* #define debug 1 */

static void output_run(int n, char c)
{
  int i;
  for (i = 0; i < n; i++) putchar(c);
}

static void output_grid_lines(struct grid *grid,
			      struct row *one,
			      struct row *tother,
			      int span)
{
  int left_col = grid->min_rank;
  int right_col = grid->max_rank;
  int column;
  struct cell *this_one = NULL;
  struct cell *this_tother = NULL;
#ifdef debug
  if (one != NULL)
    show_row(one, 0);
  if (tother != NULL)
    show_row(tother, 1);

  for (column = left_col;
       column < right_col;
       column++)
    {
      struct cell *prev_one = NULL;
      struct cell *prev_tother = NULL;

      this_one = NULL;
      this_tother = NULL;

      if ((one != NULL) &&
	  (column >= one->min_rank) &&
	  (column <= one->max_rank))
	{
	  this_one = cell_n(one, column);
	}

      if ((tother != NULL) &&
	  (column >= tother->min_rank) &&
	  (column <= tother->max_rank))
	{
	  this_tother = cell_n(tother, column);
	}

      if ((one != NULL) &&
	  ((column-1) >= one->min_rank) &&
	  ((column-1) <= one->max_rank))
	{
	  prev_one = cell_n(one, (column-1));
	}

      if ((tother != NULL) &&
	  ((column-1) >= tother->min_rank) &&
	  ((column-1) <= tother->max_rank))
	{
	  prev_tother = cell_n(tother, (column-1));
	}

      if (prev_one == NULL)
	{
	  printf("%d: prev_one absent\n", column);
	} else {
	  if (prev_one->entry == NULL)
	    {
	      printf("%d: prev_one empty\n", column);
	    } else {
	      printf("%d: prev_one == %s\n", column, prev_one->entry->name);
	    }
	}
      if (prev_tother == NULL)
	{
	  printf("%d: prev_tother absent\n", column);
	} else {
	  if (prev_tother->entry == NULL)
	    {
	      printf("%d: prev_tother empty\n", column);
	    } else {
	      printf("%d: prev_tother == %s\n", column, prev_tother->entry->name);
	    }
	}
      if (this_one == NULL)
	{
	  printf("%d: this_one absent\n", column);
	} else {
	  if (this_one->entry == NULL)
	    {
	      printf("%d: this_one empty\n", column);
	    } else {
	      printf("%d: this_one == %s\n", column, this_one->entry->name);
	    }
	}
      if (this_tother == NULL)
	{
	  printf("%d: this_tother absent\n", column);
	} else {
	  if (this_tother->entry == NULL)
	    {
	      printf("%d: this_tother empty\n", column);
	    } else {
	      printf("%d: this_tother == %s\n", column, this_tother->entry->name);
	    }
	}

    }
  printf("End of columns of this row\n");

#endif
  for (column = left_col;
       column < right_col;
       column++)
    {
      struct cell *prev_one = NULL;
      struct cell *prev_tother = NULL;
      int width = grid->row_title_widths[column-left_col];

      this_one = NULL;
      this_tother = NULL;

      if ((one != NULL) &&
	  (column >= one->min_rank) &&
	  (column <= one->max_rank))
	{
	  this_one = cell_n(one, column);
	}

      if ((tother != NULL) &&
	  (column >= tother->min_rank) &&
	  (column <= tother->max_rank))
	{
	  this_tother = cell_n(tother, column);
	}

      if ((one != NULL) &&
	  ((column-1) >= one->min_rank) &&
	  ((column-1) <= one->max_rank))
	{
	  prev_one = cell_n(one, (column-1));
	}

      if ((tother != NULL) &&
	  ((column-1) >= tother->min_rank) &&
	  ((column-1) <= tother->max_rank))
	{
	  prev_tother = cell_n(tother, (column-1));
	}
#if 0
      printf("%.2d%c%c", column, this_one?'A':'a',
	     this_tother?'B':'b');
#endif
      if (this_one || this_tother)
	{
	  if (this_one && 
	      (((this_one->y_into+1) < this_one->entry->height)
	       )
	      )
	    {
	      if ((((this_one == NULL) || (this_tother == NULL)) ||
		   (this_one->entry == this_tother->entry)) &&
		  (((prev_one == NULL) || (prev_tother == NULL)) ||
		   (prev_one->entry == prev_tother->entry)))
		{
		  printf("| ");
		} else {
		  printf("+ ");
		}
	      output_run(width+1, ' ');
	    } else {
	      printf("+-");
	      output_run(width+1, '-');
	    }
	} else {

	  if (prev_one || prev_tother)
	    {
	      printf("|");
	      output_run(width+2, ' ');
	    } else {
	      output_run(width+3, ' ');
	    }
	}
    }
  if (this_one || this_tother)
    {
      printf("+");
    }
  printf("\n");
}

static void output_in_width(int width,
			    char *text,
			    struct style *style,
			    struct entry *entry_to_link)
{
  int before, during, after;

  during = strlen(text);
  before = (width - during) / 2;
  after = width - (during + before);

  output_run(before, ' ');
  output_with_link(text, style, entry_to_link, NULL);
  output_run(after, ' ');
}

static void output_grid_names(struct grid *grid,
			      struct row *row,
			      int span,
			      struct style *style)
{
  int left_col = grid->min_rank;
  int right_col = grid->max_rank;
  int column;
  struct cell *this_one = NULL;

#ifdef debug
  show_row(row, 2);
#endif

  for (column = left_col;
       column < right_col;
       column++)
    {
      int width = grid->row_title_widths[column-left_col];

      if ((row != NULL) &&
	  (column >= row->min_rank) &&
	  (column <= row->max_rank))
	{
	  this_one = cell_n(row, column);
	}
      if (this_one)
	{
#if 0
	  printf("%.2dA ", column, 'A');
#endif
	  if ((this_one->x_into == 0)
#if 0
	      && (this_one->y_into == 0)
#endif
	      && (this_one->cell_text != NULL)
	      )
	    {
	      int this_width = width+1;
	      printf("| ");
	      if (span)
		{
		  int j;
		  for (j = 1; j < this_one->entry->width; j++)
		    {
		      this_width += 3;
		      this_width +=
			grid->row_title_widths[column+j-left_col];
		    }
		}
	      output_label(this_one);
	      output_in_width(this_width, this_one->cell_text,
			      style, this_one->entry);
	    } else {
	      if (this_one->x_into == 0)
		{
		  /* This is a gap in its own right */
		  printf("| ");
		  output_run(width+1, ' ');
		} else {
		  /* This is not so much a gap as the second part of a spanned cell */
		  if (span)
		    {
		    } else {
		      output_run(width+3, ' ');
		    }
		}
	    }
	} else {
	  struct cell *prev_one = NULL;

	  if ((row != NULL) &&
	      ((column-1) >= row->min_rank) &&
	      ((column-1) <= row->max_rank))
	    {
	      prev_one = cell_n(row, column-1);
	    }
#if 0
	  printf("%.2da%c", column, prev_one?'Y':'y');
#endif
	  if (prev_one)
	    {
	      printf("!");
	      output_run(width+2, ' ');
	    } else {
	      output_run(width+3, ' ');
	    }
	}
  
  }
  if (this_one)
    {
      printf("|");
    }
  printf("\n");
}

void output_grid_as_ascii(struct grid *grid,
			  int span,
			  struct style *style)
{
  struct row *prev_row = NULL;
  int this_row_index;
  
  for (this_row_index = 0;
       this_row_index < grid->n_rows;
       this_row_index++)
    {
      struct row *this_row=grid->rows[this_row_index];
      output_grid_lines(grid, prev_row, this_row, span);
      output_grid_names(grid, this_row, span, style);
    
      prev_row = this_row;
    }
  output_grid_lines(grid, prev_row, NULL, span);
}

/* end of ascii.c */
