/*
 *  TEX Device Driver  ver 2.02-
 *  copyright(c) 1988,1989 by TSG, 1990-93 by SHIMA
 *
 *  raster.c : functions for raster-buffer
 *	very slightly modified against warnings by Oh-Yeah? 25 May 1992
 *  modified to use EMS by SHIMA 13 Dec 1992
 *  added raster_buf_realloc() by Yakumo Nov. 1992
 */

#include <stdio.h>
#include <mem.h>
#include "dd.h"
#include "buffer.h"
#include "err.h"
#if defined(TURBOC) || defined(MSC)
#ifndef _DEF_DOS_H_
#include <dos.h>
#define _DEF_DOS_H_
#endif
#endif

#ifndef	NEMS
int copy_to_page(uint, uint, uint, long);
int set_ems(int page);
#endif

int r_b_f_count;
uint num_char;
CHAR_INFO *char_info_ptr;	/* current char_info */

static void raster_buf_flush(void)
	/*  _raster_buf のフラッシュ．char_info-list をはずす．
     */
{
	FONT_INFO *font;
	int i;

	ENTER("raster_buf_flush");

	for (font = first_font_info; font; font = font->next_font) {
		for (i = 0; i < CHAR_ROOT; i++)
			font->char_info[i] = NULL;
	}
#ifndef	NEMS
	raster_buf_pointer->ems_bank = -1;
	if( raster_buf_pointer->size > 0 )
		raster_buf_pointer->current = raster_buf_pointer->start;
	else{
		set_ems( raster_buf_pointer->ems_bank = raster_buf_pointer->ems_top );
		raster_buf_pointer->current = raster_buf_pointer->ems_start;
	}
#else
	raster_buf_pointer->current = raster_buf_pointer->start;
#endif
	r_b_f_count++;
	END();
}

void save_char_info(void)
{
	BUFFER *dst;

	dst = raster_buf_pointer->start;

	movedata(FP_SEG(char_info_ptr), FP_OFF(char_info_ptr),
			 FP_SEG(dst), FP_OFF(dst),
			 sizeof(CHAR_INFO));

	char_info_ptr = (CHAR_INFO *)dst;
	(HUGE_BUF *)raster_buf_pointer->current += sizeof(CHAR_INFO);
}

void cut_raster(uint size)
{
	(HUGE_BUF *)raster_buf_pointer->current -= size;
}

void raster_buf_alloc(PREAMBLE **preamble_ptr, long size)
	/*  allocate raster-size of the character from raster_buf.
     *   when no buffer's left, copy preamble to the top of preamble_buf
     *  and then flush char_info_list
     */
{
	PREAMBLE *preamble;

	ENTER("raster_buf_alloc");

	preamble = *preamble_ptr;
#ifndef	NEMS
resume:
	if( raster_buf_pointer->ems_bank >= 0 ){
		set_ems( raster_buf_pointer->ems_bank );
		if ((HUGE_BUF *)raster_buf_pointer->ems_end -
		  (HUGE_BUF *)raster_buf_pointer->current <= (long)size){
			if( (raster_buf_pointer->ems_bank +=4 )
			  < raster_buf_pointer->ems_last ){
				copy_to_page( (uint)(
					(HUGE_BUF*)char_info_ptr - 
					(HUGE_BUF*)raster_buf_pointer->ems_start
					),
				  raster_buf_pointer->ems_bank, 0,
				  (long)sizeof(CHAR_INFO) );
				set_ems( raster_buf_pointer->ems_bank );
rsm:			char_info_ptr = (CHAR_INFO *)raster_buf_pointer->ems_start;
				raster_buf_pointer->current = raster_buf_pointer->ems_start;
rsm0:			(HUGE_BUF *)raster_buf_pointer->current
					+= sizeof(CHAR_INFO);
rsm1:			*preamble_ptr = preamble = &(char_info_ptr->pre);
				goto resume;
			}else{
				if( size >= 0xffffL - sizeof( CHAR_INFO )
				  && size + sizeof( CHAR_INFO ) >= raster_buf_pointer->size ){
err:				error( NO_MEMORY, "Too big font" );
				}
				copy_to_page( (uint)(
					(HUGE_BUF*)char_info_ptr - 
					(HUGE_BUF*)raster_buf_pointer->ems_start
					),
				  raster_buf_pointer->ems_top, 0, (long)sizeof(CHAR_INFO) );
				set_ems( raster_buf_pointer->ems_top );
				char_info_ptr = (CHAR_INFO *)raster_buf_pointer->ems_start;
				raster_buf_flush();
				if( raster_buf_pointer->ems_bank >= 0 ) goto rsm0;
				save_char_info();
				goto rsm1;
			}
		}
	}else{
		if ((HUGE_BUF *)raster_buf_pointer->end -
			(HUGE_BUF *)raster_buf_pointer->current <= size) {
			if( raster_buf_pointer->ems_last > 0 ){
				set_ems( raster_buf_pointer->ems_bank
				  = raster_buf_pointer->ems_top );
				movedata(FP_SEG(char_info_ptr), FP_OFF(char_info_ptr),
				  FP_SEG( raster_buf_pointer->ems_start ),
				  FP_OFF( raster_buf_pointer->ems_start ),
				  (long)sizeof(CHAR_INFO) );
				goto rsm;
			}else{
				if( size + sizeof( CHAR_INFO ) >= raster_buf_pointer->size )
					goto err;
				raster_buf_flush();
				save_char_info();
				goto rsm1;
			}
		}
	}
#else
	preamble->raster = raster_buf_pointer->current;
	if ((HUGE_BUF *)raster_buf_pointer->end -
		(HUGE_BUF *)raster_buf_pointer->current <= size) {
		raster_buf_flush();
		save_char_info();
		*preamble_ptr = preamble = &(char_info_ptr->pre);
	}
#endif
	preamble->raster = raster_buf_pointer->current;
	raster_buf_pointer->current += size;
 	END();
}

#ifdef VFD
void raster_buf_realloc(PREAMBLE **preamble_ptr)
{
	ENTER("raster_buf_realloc");

	raster_buf_pointer->current = (*preamble_ptr)->raster;
	raster_buf_alloc(preamble_ptr,
			(long)(*preamble_ptr)->byte_width * (*preamble_ptr)->height);
	END();
}

#endif

PREAMBLE *
    alloc_preamble(void)
{
	ENTER("alloc_preamble");

resume:
	char_info_ptr = (CHAR_INFO *)raster_buf_pointer->current;
	(HUGE_BUF *)raster_buf_pointer->current += sizeof(CHAR_INFO);

#ifndef	NEMS
	if( raster_buf_pointer->ems_bank >= 0 ){
		set_ems( raster_buf_pointer->ems_bank );
		if( (HUGE_BUF *)raster_buf_pointer->current >=
		    (HUGE_BUF *)raster_buf_pointer->ems_end ){
			if( (raster_buf_pointer->ems_bank +=4 )
				< raster_buf_pointer->ems_last ){
ems:			set_ems( raster_buf_pointer->ems_bank );
				raster_buf_pointer->current = raster_buf_pointer->ems_start;
				goto resume;
			}
			else{
flush:			raster_buf_flush();
				goto resume;
			}
		}
	}
	else{
		if (is_end_of(raster_buf_pointer)){
			if( raster_buf_pointer->ems_last == 0 )	goto flush;
			raster_buf_pointer->ems_bank = raster_buf_pointer->ems_top;
			goto ems;
		}
	}
#else
	if (is_end_of(raster_buf_pointer)) {
		raster_buf_flush();
		goto resume;
	}
#endif
	num_char++;
	RETURN(&(char_info_ptr->pre));
}

/* end of file : raster.c */
