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

	hardware.c
	scanner dependend routines

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

#include <stdlib.h>
#include <scanner.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include "Xscan.h"

/*
	Get info about bytes per line (int *bpl) and dots per inch (int *dpi)
*/  
void ScanInfo(int *bpl, int *dotspi)
{
	int fd;
	struct m105_modeinfo_struct mi;

	fd = open("/dev/scan",O_RDONLY);
	if (fd == 0) {
		perror("can not open /dev/scan");
		exit(1);
	}
	if (ioctl(fd,HSIOCGMOD, &mi) != 0) {
		perror("ioctl failed");
		exit(1);
	}
	close(fd);
	bytes_per_line = mi.bpl;
	*bpl = mi.bpl;
	*dotspi = mi.dpi;
}

/*
	Read scannlines from scannerdevice
	This function is a call-back function, started with "XtAppAddInput"
	in function "Scan" found in file scan.c

	This function will be called whenever some bytes come from the 
	scannerdevice
*/

static char *ptr, *line;

void get_line(XtPointer *unused, int fid, XtInputId *id)
{
	int j,k,rd;
	int wi;
	int mask;

	if (bufcnt == 0) {	/* New scannline  */
					/* allocate memory for linebuffer */
				      /* space for 8 lines 			*/
		if ((lines_scanned & 0x7) == 0) {
			for(j = 0; j < 8; j++) {
				line = XtMalloc(bytes_per_line);
				if (line == NULL) {
					fprintf(stderr,"out of memory !!!\n");
					exit(1);
				}
				memset(line,0,bytes_per_line);
				linebuf[lines_scanned + j] = line;
			}
		}
		line = ptr = linebuf[lines_scanned];
		lines_scanned++;
	}

	/* calulate number of bytes to read before line is complete */

	j = bytes_per_line - bufcnt;
	rd = read(fd, line, j);
	bufcnt += rd;
	if (bufcnt < bytes_per_line) return;   /* line is not complete */

	/* show line  (only visible part for performance) */

	bufcnt = 0;
	ptr = &line[slider_x>>3];
	wi = slider_width + 16;
	wi = wi >> 3;
	for(j = 0; j < wi;j++) {
		mask = 0x80;
		for(k = 0; k < 8;k++) {
			if (!(*ptr & mask)) 			 
				XDrawPoint(XtDisplay(DrawArea),DrawPix,DrawGC,
					  (j<<3)+k + slider_x,lines_scanned-1);
			mask = mask >> 1;
		}
		ptr++;
	}

	/* bottom of canvas widget ? */

	if (lines_scanned > (slider_y + slider_height)) { 
		canvas_line += 20;	/* scroll up */
		XawViewportSetCoordinates(Canvas,slider_x,canvas_line);	
	}		
	QRedraw(lines_scanned-1);	
	if (lines_scanned > XscanAppData.MaxScanLines) {
		XtSetSensitive(InputBox, TRUE);
		XtRemoveInput(AppId);
		close(fd);
		pixmap_heigh = lines_scanned;
		cellsize = oldcell;
		scaninprog = FALSE;
		sprintf(ScanLabel,"max scanlines reached !");
		XtVaSetValues(ShowLabel,XtNlabel,ScanLabel, NULL);
		Make();
	}
}
