/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#include	<sys/types.h>
#include	"machine/include.h"
#include	<string.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	"ppm_error.h"
#include	"ppm_types.h"
#include	"ppmlib_types.h"

#define BUF_LEN	100

int cnt;

int
read_char(char ** ptr,PPM_INFO * pi)
{
	for ( ; ; ) {
		if ( read(pi->pi_fd,*ptr,1) <= 0 )
			return E_UNIX;
		switch ( **ptr ) {
		case ' ':
		case '\t':
		case '\n':
		case '\r':
			(*ptr) ++;
			return E_OK;
		default:
			(*ptr) ++;
		}
	}
}

int
read_space(char ** ptr,PPM_INFO * pi)
{
	for ( ; ; ) {
		if ( read(pi->pi_fd,*ptr,1) <= 0 )
			return E_UNIX;
		switch ( **ptr ) {
		case ' ':
		case '\t':
		case '\n':
		case '\r':
			(*ptr) ++;
		default:
			(*ptr) ++;
			return E_OK;
		}
	}
}

int
read_header(PPM_INFO * pi)
{
char buffer[BUF_LEN];
char * ptr;
int er;
int i;
	ptr = &buffer[0];
	lseek(pi->pi_fd,SEEK_SET,0);
	er = read_char(&ptr,pi);
	if ( er < 0 )
		return er;
	er = read_space(&ptr,pi);
	if ( er < 0 )
		return er;
	er = read_char(&ptr,pi);
	if ( er < 0 )
		return er;
	er = read_space(&ptr,pi);
	if ( er < 0 )
		return er;
	er = read_char(&ptr,pi);
	if ( er < 0 )
		return er;
	if ( memcmp(buffer,"P4",2) == 0 ) {
		pi->pi_offset = ptr - &buffer[0];
		*ptr = 0;
		er = sscanf(buffer,"%s %i %i\n",
			pi->pi_type,
			&pi->pi_width,
			&pi->pi_height);
		if ( er != 3 )
			return E_UNIX;
		pi->pi_max = 1;
		goto next;
	}
	er = read_space(&ptr,pi);
	if ( er < 0 )
		return er;
	er = read_char(&ptr,pi);
	if ( er < 0 )
		return er;
	pi->pi_offset = ptr - &buffer[0];
	*ptr = 0;
	er = sscanf(buffer,"%s %i %i %i\n",
		pi->pi_type,
		&pi->pi_width,
		&pi->pi_height,
		&pi->pi_max);
	if ( er != 4 )
		return E_UNIX;
next:
	for ( i = 0 ; i < CACHE_SIZE ; i ++ ){
		pi->pi_cache[i].pc_h = 0;
		if ( pi->pi_cache[i].pc_line )
			pi->pi_cache[i].pc_line = 0;
	}
	pi->pi_write = 0;
	pi->pi_write_offset = 0;
	return E_OK;
}

void
close_ppm(PPM_INFO * p)
{
	if ( p->pi_write ) {
		lseek(p->pi_fd,p->pi_write_offset,SEEK_SET);
		write(p->pi_fd,p->pi_write,p->pi_width*3);
		free(p->pi_write);
		p->pi_write = 0;
	}
	close(p->pi_fd);
}

void
refresh(PPM_INFO * p,int i)
{
PPM_CACHE c1,c2;
int j;
	c1 = p->pi_cache[i];
	for ( j = 0 ; j < i ; j ++ ) {
		c2 = p->pi_cache[j];
		p->pi_cache[j] = c1;
		c1 = c2;
	}
	p->pi_cache[i] = c1;
}


unsigned char *
get_pixel(PPM_INFO * p,int w,int h)
{
int i;
	for ( i = 0 ; i < CACHE_SIZE ; i ++ ) {
		if ( p->pi_cache[i].pc_line &&
				p->pi_cache[i].pc_h == h ) {
			refresh(p,i);
			return &p->pi_cache[i].pc_line[w*3];
		}
	}
	return 0;
}

unsigned char *
new_line(PPM_INFO * p,int h)
{
PPM_CACHE c1;
int i,j;
	i = CACHE_SIZE - 1;
	if ( p->pi_cache[i].pc_line ) {
		free(p->pi_cache[i].pc_line);
		p->pi_cache[i].pc_line = 0;
		p->pi_cache[i].pc_h = 0;
	}
	p->pi_cache[i].pc_line = malloc(p->pi_width*3);
	p->pi_cache[i].pc_h = h;
	refresh(p,i);
	return p->pi_cache[0].pc_line;
}

