#include <stdio.h>
#ifndef	WIN32
#define	Free(x)	free(x)
#define	NOT_WIN32 1
#endif
#include <windows.h>
#include <winspool.h>
#include "root.h"
#include "err.h"
#include "inter.h"

void *marea(unsigned int);
FILE *fopenf(char *, char *);

char printer_name[256];
static HANDLE printer;
BOOL f_rawfile;
BOOL f_rawerr;
BOOL f_rawwait;

#define	BUF_UNIT	0x20000

static FILE *f_rawout;
static int buf_pt;
static int buf_size;
static char *raw_buf;

#define	TEST	0


void AbortRawPrint(void)
{
	Free0(raw_buf);
	raw_buf = NULL;
	if(f_rawout != NULL){
		fclose(f_rawout);
		Free(f_rawout);
		f_rawout = NULL;
		f_rawfile = 0;
	}
	if(printer){
		AbortPrinter(printer);
		printer = NULL;
	}
	f_rawerr = TRUE;
}

void Win32cPrtinterInit(int prt_no)
{
#if	TEST
	error(14, "Initialize RawPrt");
#else
	DOC_INFO_1 di;
	char *p;

	f_rawerr = FALSE;
	Free0(raw_buf);
	raw_buf = NULL;
#ifndef	NOT_WIN32
	if(f_rawfile){
		p = QueryPrnName();
		ToDviDir();
		if(p == NULL || (f_rawout = fopenf(p, "wb")) == NULL)
			AbortRawPrint();
		return;
	}
#endif
  	if (prt_no <= 0) {	/* default printer */
//		GetProfileString("windows", "device", "", printer_name, 256);
//		if ( (p = strchr(printer_name, ',')) != NULL )
//		    *p = '\0';
		GetLPTName(printer_name, 0);
	} else
		sprintf(printer_name, "LPT%d", prt_no);

    if (!OpenPrinter(printer_name, &printer, NULL)) {
		printer = NULL;
		error(BAD_SYSTEM, 
			"OpenPrinter() failed for \042%s\042, error code = %d", 
			printer_name, GetLastError());
			AbortRawPrint();
			return;
	}
	/* from here until ClosePrinter, should AbortPrinter on error */
	di.pDocName = "dviprt";
	di.pOutputFile = NULL;
	di.pDatatype = "RAW";
	if (!StartDocPrinter(printer, 1, (LPBYTE)&di)) {
		AbortRawPrint();
		error(BAD_SYSTEM, 
			"StartDocPrinter() failed for \042%s\042, error code = %d", 
			printer_name, GetLastError());
    }
#endif
	return;
}

void Win32cPrtinterEnd()
{
#if	TEST
	error(14, "Close RawPrt");
#else
	Free0(raw_buf);
	raw_buf = NULL;
	if (!printer){
		if(f_rawout){
			fclose(f_rawout);
			Free(f_rawout);
			f_rawout = NULL;
		}
		return;
	}
	if (!EndDocPrinter(printer)) {
		AbortRawPrint();
		error(BAD_SYSTEM, 
			"EndDocPrinter() failed for \042%s\042, error code = %d", 
			printer_name, GetLastError());
	}
    else if (!ClosePrinter(printer)) {
		error(BAD_SYSTEM, 
			"CloseDocPrinter() failed for \042%s\042, error code = %d", 
			printer_name, GetLastError());
		AbortRawPrint();
	}
	printer = NULL;
#endif
}

void PrBufFlush(void)
{
	DWORD written;

	if(!raw_buf || f_rawerr)
		return;
	if (!printer){
		if(f_rawout)
			fwrite(raw_buf, buf_pt, 1, f_rawout);
	}
	else if (!WritePrinter(printer, (LPVOID)raw_buf, buf_pt, &written)) {
	    AbortPrinter(printer);
		error(BAD_SYSTEM, 
			"WritePrinter() failed for \042%s\042, error code = %d", 
			printer_name, GetLastError());
		f_rawerr = TRUE;
	}
	Free(raw_buf);
	raw_buf = NULL;
}

void PrFlush(char *pr_buf, int pr_buf_len)
{
	char *bf;
	DWORD written;

#if	TEST
	error(13, "Raw %d byte", pr_buf_len);
#else

	if(!pr_buf_len)
		return;

	if (f_rawwait){
		if(!raw_buf){
			raw_buf = (char*)marea( buf_size = BUF_UNIT );
			buf_pt = 0;
		}
		if(buf_pt + pr_buf_len > buf_size){
			bf = (char*)marea( buf_size += BUF_UNIT );
			memmove( bf, raw_buf, buf_pt );
			Free( raw_buf );
			raw_buf = bf;
		}
		memmove( raw_buf + buf_pt, pr_buf, pr_buf_len );
		buf_pt += pr_buf_len;
		return;
	}
	if (!printer){
		if(f_rawout)
			fwrite(pr_buf, pr_buf_len, 1, f_rawout);
		return;
	}
	if (!WritePrinter(printer, (LPVOID)pr_buf, pr_buf_len, &written)) {
	    AbortPrinter(printer);
		error(BAD_SYSTEM, 
			"WritePrinter() failed for \042%s\042, error code = %d", 
			printer_name, GetLastError());
	}
	return;
#endif
}

