/*
 * grid.c	This file defines the grid interface for 1down.
 *
 * Copyright (C) 1990 Rob Mayoff.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>
#include "grid.h"
#include "misc.h"

int		G_WIDTH, G_HEIGHT;
grid_t		grid;
int		numAcross, numDown;
wordSpace_t	across[], down[];
grid_t		acrossID, downID;
stack_t		stack;
int		stackTop;

int	compare(wordSpace_t *a, wordSpace_t *b)
{
  return b->length-a->length;
}

void	initGrid(char *fn)
{
  register	int x, y, t, i=0, flag;
  register	int fd, rc;
  char		str[100];

  for(x=0; x<G_REAL_WIDTH-1; x++)
    for(y=0; y<G_REAL_HEIGHT; y++)
      grid[y][x]=BLOCK;
  for(y=0; y<G_REAL_HEIGHT; y++)
    grid[y][G_REAL_WIDTH-1]='\0';

  fd=open(fn, O_RDONLY);
  panicif(fd<0, fn);
  rc=read(fd, str, 100);
  panicif(rc<0, fn);
  sscanf(str, "%d %d", &G_WIDTH, &G_HEIGHT);
  panicif(G_WIDTH<3 || G_WIDTH>G_MAX_WIDTH
       || G_HEIGHT<3 || G_HEIGHT>G_MAX_HEIGHT, "Bad grid size");
  for(i=0; str[i]!='\n'; i++)
    ;
  rc=lseek(fd, i+1, L_SET);
  panicif(rc<0, fn);
  for(y=1; y<=G_HEIGHT; y++)
  {
    i=read(fd, grid[y]+1, G_WIDTH+1);
    panicif(i<=0, fn);
    grid[y][G_WIDTH+1]=BLOCK;
    grid[y][G_WIDTH+2]='\0';
  }
  close(fd);
  grid[0][G_WIDTH+2]='\0';
  grid[G_HEIGHT+1][G_WIDTH+2]='\0';

  for(y=1; y<=G_HEIGHT; y++)
  {
    for(x=1; x<=G_WIDTH; x++)
    {
      /* If the space is blank, it might be the beginning of a word-space. */
      if(grid[y][x]==SPACE)
      {
	flag=0;
	/* If it is right of a block, it is. */
	if(grid[y][x-1]==BLOCK)
	{
	  /* Find the length. */
	  for(t=1; grid[y][x+t]!=BLOCK; t++)
	    ;
	  if(t==2 || t>20)
	  {
	    fprintf(stderr,
	      "Invalid across word-space length %d at (%d,%d).\n",
	      t, x, y);
	    exit(1);
	  }
	  if(t>1)
	  {
	    across[numAcross].x=x;
	    across[numAcross].y=y;
	    across[numAcross].length=t;
	    across[numAcross].number=++i;
	    numAcross++;
	    flag=1;
	  }
	}
	/* If it is right below a block, it is. */
	if(grid[y-1][x]==BLOCK)
	{
	  /* Find the length. */
	  for(t=1; grid[y+t][x]!=BLOCK; t++)
	    ;
	  if(t==2 || t>20)
	  {
	    fprintf(stderr, "Invalid down word-space length %d at (%d,%d).\n",
	      t, x, y);
	    exit(1);
	  }
	  if(t>1)
	  {
	    down[numDown].x=x;
	    down[numDown].y=y;
	    down[numDown].length=t;
	    if(flag)
	      down[numDown].number=i;
	    else
	      down[numDown].number=++i;
	    numDown++;
	  }
	}
      }
    }
  }

  /* Build the acrossID and downID databases. */
  for(i=0; i<numAcross; i++)
  {
    x=across[i].x; y=across[i].y;
    for(t=0; t<across[i].length; t++)
      acrossID[y][x+t]=i;
  }
  for(i=0; i<numDown; i++)
  {
    x=down[i].x; y=down[i].y;
    for(t=0; t<down[i].length; t++)
      downID[y+t][x]=i;
  }

  for(i=1; i<=G_WIDTH; i++)
  {
    for(y=1; y<i; y++)
    {
      if(grid[y][i]!=SPACE)
	continue;
      stack[stackTop].x=i;
      stack[stackTop].y=y;
      stack[stackTop].acrossID=acrossID[y][i];
      stack[stackTop].downID=downID[y][i];
      stackTop++;
    }
    for(x=1; x<=i; x++)
    {
      if(grid[i][x]!=SPACE)
	continue;
      stack[stackTop].x=x;
      stack[stackTop].y=i;
      stack[stackTop].acrossID=acrossID[i][x];
      stack[stackTop].downID=downID[i][x];
      stackTop++;
    }
  }
}
