/* Functions: ps_outline, outlinefile
**
** Author: Paul W. Carlson	May 1992
*/

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <grass/gis.h>
#include "ps_info.h"
#include "local_proto.h"

extern int verbose;
static int k, col, row, top, bottom;
static void *tl, *tr, *bl, *br;
static void *buffer[2];
static int scan_length;
static int draw_boundaries(void);
static int read_next(void);
double e1, e2, e3, n1, n2, n3;
/*
  e1 e2 e3
   *--*--* n1
   |  |  |
   *--*--* n2
   |  |  |
   *--*--* n3
*/
/* the ps_outline function creates a vector file called "tmp.outl" in
** the current location.  This file is removed after it has been
** plotted.
*/

extern RASTER_MAP_TYPE o_open_file();
static RASTER_MAP_TYPE map_type;

int 
ps_outline (void)
{
    /* let user know what's happenning */
    if (verbose > 1)
    {
        fprintf (stdout,"PS-PAINT: outlining areas in raster file <%s in %s> ...",
	    PS.cell_name, PS.cell_mapset);
        fflush(stdout);
    }
    /* set the outline color and width */
    set_rgb_color(PS.outline_color);
    set_line_width(PS.outline_width );

    /* create temporary vector file containing outlines */
    o_io_init();
    map_type = o_open_file(PS.cell_name);
    draw_outline();
    o_close_file();

    if (verbose > 1) fprintf (stdout,"\n");

    return 0;
}


/* The outlinefile function is just slightly modified p.map code. */
#define KEY(x) (strcmp(key,x)==0)
static char *help[] =
{
    "color  color",
    "width  #",
    ""
};
int 
read_outline(void)
{	
    char buf[1024];
    char ch, *key, *data;
    int color;

    PS.outline_width = 1.;
    color = BLACK;
    while (input(2, buf, help))
    {
	if (!key_data(buf, &key, &data)) continue;
	if (KEY("color"))
	{
	    color = get_color_number(data);
	    if (color < 0)
	    {
		color = BLACK;
		error(key, data, "illegal color request");
	    }
	    continue;
	}
	if (KEY("width"))
	{
	    PS.outline_width = -1.;
	    ch = ' ';
	    if(sscanf(data, "%lf%c", &(PS.outline_width), &ch) < 1 
	       || PS.outline_width < 0.)
	    {
	        PS.outline_width = 1.;
		error(key, data, "illegal width request");
	    }
	    if(ch=='i') PS.outline_width = PS.outline_width/72.;
	    continue;
	}
	error(key, data, "illegal outline sub-request");
	error(key, data, "illegal outline sub-request");
    }
    PS.outline_color = color;
    PS.do_outline = 1;

    return 0;
}


/* draw_outline - draw boundaries of polygons in file */

int 
draw_outline (void)
{
  int raster_size;
  row = col = top = 0;			/* get started for read of first */
  bottom = 1;				/*   line from cell file */
  scan_length = read_next();
  k = 0;
  raster_size = G_raster_size(map_type);
  while (read_next())			/* read rest of file, one row at */
  {					/*   a time */
     n1 = G_row_to_northing((double)row -1., &(PS.w));
     n2 = G_row_to_northing((double)row, &(PS.w));
     n3 = G_row_to_northing((double)row + 1., &(PS.w));

    for (col = 0; col < scan_length - 1; col++)
    {
      e1 = G_col_to_easting((double)col - 1., &(PS.w));
      e2 = G_col_to_easting((double)col, &(PS.w));
      e3 = G_col_to_easting((double)col + 1., &(PS.w));
      tl = G_incr_void_ptr(buffer[top], col * raster_size);	
      /* top left in window */
      tr = G_incr_void_ptr(buffer[top], (col+1) * raster_size);	
      /* top right in window */
      bl = G_incr_void_ptr(buffer[bottom], col * raster_size);	
      /* bottom left in window */
      br = G_incr_void_ptr(buffer[bottom], (col+1) * raster_size);	
      /* bottom right in window */
      draw_boundaries();
      if (k==3) k = 0;
    }
    row++;
  }

    return 0;
}					/* draw_outlines */


static int 
draw_boundaries (void)
{
  if( G_raster_cmp(bl, br, map_type) != 0) draw_bot();
  if( G_raster_cmp(tr, br, map_type) != 0) draw_rite();

    return 0;
}						/* draw_boundaries */

/* read_next - read another line from input file */

static int read_next (void)
{
  int n;

  top = bottom++;			/* switch top and bottom, */
  bottom = 1 & bottom;			/*   which are always 0 or 1 */
  n = o_read_row(buffer[bottom]);
  return(n);
}

/* alloc_bufs - allocate buffers we will need for storing cell file */
/* data, pointers to extracted lines, area number information */

int o_alloc_bufs (int ncols, int size)
{
  buffer[0] = (void *) G_calloc(ncols, size);
  buffer[1] = (void *) G_calloc(ncols, size);

  return 0;
}

int 
draw_top (void)
/*    *--*--*    */
/*    |  |  |    */
/*    *  |  *    */
/*    |     |    */
/*    *--*--*    */
{
   start_line(e2, n2);
   sec_draw = 0;
   G_plot_line(e2, n2, e2, n1);
   if(++k==3) fprintf(PS.fp," D\n");
   else fprintf(PS.fp, " D ");

  return 0;
}

int 
draw_rite (void)
/*    *--*--*    */
/*    |     |    */
/*    *  ---*    */
/*    |     |    */
/*    *--*--*    */
{
   start_line(e2, n2);
   sec_draw = 0;
   G_plot_line(e2, n2, e3, n2);
   if(++k==3) fprintf(PS.fp," D\n");
   else fprintf(PS.fp, " D ");

  return 0;
}

int 
draw_left (void)
/*    *--*--*    */
/*    |     |    */
/*    *---  *    */
/*    |     |    */
/*    *--*--*    */
{
   start_line(e2, n2);
   sec_draw = 0;
   G_plot_line(e2, n2, e1, n2);
   if(++k==3) fprintf(PS.fp," D\n");
   else fprintf(PS.fp, " D ");

  return 0;
}

int 
draw_bot (void)
/*    *--*--*    */
/*    |     |    */
/*    *  |  *    */
/*    |  |  |    */
/*    *--*--*    */
{
   start_line(e2, n2);
   sec_draw = 0;
   G_plot_line(e2, n2, e2, n3);
   if(++k==3) fprintf(PS.fp," D\n");
   else fprintf(PS.fp, " D ");

  return 0;
}
