#ifdef __arm
#define FAKE_UNIX 1
#endif
/*
 * grid.c	This file defines the grid interface for 1down.
 *
 * Copyright (C) 1990 Rob Mayoff.
 */

#include <stdio.h>
#include <stdlib.h>

#ifdef FAKE_UNIX
/* Fake the calls for now, rewrite avoiding unix code later... */
extern int open(const char*, int, ...);
extern int close(int);
extern long lseek(int, long, int);
extern int read(int fd, char *buff, int size);

#define fileno(p)       ((__fd = (int)(p)) == NULL ? -1 : __fd)
/* Don't evaluate twice. The -1 trick is useful if you forget the
   return code in various of the emulated functions */

/* Note - unix files are always binary */
#define O_RDONLY 1
#define O_WRONLY 2
#define O_RDWR (O_RDONLY|O_WRONLY)

#define L_SET SEEK_SET
#define L_CUR SEEK_CUR
#define L_END SEEK_END

int __fd;

int
open(const char* path, int oflag, .../*mode*/)
{
char *acc[4] = { "", "rb", "wb", "rwb" };
int fd;
/*
    path points to a file.
    oflag may include O_RDONLY | O_WRONLY | O_APPEND | O_CREAT | O_TRUNC
    returns int fd, else -1
 */
  /* Just looking at rd/wr for this quick hack... */
  fd = fileno(fopen(path, acc[oflag&3]));
  return(fd);
}

int
close(int fd)
{
/*
    returns 0 if successful, -1 if fails
 */
  fclose((FILE *)fd);
  return(0);
}

long
lseek(int fd, long offset, int whence)
{
  return(fseek((FILE *)fd, offset, whence) == 0 ? 0 : -1);
}


int read(int fd, char *buff, int size)
{
size_t count;
  /*fprintf(stderr, "Read %d bytes from file %8x to address %8x\n", size, fd, (int)buff);*/
  count = fread(buff, (size_t)1, (size_t)size, (FILE *)fd);
  if (count == 0) {
    fprintf(stderr, "No bytes read - returning 0\n");
    return(0); /* I *think* this is what it should do! */
  }
  if (ferror((FILE *)fd)) {
    fprintf(stderr, "File error\n");
    return(-1); /* I *think* this is what it should do! */
  }
  if (count != size) {
    fprintf(stderr, "Wanted %d bytes - got %d\n", size, count);
  } else {
    /*fprintf(stderr, "Info: %d bytes\n", count);*/
  }
  return(count);
}

#else

#include <sys/types.h>
#include <sys/file.h>
#include <fcntl.h>

#endif

#include "grid.h"
#include "misc.h"

int		G_WIDTH, G_HEIGHT;
grid_t		grid;
int		numAcross, numDown;
wordSpace_t	across[MAXWORDS], down[MAXWORDS]; /* Not what you thought it did... */
grid_t		acrossID, downID;
stack_ty	stack;
int		stackTop;

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

void	initGrid(char *fn)
{
  int x, y, t, i=0, flag;
  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=(int)lseek(fd, i+1L, L_SET); /* Loss of precision rc is int, lseek is long */
  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++;
    }
  }
}
