/**
 *
 *  TEX Device Driver  ver 2.02-   for J3100
 *  copyright(c) 1988,89 by TSG, 1990-93 SHIMA, 1991 sempa
 *
 *  PREVIEWER ver 2.02-
 *  device.c : previewer module
 *             4th edition
 *
 *  modified for AX by akiii. 1991/09/25
 *
 *	modified by sempa 1992
 *
 *	Ver.2.35 page resume supported by SOLITON
 *
 *  Support EMS by SHIMA, Dec 1992
 *
 *  Of course, this module is device-dependent.
**/

#define	TITLE_COMMENT	""

#include <stdio.h>
#include <ctype.h>
#define _DEF_STDIO_H_
#include <dos.h>
#include <mem.h>
#include <alloc.h>
#include <conio.h>
#define _DEF_DOS_H_
#include "dd.h"

#define ONEBYTE		8
#define G_TOP		0xa0000000L
#define	G_SEG		0xa000
#define	G_ID		0xafff0008L
#define	T_ID		0xa0000008L
#define G_WIDTH_B	80
#define G_HEIGHT	480
#define HIGH_MONO	2
#define ON			1
#define OFF			0
#define ESC			0x1b
#define	V_SHIFT		1
#define	CRT_BIOS	0x10
#define	new_width	((f_use_new_size_option)?dim->text_width:s_max_width)
#define	new_height	((f_use_new_size_option)?dim->text_height:s_max_height)

#define GRAM_BUF	uchar far

#ifdef	AX
#define	g_height	G_HEIGHT
#define	g_width_b	G_WIDTH_B
#endif

int f_machine_unique;
const char *const title_comment = TITLE_COMMENT;
extern BOOL f_use_new_size_option;
extern BOOL f_resume;
extern BOOL f_reverse;
extern int num_view;
extern int num_view_buf;
extern int slow_fact;
extern int slow_fact2;
extern int slow_page;
extern int unit_pages;
extern int v_shift0;
extern uint resume_info;
static int v_shift1 = 1;

#define	MAX_VIEW	16

#ifndef	NEMS
extern int system_EMS_end;
int view_EMS_top;
int view_EMS_unit;
int set_ems( int );
#endif

struct VIEW {
	int current;	/* current screen to be saved	*/
	int total;	/* total screen saved			*/
	int page[MAX_VIEW];	/* page numbers for screens		*/
};
static struct VIEW view;

struct SCROLL {
	/* output parameter. send to scroll-functions and other device-output-
     * functions
     */
	uint offset;
	/* skipped bytes due to horizontal scroll */
	uint r_line;
	/* number of lines of the second part of screen */
	int x;
	int y;
	/* the current positioin in bitmap. */
	int gw_act, gh_act;
	/* width and height to output on screen */
	BOOL x_lock, y_lock;
	/* permition to scroll horizontal and vertical direction. */
	HUGE_BUF *mptr;
	/* the current position of bitmap pointer */
	int h_spc, v_spc;
	/* h_spc and v_spc is to put at the center of the screen */

};

typedef enum {
	BackSpace, SpaceKey,	/* PreviousPart, NextPart   */
	Key_P, Key_N,	/* PreviousPage, NextPage   */
	CaridgeReturn,	/* NextPageDirection        */
	EscapeKey,	/* EscapeQuit               */
	Key_Q,	/* Same as above            */
	Key_B,	/* Another Previous Page	*/
	Key_V,	/* View outline				*/
	Key_C,	/* Comressed View			*/
	Key_R,	/* Reverse					*/
	Key_H,	/* HELP 					*/
	HELP,	/* Help key					*/
	Key_M,	/* Move to a page			*/
	Key_G,	/* Same as above			*/
	ArrowDown, ArrowUp, ArrowLeft, ArrowRight,
	ShiftDown, ShiftUp, ShiftLeft, ShiftRight, LoopEnd
} KeyInput;

static unsigned int key_data[] =
{
	0x0008, 0x0020,
	0x0050, 0x004e,
	0x000d,
	0x001b,
	0x0051,
	0x0042,
	0x0056,
	0x0043,
	0x0052,
	0x0048,
	0x4700,
	0x004d,
	0x0047,
	0x5000, 0x4800, 0x4b00, 0x4d00,
	0x50ff, 0x48ff, 0x4bff, 0x4dff,
	0x001b
};

int s_max_width = 118 * 8;
int s_max_height = 118 * 11;
int f_center;

static HUGE_BUF *map_top_ptr;

/* pointer of bitmap buffer */
static PIXEL vmax, hmax, hmaxb;

/* size to output. hmaxb is byte-size. */
static GRAM_BUF *g_top_ptr;

/* head pointer of graphic vram */
static int f_div;
static int f_div2;
static int f_box;
static int v_x_shift;
static int v_x_shift2;
static int v_y_shift;
static int v_y_shift2;
static int view_page;
static BUFFER *v_top;
static BUFFER *v_top2;
static HUGE_BUF *view_buf;
long view_buf_size = (long)g_width_b * (long)G_HEIGHT / 2;	/* 0x4B00L */

int x_shift;
int y_shift;

/**

	Proto-types

**/

ulong leftbuffer();	/*	buffer.c */

void device_init(DIMENSION *);
void device_end(void);	/* (in fact, DIMENSION information is given) */
void device_clear(OUTPUT_INFO *);
void pr_new_page(void);
NEXT_ACTION device_out(OUTPUT_INFO *, DIMENSION *);

/* (in fact, OUTPUT_INFO information is given also to this) */
KeyInput extra_inkey(void);
static void first_draw(struct SCROLL *, int, int);
static void draw_screen(struct SCROLL *);
static void move_screen(struct SCROLL *, KeyInput);
static void scroll_up(struct SCROLL *);
static void scroll_down(struct SCROLL *);
static void scroll_right(struct SCROLL *);
static void scroll_left(struct SCROLL *);
static void flskey(void);
static void clear_text_screen(void);
static void s_up(struct SCROLL *, int);
static void s_down(struct SCROLL *, int);
static void s_left(struct SCROLL *);
static void s_right(struct SCROLL *);
static void hdw_scroll(struct SCROLL *);
static void gshift(uint);
static void cls(void);
static void s_view4(void);
static void s_view8(void);
static void v_box(BUFFER *, int, int, int, int);
static void msg_help(void);
static int  get_view(int, int);

void s_up(struct SCROLL *s_dat, int v_shift)
	/* scroll up by v_shift dots */
{
	int i, j, off1;
	HUGE_BUF *mptr_tmp;
	HUGE_BUF *mptr_tmp_1;
	GRAM_BUF *gptr_tmp;
	GRAM_BUF *gptr_tmp_1;

	mptr_tmp = s_dat->mptr + (ulong)hmaxb *(g_height - v_shift);

	gptr_tmp = g_top_ptr + s_dat->offset + g_width_b * (s_dat->r_line + g_height);
	s_dat->r_line += v_shift;

	for (i = 0; i < v_shift; i++) {
		movedata(FP_SEG(mptr_tmp), FP_OFF(mptr_tmp), FP_SEG(gptr_tmp), FP_OFF(gptr_tmp), s_dat->gw_act);
		gptr_tmp += g_width_b;
		mptr_tmp += hmaxb;
	}
	hdw_scroll(s_dat);
}

static void s_down(struct SCROLL *s_dat, int v_shift)
	/* scroll down by v_shift dots */
{
	int ins, i, j;
	HUGE_BUF *mptr_tmp;
	HUGE_BUF *mptr_tmp_1;
	GRAM_BUF *gptr_tmp;
	GRAM_BUF *gptr_tmp_1;

	mptr_tmp = s_dat->mptr;
	s_dat->r_line -= v_shift;
	gptr_tmp = g_top_ptr + s_dat->offset + g_width_b * (s_dat->r_line);

	for (i = 0; i < v_shift; i++) {
		movedata(FP_SEG(mptr_tmp), FP_OFF(mptr_tmp), FP_SEG(gptr_tmp), FP_OFF(gptr_tmp), s_dat->gw_act);
		mptr_tmp += hmaxb;
		gptr_tmp += g_width_b;
	}
	hdw_scroll(s_dat);
}

static void s_right(struct SCROLL *s_dat)
	/* 左方向　スムース・スクロール by 16 dots */
{
	HUGE_BUF *mptr_tmp;
	GRAM_BUF *gptr_tmp;
	int i, count;

	s_dat->offset -= 2;

	mptr_tmp = s_dat->mptr;
	gptr_tmp = (GRAM_BUF *) G_TOP + s_dat->offset + g_width_b * s_dat->r_line;
	count = 0;
	hdw_scroll(s_dat);
	for (i = g_height - 1 /*s_dat->r_line*/ ; i > 0; i--) {
		if (count++ < s_dat->v_spc || count > s_dat->v_spc + s_dat->gh_act)
			*((int far *)gptr_tmp) = 0;
		else {
			*((int far *)gptr_tmp) = *((int far *)mptr_tmp);
			mptr_tmp += hmaxb;
		}
		gptr_tmp += g_width_b;
	}
}

static void s_left(struct SCROLL *s_dat)
	/* 右方向　スムース・スクロール by 16 dots */
{
	HUGE_BUF *mptr_tmp;
	GRAM_BUF *gptr_tmp;
	int i, count;

	s_dat->offset += 2;

	/*	if( ++(s_dat->offset) >= g_width_b ) line1to2( s_dat, 1 ); */

	mptr_tmp = s_dat->mptr + (g_width_b - 2);
	gptr_tmp = (GRAM_BUF *) G_TOP + s_dat->offset
		+ g_width_b * s_dat->r_line + (g_width_b - 2);
	count = 0;
	for (i = g_height - 1 /*s_dat->r_line*/ ; i > 0; i--) {
		if (count++ < s_dat->v_spc || count > s_dat->v_spc + s_dat->gh_act)
			*((int far *)gptr_tmp) = 0;
		else {
			*((int far *)gptr_tmp) = *((int far *)mptr_tmp);
			mptr_tmp += hmaxb;
		}
		gptr_tmp += g_width_b;
	}

	hdw_scroll(s_dat);
}

static void hdw_scroll(struct SCROLL *s_dat)
	/* hardware scroll */
{
	gshift(s_dat->offset + g_width_b * s_dat->r_line);
}

void gshift(uint adr_1)
	/* output to crtc  */
{
	int crtc = peek(0, 0x463);	/* get crtc port address */

	disable();					/* cli */
	(void)outp(crtc, 12);
	(void)outp(crtc + 1, (adr_1 / 256));
	(void)outp(crtc, 13);
	(void)outp(crtc + 1, (adr_1 % 256));

	poke(0, 0x4D6, (adr_1 * 2)); /* set vram offset address for video bios */
	enable();					 /* sti */
}

KeyInput
extra_inkey(void)
	/* realtime key scanning. waiting until one of KeyInput is pressed.
     * and if the key is a cursor-key, I check at the same time whether Shift-
     * key is hit or not.
     */
{
	int num = 0;
	int f_num = 0;
	unsigned int k_dat;
	KeyInput key_d;

	union REGS regs;

	while (TRUE) {
		regs.h.ah = 0;
		int86(0x16, &regs, &regs);
		k_dat = regs.x.ax;
/*		k_dat = bioskey(0);	*/
		if ((k_dat & 0xff) != 0)
			k_dat = toupper(k_dat & 0xff);
		else {					/* Extend code */
			regs.h.ah = 2;
			int86(0x16, &regs, &regs);
			if ((regs.x.ax & 0x03) != 0)
/*			if ((bioskey(2) & 0x03) != 0)	*/
				k_dat |= 0xff;
		}
		switch (k_dat) {
		  case 0x4900:
			  k_dat = (int)'P';	/* PagUp */
			  break;
		  case 0x5100:
			  k_dat = (int)'N';	/* PagDn */
			  break;
		}
		if (k_dat >= '0' && k_dat <= '9') {
			f_num = 1;
			num -= (num / 100) * 100;
			num = num * 10 + k_dat - '0';
			if (num >= 1)
				unit_pages = num;
		}
		else {
			for (key_d = (KeyInput) 0; key_d != LoopEnd; ++key_d)
				if (key_data[(int)key_d] == k_dat)
					break;
			if (key_d == LoopEnd)
				continue;
			if ((key_d == Key_M || key_d == Key_G) && f_num == 0)
				continue;
			break;
		}
	}
	return (key_d);
}

void device_init(DIMENSION *dim)
	/* initialize graphic screen */
{
	union REGS regs;
	uint x, x2, y, y2;

	if (slow_fact < 0)
		slow_fact = 0;
	if (v_shift0 < 0 ){
		if((v_shift1 = - v_shift0) <= 1) v_shift1 = 1;
		if(v_shift1 > 8) v_shift1 = 8;
		v_shift0 = 0;
	}
	v_shift1 *= 4;

	if (f_resume) {
			/* Check resume information starting from 0040:00F0 */
		if (peekb(0x0040, 0x00f0) == 'R'
		  && peek(0x0040, 0x00f1) == resume_info)
			dim->start_page = peek(0x0040, 0x00f3);
		pokeb(0x0040, 0x00f0, 'R');
		poke(0x0040, 0x00f1, resume_info);
	}
	regs.h.al = 0x53;
	regs.h.ah = 0x0;
	int86(CRT_BIOS, &regs, &regs);	/* graphic ON */

	if (dim->split == 1) {
		x = x_shift + dim->text_width;
		if (x < s_max_width)
			x = s_max_width;
		if (x_shift < 0)
			x -= x_shift;

		y = y_shift + dim->text_height;
		if (y < s_max_height)
			y = s_max_height;
		if (y_shift < 0)
			y -= y_shift;
	}
	else
		return;

	num_view_buf = (leftbuffer() - 0x80L) / view_buf_size;

	if (x < (g_width_b - 12) * 32 && y < (g_height - 4) * 4) {
		f_div = 4;
	}
	else if (x < (g_width_b - 12) * 64 && y < (g_height - 4) * 8) {
		f_div = 8;
	}
	if (f_div > 0 && x > (g_width_b - 6) * 4 * f_div) {
		if (f_div == 4)
			f_div2 = 8;
	}
	else
		f_div2 = f_div;

	if (!f_use_new_size_option && s_max_height > 0 && s_max_width > 0)
		f_box = 1;

	if (num_view_buf > MAX_VIEW)
		num_view_buf = MAX_VIEW;
	if( num_view == 0 ) num_view = num_view_buf;
	if (f_div) {
		v_x_shift = x_shift >> 2;
		v_x_shift2 = x_shift >> 3;
		v_y_shift = y_shift >> 2;
		v_y_shift2 = y_shift >> 3;
		x = x2 = 5;
		y = y2 = 2;
		if (v_x_shift > 0) {
			x += (v_x_shift >> 3);
			x2 += (v_x_shift2 >> 3);
		}
		if (v_y_shift > 0) {
			y += v_y_shift;
			y2 += v_y_shift2;
		}
		v_top = (BUFFER *)G_TOP + x + (g_width_b * y);
		v_top2 = (BUFFER *)G_TOP + x2 + (g_width_b * y2);
		if (f_div2) goto nv;
#ifndef	NEMS
		if (num_view < 0 && num_view >= -MAX_VIEW){
			num_view_buf = -num_view;
			view_EMS_top = system_EMS_end;
			max_user_page -= view_EMS_unit*num_view_buf;
			system_EMS_end += view_EMS_unit*num_view_buf;
			view_buf = pf_addr;
			return;
		}
#endif
		if (num_view_buf > 0) {
			view_buf = (HUGE_BUF *)farmalloc(view_buf_size * num_view_buf);
		}
	}
	else
nv:		num_view_buf = 0;
}

static void cls()
{
	static BUF_INFO vram =
	{
		(BUFFER *)0xa0000000L,
		(BUFFER *)0xa0000000L,
		(BUFFER *)0xa0009fffL,
		0x9ff0L
	};

	clear_buf(&vram);
}

void device_end()
	/* erase graphic screen */
{
	union REGS regs;

	regs.h.al = 0x03;
	regs.h.ah = 0x0;
	int86(CRT_BIOS, &regs, &regs);	/* graphic ON */
}

void device_clear(OUTPUT_INFO *out)
	/* clear screen and initialize variables */
{
	/* intialize variables */
	map_top_ptr = out->bitmap_ptr;
	hmax = out->width;
	vmax = out->height;
	hmaxb = out->byte_width;

	/* clear screen */
	if (out->split > 1)
		cls();
	clear_text_screen();
}

static void s_view8(void)
{
	int i, j, vm, v;
	uint ch, gptr_off, x, y;
	HUGE_BUF *ptr0;
	BUFFER *ptr1;
	BUFFER *ptr;
	BUFFER *ptrg0;
	BUFFER *ptrg;

	ptrg0 = v_top2;
	ptr0 = map_top_ptr;

	for (ch = v = 0; v < vmax; v += 8) {
		vm = ((vmax - v) < 8) ? vmax - v : 8;
		ptr1 = (BUFFER *)ptr0;
		ptr0 += (hmaxb << 3);
		ptrg = ptrg0;
		ptrg0 += g_width_b;
		for (i = 0; i < hmaxb; i++) {
			ptr = ptr1++;
			for (j = vm; j != 0; j--) {
				if (*ptr != 0) {
					ch |= 1;
					break;
				}
				ptr += hmaxb;
			}
			if ((i & 7) == 7)
				*ptrg++ = ch;
			ch += ch;
		}
		if ((i = (hmaxb & 7)) != 0)
			*ptrg++ = (ch << (7 - i));
	}
	if (f_box)
		v_box(v_top2, -v_x_shift2, -v_y_shift2,
			  s_max_width / 8, s_max_height / 8);
}

static void s_view4(void)
{
	int i, j, vm, v;
	uint ch, gptr_off, x, y;
	HUGE_BUF *ptr0;
	BUFFER *ptr1;
	BUFFER *ptr;
	BUFFER *ptrg0;
	BUFFER *ptrg;

	ptrg0 = v_top;
	ptr0 = map_top_ptr;

	for (ch = v = 0; v < vmax; v += 4) {
		vm = ((vmax - v) < 4) ? vmax - v : 4;
		ptr1 = (BUFFER *)ptr0;
		ptr0 += (hmaxb << 2);
		ptrg = ptrg0;
		ptrg0 += g_width_b;
		for (i = 0; i < hmaxb; i++) {
			ptr = ptr1++;
			for (j = vm; j != 0; j--) {
				if ((*ptr & 0xf0) != 0) {
					ch |= 2;
				}
				if ((*ptr & 0x0f) != 0) {
					ch |= 1;
				}
				if ((ch & 3) == 3)
					break;
				ptr += hmaxb;
			}
			if ((i & 3) == 3)
				*ptrg++ = ch;
			ch <<= 2;
		}
		if ((i = (hmaxb & 3)) != 0)
			*ptrg++ = (ch << ((3 - i) * 2));
	}
	if (f_box)
		v_box(v_top, -v_x_shift, -v_y_shift,
			s_max_width / 4, s_max_height / 4);
}

static void v_box(BUFFER *orig, int x, int y, int w, int h)
{
	BUFFER *ptr;
	int i, b, ch, dif;

	orig += (x + g_width_b * 8) / 8 + g_width_b * (y - 1);
	b = (x & 7);

	ch = (1 << (7 - b));
	ptr = orig;
	for (i = h; i > 0; ptr += g_width_b, i--)
		*ptr |= ch;

	dif = g_width_b * (h - 1);
	ch = (0xff >> b);
	ptr = orig;
	*(ptr + dif) |= ch;
	*(ptr) |= ch;

	ptr++;
	for (i = w + b - 8; i > 8; ptr++, i -= 8) {
		*(ptr) |= 0xff;
		*(ptr + dif) |= 0xff;
	}
	ch = (0xff << (8 - i));
	*(ptr) |= ch;
	*(ptr + dif) |= ch;

	ch = (1 << (8 - i));
	for (i = h; i > 0; ptr += g_width_b, i--)
		*ptr |= ch;
}

void msg_help()
{
	cls();

	fprintf(stderr,
			"\x1b" "[5;H"
			"\t\t\t\t<<< Help >>>\n\n"
			"\t(SHIFT + ) → ← ↑ ↓\t: Scroll in a page\n"
			"\tN\t\t\t: Next page\n"
			"\tP, B\t\t\t: Previous page\n"
			"\tG, M\t\t\t: Move to a page\n"
			"\tnumbers\t\t\t: pages (skipped) by next B, G, M, N, P\n"
			"\tSpace\t\t\t: Next part\n"
			"\tBack Space\t\t: Previous part\n"
			"\tC, V\t\t\t: (Compressed) View outline\n"
			"\tR\t\t\t: Reverse Screen(toggle)\n"
			"\tH, HOME\t\t\t: Help message\n"
			"\tReturn\t\t\t: Next block or quit\n"
			"\tEscape\t\t\t: Quit\n"
		);

	flskey();
	getch();
	fprintf(stderr, "\x1b" "[5;H" "\x1b" "[0J" "\x1e");

}

void slow(int fact)
{
	int	  i, j;

	i = (fact<6)?5:fact;
	while(fact-- > 0){
		for(j = 0; j < 6*i; j++) slow( 0 );
	}
}

NEXT_ACTION device_out(OUTPUT_INFO *out, DIMENSION *dim)
{
	static struct SCROLL s_dat;
	KeyInput key;
	int i, j;

	s_dat.mptr = map_top_ptr;

	first_draw(&s_dat, out->page, dim->split);
	slow(slow_page);

	for (;;) {
		switch (key = extra_inkey()) {
		  case Key_V:
		  case Key_C:
			  if (!f_div)
				  break;
			  cls();
			  gshift(0);
			  s_dat.r_line = 0;
			  i = s_dat.offset;
			  s_dat.offset = 0;
			  if (f_div == 4 && key != Key_C) {
				  s_view4();
				  j = get_view(out->page, 4);
			  }
			  else {
				  s_view8();
				  j = get_view(out->page, 8);
			  }
			  s_dat.offset = i;
			  cls();
			  if (j) goto disp_m;
disp_0:		  draw_screen(&s_dat);
			  slow(slow_page);
			  break;
		  case Key_R:
			  goto disp2;
		  case Key_H:
		  case HELP:
			  msg_help();
			  goto disp_0;
		  case Key_M:
disp_m:		  unit_pages -= out->page;
			  return ((NEXT_ACTION)Key_N);
		  case ArrowDown:
			  scroll_up(&s_dat);
			  goto sl0;
		  case ArrowLeft:
			  scroll_right(&s_dat);
			  goto disp2;
		  case ArrowRight:
			  scroll_left(&s_dat);
sl2:		  slow(slow_fact2);
			  break;
		  case ArrowUp:
			  scroll_down(&s_dat);
sl0:		  slow(v_shift0);
			  break;
		  case ShiftUp:
		  case ShiftDown:
		  case ShiftLeft:
		  case ShiftRight:
			  move_screen(&s_dat, key);
			disp2:slow(slow_fact);
			  break;
		  default:
			  return ((NEXT_ACTION)key);
		}
	}
}

static void first_draw(struct SCROLL *s_dat, int page, int split)
	/* at first, set variables and put to screen */
{
	if (f_resume)
		poke(0x0040, 0x00f3, page);
	s_dat->x_lock = s_dat->y_lock = FALSE;
	s_dat->offset = 0;

	if (hmaxb < g_width_b) {
		/* can't scroll horizontally */
		s_dat->gw_act = hmaxb;
		s_dat->x_lock = TRUE;
	}
	else
		s_dat->gw_act = g_width_b;

	if (vmax < g_height) {
		/* can't scroll vertically */
		s_dat->gh_act = vmax;
		s_dat->y_lock = TRUE;
	}
	else
		s_dat->gh_act = g_height;

	s_dat->h_spc = (g_width_b - s_dat->gw_act) / 2;
	s_dat->v_spc = (split == 1) ? (g_height - s_dat->gh_act) / 2 : 0;
	g_top_ptr = (GRAM_BUF *) G_TOP + s_dat->h_spc + s_dat->v_spc * g_width_b;

	s_dat->x = -s_dat->h_spc;
	s_dat->y = -s_dat->v_spc;

	draw_screen(s_dat);
	fprintf(stderr, "\x1b" "[0;0H" "[%d]", page);
}

void draw_screen(struct SCROLL *s_dat)
	/* put bitmap-image to screen */
{
	int i, j;
	HUGE_BUF *mptr_tmp;
	GRAM_BUF *gptr_tmp;

	gptr_tmp = g_top_ptr;
	if (s_dat->y_lock == TRUE && s_dat->x_lock == FALSE) {
		gptr_tmp = g_top_ptr;
		for (i = s_dat->offset; --i >= 0;)
			gptr_tmp[i] = 0;
		gptr_tmp += (g_width_b * s_dat->gh_act + s_dat->gw_act);
		j = hmaxb - s_dat->offset - g_width_b;
		for (i = 0; i < j;)
			gptr_tmp[i++] = 0;
	}
	s_dat->r_line = 0;
	hdw_scroll(s_dat);
	mptr_tmp = s_dat->mptr;
	gptr_tmp = g_top_ptr + s_dat->offset;
	for (i = 0; i < s_dat->gh_act; i++) {
		movedata(FP_SEG(mptr_tmp), FP_OFF(mptr_tmp), FP_SEG(gptr_tmp), FP_OFF(gptr_tmp), s_dat->gw_act);
		gptr_tmp += g_width_b;
		mptr_tmp += (ulong)hmaxb;
	}
}

static int get_view(page, div)
{
	int i, pt, pg;
	uchar tmp[g_width_b / 2];
	GRAM_BUF *gptr_tmp;
	HUGE_BUF *buf_tmp;

	union REGS regs;

	pg = -1;
	fprintf(stderr, "\x1b" "[0;0H" "[%d]" "\x1b" "[0;0H", page);

	if (num_view_buf <= 0) {
		regs.h.ah = 0;
		int86(0x16, &regs, &regs);
/*		bioskey(0);	*/
		return;
	}
	pt = view.current;
	while (TRUE) {
		if (div != f_div2)
			goto skip;
		if (--pt < 0)
			pt = view.total - 1;
		if (pt >= 0) {
#ifndef	NEMS
			if( view_EMS_unit ){
				buf_tmp = view_buf;
				set_ems( view_EMS_top + view_EMS_unit*pt );
			}
			else
#endif
				buf_tmp = view_buf + view_buf_size * pt;
			gptr_tmp = (GRAM_BUF *) (G_TOP + g_width_b / 2);
			for (i = g_height; i > 0; i--) {
				movedata(FP_SEG(buf_tmp), FP_OFF(buf_tmp), FP_SEG(gptr_tmp), FP_OFF(gptr_tmp), g_width_b / 2);
				buf_tmp += g_width_b / 2;
				gptr_tmp += g_width_b;
			}
			pg = view.page[pt];
		}
skip:	flskey();
		regs.h.ah = 0;
		int86( 0x16, &regs, &regs );
		i = regs.h.al;
/*		i = (uchar)bioskey(0);	*/
		if (i != 'm' && i != 'M' && i != 'ﾓ')
			pg = -1;
		if (i != 'v' && i != 'V' && i != 'ﾋ')
			break;
	}
	fprintf(stderr, "\x1a" "[%d]", page);
	if (div != f_div2)
		return 0;
	for (pt = view.total; pt > 0;) {
		if (view.page[--pt] == page) {
			view.current = pt + 1;
			goto nxt;
		}
	}
	if (view.total < num_view_buf)
		view.current = view.total++;
	if (view.current >= num_view_buf)
		view.current = 0;
	view.page[view.current] = page;

	gptr_tmp = (GRAM_BUF *) G_TOP;
#ifndef	NEMS
	if( view_EMS_unit ){
		buf_tmp = view_buf;	
		set_ems( view_EMS_top + view_EMS_unit*view.current );
	}else
#endif
		buf_tmp = view_buf + view_buf_size * view.current;
	view.current++;
	for (i = g_height; i > 0; i--) {
		movedata(FP_SEG(gptr_tmp), FP_OFF(gptr_tmp), FP_SEG(buf_tmp), FP_OFF(buf_tmp), g_width_b / 2);
		buf_tmp += g_width_b / 2;
		gptr_tmp += g_width_b;
	}
nxt:
	if (pg >= 0)
		unit_pages = pg;
	return pg+1;
}

static void move_screen(struct SCROLL *s_dat, KeyInput direct)
{
	int x_step, y_step;

	x_step = y_step = 0;
	switch (direct) {
	  case ShiftDown:
		  y_step = (s_dat->gh_act) >> 1;
		  break;
	  case ShiftUp:
		  y_step = -((s_dat->gh_act) >> 1);
		  break;
	  case ShiftLeft:
		  x_step = -(s_dat->gw_act) >> 1;
		  break;
	  case ShiftRight:
		  x_step = (s_dat->gw_act) >> 1;
		  break;
	}

	if (x_step != 0 && !s_dat->x_lock) {
		if (s_dat->x + x_step <= 0)
			x_step = -s_dat->x;
		if (s_dat->x + x_step + g_width_b >= hmaxb)
			x_step = hmaxb - (s_dat->x + g_width_b);
		x_step &= 0xfffe;
		s_dat->x += x_step;
		s_dat->mptr += x_step;
		s_dat->offset = s_dat->h_spc + s_dat->x;
		draw_screen(s_dat);
	}
	else if (y_step != 0 && !s_dat->y_lock) {
		if (s_dat->y + y_step <= 0)
			y_step = -s_dat->y;
		if (s_dat->y + y_step + g_height >= vmax)
			y_step = vmax - (s_dat->y + g_height);
		s_dat->y += y_step;
		s_dat->mptr += (long)y_step *hmaxb;

		draw_screen(s_dat);
	}
}

static void scroll_up(struct SCROLL *s_dat)
{
	int shift;

	if ((shift = vmax - s_dat->y - g_height) > 0) {
		shift = (shift / 4) * 4;
		if (shift > v_shift1)
			shift = v_shift1;
		s_dat->mptr += hmaxb * shift;
		s_dat->y += shift;
		s_up(s_dat, shift);
	}
}

static void scroll_down(struct SCROLL *s_dat)
{
	int shift;

	if ((shift = s_dat->y) > 0) {
		shift = (shift / 4) * 4;
		if (shift > v_shift1)
			shift = v_shift1;
		s_dat->mptr -= hmaxb * shift;
		s_dat->y -= shift;
		s_down(s_dat, shift);
	}
}

static void scroll_right(struct SCROLL *s_dat)
{
	if (s_dat->x > 0) {
		s_dat->mptr -= 2;
		s_dat->x -= 2;
		s_right(s_dat);
	}
}

static void scroll_left(struct SCROLL *s_dat)
{
	if (s_dat->x + g_width_b < hmaxb) {
		s_dat->mptr += 2;
		s_dat->x += 2;
		s_left(s_dat);
	}
}

static void flskey(void)
	/*  flush key-buffer. by calling dos function */
{
	bdos(12, 0, 0);
}

static void clear_text_screen()
	/* clear text screen */
{
	fprintf(stderr, "\x1b" "[2J");
}

void pr_new_page(void)
{
}

void device_cont(void)
{
}

void device_pause(void)
{
}

/* end of file : device.c */
