/*
 *  TEX Device Driver  ver 2.02-
 *  (c) copyright 1988, 1989 by TSG, 1990-93 by SHIMA
 *
 *  buffer.c :
 *  Apr. 15, 1989 : first edition
 *  Jul.  1, 1989 : 2nd edition
 *                      programed by T.IWAI
 *	modfied for non PC-9801 machines by sempa 1992
 *	very slightly modified against warnings by Oh-Yeah? 25 May 1992
 *  support EMS by SHIMA,  Dec 1992
 */

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

#ifdef  UNIX
#include <sys/stat.h>
#include <unistd.h>
#else
#include <sys\stat.h>
#include <io.h>
#ifdef MSVC
#include "msvcdir.h"
#include <memory.h>
#else
#include <dir.h>
#include <mem.h>
#endif
#endif

#include "dd.h"
#include "err.h"
#include "buffer.h"
#include "vfont.h"
#include "option.h"

#ifdef WIN32
#define	BUFMALLOC(n)	marea(n)
#else
#define BUFMALLOC(n)    malloc(n)
#endif

/* loadpk.c */
int file_read(int, BUFFER *, int);
int resume_fontfile(int);

/* vfont.c */
V_JFM *get_vjfm(int);

#ifdef	VIRTUALFONT
void local_pkbuf_flush(FONT_INFO *);
void local_font_flush(FONT_INFO *);
void vir_cash_flush(void);
#endif
extern V_FONT *vfont[];
extern int f_init;
extern int f_path_cash;

#ifndef NO_NTTRPL
extern BOOL ntt_subst;
#endif

#ifndef	WIN32
static uchar *heap_buffer;
#endif

extern uint num_char;
void buffer_init(void);
void pk_buf_flush(void);
void font_flush(void);
void *marea(unsigned int);
FONT_INFO *font_info_alloc(void);
char *dup_string(char *);
void clear_buf(BUF_INFO *);

static void buffer_alloc(BUF_INFO *, BUFFER *(*)(long size));

#define omit_divide(a,b) ( ( (a)/(b) ) * (b) )
/* ｂで割り切れるようにする（端数切捨て）*/

#ifndef	WIN32
uchar *get_near_work(uint size)
{
	Free0(heap_buffer);
	if (size != 0){
		heap_buffer = (uchar *)marea(size);		/* get from near heap */
		return(heap_buffer);
	}
	return(heap_buffer = NULL);
}
#endif

BUFFER *get_work(uint size)
{
	if (size <= COMMON_SIZE)
		return(common_work);				/* common_work[] in near area */
	return(get_near_work(size));			/* get from near heap */
}

static BUFFER *
	bufmalloc(long size)
	/* BUFFER用のメモリー確保
	 */
{
	return ((BUFFER *)BUFMALLOC(size));
}


static void buffer_alloc(BUF_INFO *buf, BUFFER *(*alloc) (long size))
	/* size分のbufferを確保し，セットする．
	 */
{
	if (buf->size == 0)
		return;
	Free0(buf->start);
	if ((buf->start = (*alloc) (buf->size)) == NULL)
		error(NO_MEMORY,
#ifdef	JAPANESE
			  "バッファ領域の不足"
#else
			  "Cannot get Buffer"
#endif
			);
	buf->end = buf->start + (uint)buf->size;
	buf->current = buf->start;
}

void buffer_init(void)
	/*  バッファ領域の確保．この前に，各BUF_INFOのsizeは，設定
	 *  されていること．
	 */
{
	if(f_init & INIT_R_BUF)
		buffer_alloc(raster_buf_pointer, bufmalloc);
	if(f_init & INIT_F_BUF)
		buffer_alloc(pk_buf_pointer, bufmalloc);
	if(f_init & INIT_B_BUF)
		buffer_alloc(bitmap_buf_pointer, bufmalloc);
}

void pk_buf_flush(void)
	/*  pk_buf　のフラッシュ．
	 */
{
	FONT_INFO *font;

	for (font = first_font_info; font; font = font->next_font) {
		if(font->name != NULL && font->name[0] != '<')
			font->pk = NULL;
#ifdef	VIRTUALFONT
		if (font->font_type == VIRTUAL_FONT)
			local_pkbuf_flush(font->ext.local_font);
#endif
	}
	pk_buf_pointer->current = pk_buf_pointer->start;
	pk_buf_pointer->flush++;
}

void font_flush(void)
{
	FONT_INFO *font, *nfont;
#ifndef NO_NTTRPL
	FONT_INFO *dfont;
#endif

	raster_buf_pointer->current = raster_buf_pointer->start;
	raster_buf_pointer->flush++;
	pk_buf_pointer->current = pk_buf_pointer->start;
	pk_buf_pointer->flush++;

	if(first_font_info == NULL)
		return;
	resume_fontfile(0x7000);
	for (font = first_font_info; font; ){
		nfont = font->next_font;
		Free0(font->name);
		switch(font->font_type){
		  case(JIS_FONT):
		  case(JIS_PK):
		  case(TT_FONT):
		  case(ZS_FONT):
#ifdef	USE_WINFONT
		  case(WINJTT_FONT):
#endif
		  case(JIS_PKH):
		  case(GAIJI):
		  case(JLBP):
			if(font->ext.kdir != NULL){
				Free0(font->ext.kdir->name);
				Free(font->ext.kdir);
#ifndef NO_NTTRPL
				if (font->code_offset >= 0){
					for(dfont=nfont; dfont; dfont=dfont->next_font){
						if (dfont->code_offset >= 0
						  && dfont->family_code == font->family_code)
							dfont->ext.kdir = NULL;
					}
				}
#endif
			}
			font->ext.kdir = NULL;
			break;

#ifdef	USE_ETF
		  case(ETF_FONT):
			if(font->etf_type == VIRTUAL_FONT){
				local_font_flush(font->ext.local_font);
				font->ext.local_font = NULL;
			}else if(font->etf_type == TT_FONT)
				Free(font->ext.kdir);
			break;
#endif
#ifdef	VIRTUALFONT
		  case(VIRTUAL_FONT):
			local_font_flush(font->ext.local_font);
			font->ext.local_font = NULL;
			Free0(font->vjfm);
			break;
#endif
		}
		Free(font);
		font = nfont;
		if(f_path_cash > 1)
			f_path_cash = 1;
	}
	num_char = 0;
#ifdef	USE_WINFONT
	check_wintt(NULL);
#endif
	resume_fontfile(0);
	first_font_info = NULL;
#ifdef	VIRTUAL_FONT
	vir_cash_flush();
#endif
}

FONT_INFO *
	font_info_alloc(void)
	/*  １つ分のフォントバッファを確保 */
{
	FONT_INFO *font;

	ENTER("font_info_alloc");

	if ((font = (FONT_INFO *)bufmalloc(sizeof(FONT_INFO))) == NULL)
			error(NO_MEMORY,
#ifdef	JAPANESE
				  "フォントバッファ領域の不足"
#else
				  "Cannot get FONT Buffer"
#endif
		);

	RETURN(font);
}

#ifndef	WIN32
void *
	marea(unsigned int size)
	/* エラーチェック付きmalloc */
{
	char *ptr;

	ENTER("marea");
	if (size == 0)
		size = 1;
rep:
	if ((ptr = (char *)malloc(size)) == NULL){
		if (heap_buffer != NULL){
			get_near_work(0);
			goto rep;
		}
		error(NO_MEMORY,
# ifdef	JAPANESE
			  "ヒープエリアの不足"
# else
			  "Not enough heap area"
# endif
			);
	}
	RETURN(ptr);
}

char *
	dup_string(char *src)
	/* エラーチェック付きstrdup */
{
	char *dst;

	if (src == NULL)
		returen NULL;
	if ((dst = strdup(src)) == NULL)
		error(NO_MEMORY,
# ifdef	JAPANESE
			  "ヒープエリアの不足"
# else
			  "Not enough heap area"
# endif
	);
		return dst;
}
#endif

void clear_buf(BUF_INFO *buf)
{
	memset(buf->start, 0, buf->size);
}


unsigned char *PageDup(void)
{
	unsigned char *buf;

	if((buf = (char*)marea(bitmap_buf_pointer->size)) != NULL){
		memcpy(buf, bitmap_buf_pointer->start, bitmap_buf_pointer->size);
	}
	return buf;
}

/* end of file : buffer.c */
