/*
 *  TEX Device Driver  ver 2.02-
 *  (c)copyright 1988, 1989 by TSG, 1990-93 by SHIMA
 *
 *  bitmap.c : to write characters and rules on bitmap buffer
 *             2nd edition
 *             2 January 1992 : modified for tpic by Oh-Yeah?
 *             22 July 1992 : modified for pTeX by Naochan!.
 */

/* #pragma inline */

#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#define _DEF_STDIO_H_
#include "dd.h"
#include "err.h"

/* w_font.asm */
/* void  w_font( BUFFER *, BUFFER *, int, int, int, int, int, int ); */
/* bitblt.c */
extern void (*bitblt) (BUFFER *source_byte, int s_linewidth_byte,
					   int s_width_bit, int s_height_bit, BUFFER *dest_byte,
					   int d_linewidth_byte, int d_offset_x_bit,
					   int d_offset_y_bit);

#ifndef NOTPIC
void alter_bitblt_ow(BOOL flag);

#endif

/* size.c, prtsize.c */
PIXEL sptopixel(SCALED_PT);
PIXEL vtopixel(SCALED_PT);

/* buffer.c */
copy_to_user( int, int, int, int, long );
alloc_ems( int, int, int, int, int );

static BUFFER *map_top_ptr;

#ifdef BIGFONT
extern int f_assigned;

/* epsbox.c */
extern	int	current_f_GIF;
BOOL put_pbm(char *epsfname, PIXEL h, PIXEL v, PIXEL width, PIXEL height, int mode , BOOL fgbox);

/* getfont.c */
int *get_bigfont(void);
#endif

/*  bitmap のポインタ */
static PIXEL vmax, hmax, hmaxb, vmin, hmin;
BOOL draw_baseline = 0;
BOOL draw_boxpic = 0;
extern char ptex_d;
void bitmap_init(OUTPUT_INFO *out);

void boxpic(PIXEL h, PIXEL v, PIXEL w, PIXEL d);

void write_font(PIXEL h, PIXEL v, PREAMBLE *pxl);
void write_rule(PIXEL h, PIXEL v, PIXEL a, PIXEL b);

#ifndef NOTPIC
void init_tile(double grayscale);	/* initialize overriding for tiles */
void fin_tile(void);	/* finish tiling. recover original data */
void write_tile(PIXEL h, PIXEL v, PIXEL a, PIXEL b);
void set_tile(double grayscale);
void adjust_tile(PIXEL h, PIXEL v);	/* adjust pattern by (h, v) position */

#ifdef VFTPIC
/* called by draw_character() in vfont.c */
void init_alter_bitmap(BUFFER *dest, PIXEL d_linewidth_byte);
void fin_alter_bitmap(void);

#endif
#ifndef NOTPIC_EXTENSION
/* called by alter_bitblt_rt() in bitblt.c */
typedef struct {
	PIXEL x, y;
} pixelpoint;

pixelpoint turn_off_trimming(void);
void turn_on_trimming(void);

#endif
#endif

BUFFER *rotate_raster(PREAMBLE *preamble);
uchar leftside_right(uchar orig);

void bitmap_init(OUTPUT_INFO *out)
	/*  変数のイニシャライズ  */
{
	extern PIXEL vmax, hmax, hmaxb, vmin, hmin;

	ENTER("bitmap_init");

	map_top_ptr = (BUFFER *)out->bitmap_ptr;
	hmax = out->width;
	vmax = out->height;
	vmin = hmin = 0;
	hmaxb = out->byte_width;

	END();
}

#define  WIDTH_OF_LINE  26214L	/* 線の太さ: 26214(scaled point) = 0.4pt */

void boxpic(PIXEL h, PIXEL v, PIXEL w, PIXEL d)
	/* 文字の代わりに「箱」で組版するための関数 （「白い箱」版 rput） */
{
	PIXEL w_h, w_v;

	w_h = vtopixel(WIDTH_OF_LINE);	/* 横線の太さ */
	w_v = sptopixel(WIDTH_OF_LINE);	/* 縦線の太さ */

	write_rule(h, v + (w_h - 1), w_h, w);	/* 横線 (上) */
	write_rule(h, v + d - 1, w_h, w);	/* 横線 (下) */
	write_rule(h, v + d - 1, d, w_v);	/* 縦線 (左) */
	write_rule(h + w - w_v, v + d - 1, d, w_v);	/* 縦線 (右) */
}

int f_shift_EMS;

void write_font(PIXEL h, PIXEL v, PREAMBLE *pxl)
	/* キャラクターの書き込み */
	/* pTeX の「90度回転書き込み」に対応  by Naochan! 18 July 1992 */
{
	PIXEL he, ve;	/* end points */
	PIXEL haba, takasa;
	int *tmp;
	int byte_width;
	BUFFER *raster;

	ENTER("write_font");
	haba = pxl->width;
	takasa = pxl->height;
	raster = pxl->raster;
	f_shift_EMS = pxl->shift_up_ptex;

	if (ptex_d == 1) {			/* 縦書きの場合 */
								/* 文字を右・上方向に補正 */
		h += pxl->depth_offset + pxl->shift_right_ptex;
#ifdef BIGFONT
		if (f_assigned != 3)
#endif
			h -= ((pxl->rotate_ptex & 1)?takasa:haba);
		v -= pxl->pitch_offset + pxl->shift_up_ptex;

		if (pxl->rotate_ptex & 1) {	/* 文字を90度回転 */
			haba = takasa;
			takasa = pxl->width;
			raster = rotate_raster(pxl);
		}
		byte_width = (haba + 7) / 8;
	}
	else {
		h -= pxl->pitch_offset;
		v -= pxl->depth_offset;
	    byte_width = pxl->byte_width;
	}
#ifdef	BIGFONT
	if (f_assigned == 3){
pbm:
		tmp    = get_bigfont();
		takasa = pxl->height;
		haba   = pxl->width;
		if (ptex_d == 1) h -= haba;
	}
#endif
	if (v < vmax && h < hmax
		&& (he = h + haba) > hmin && (ve = v + takasa) > vmin) {
		/* キャラクターの１部でも表示範囲にはいったら... */

		if (he > hmax)
			he = hmax;			/* right trimmed */
		if (ve > vmax)
			ve = vmax;			/* bottom trimmed */

		if (draw_boxpic != 0) {
			v += (f_shift_EMS & 0x3fff);
			if ((he = h + haba - pxl->shift_right_ptex) > hmax)
				he = hmax;
			boxpic(h, v, he - h, ve - v);
		}
		else{
#ifdef	BIGFONT
			if (f_assigned >= 3){
				if(f_assigned == 4)
					tmp = get_bigfont();
  #ifdef GIF
				current_f_GIF = 0;
  #endif
				if (put_pbm("bf$.pbm", h, v, tmp[0], tmp[1], 0x8800, 0)==NULL)
					error(PROGRAM_STOP, "can't open %s", common_work);
			}
			else
#endif
				bitblt(raster, byte_width, he - h, ve - v, map_top_ptr, hmaxb,
					h, v);		/* left and top will be trimmed */
		}
	}
end:
	if(f_shift_EMS & 0x4000) alloc_ems( -1, 0, 0, 0, 0 );
	END();
}

#define LINE_LEN 4
#define ONEBYTE  8
static uchar box_data[LINE_LEN] =
{0xff, 0xff, 0xff, 0xff};	/* black */

/* used for overriding write_rule() by write_tile() for tpic */
static BUFFER *tile_ptr = (BUFFER *)box_data;
static int tile_width_bit = LINE_LEN * ONEBYTE;	/* pattern width */
static int tile_inc_byte = 0;
/* increment = 0; use same pattern repeatedly */
static int tile_height_bit = 10000;	/* actually infinite */

void write_rule(PIXEL h, PIXEL v, PIXEL a, PIXEL b)
	/*  長方形の書き込み */
{
	PIXEL he, ve;	/* end points */
	PIXEL hs, hspan, hrep, hres, vspan, vrep, vres, i;

	ENTER("write_rule");

	if (a >= 0)
		v -= a - 1;
	else
		a = -a;

	if (b < 0) {
		b = -b;
		h -= b - 1;				/* (h, v) = rule's top-left point */
	}
	if (v < vmax && h < hmax
		&& (he = h + b) > hmin && (ve = v + a) > vmin) {
		/* キャラクターの１部でも表示範囲にはいったら... */

		if (he > hmax)
			he = hmax;			/* right trimmed */
		if (ve > vmax)
			ve = vmax;			/* bottom trimmed */
		/* left and top will be trimmed in bitblt() */

		vrep = (vspan = ve - v) / tile_height_bit;
		vres = vspan % tile_height_bit;
		hrep = (hspan = he - h) / tile_width_bit;
		hres = hspan % tile_width_bit;
		hs = h;

		while (vrep-- > 0) {
			i = hrep;
			h = hs;
			while (i-- > 0) {
				bitblt(tile_ptr, tile_inc_byte, tile_width_bit,
					   tile_height_bit, map_top_ptr, hmaxb, h, v);
				h += tile_width_bit;
			}
			if (hres > 0)
				bitblt(tile_ptr, tile_inc_byte, hres,
					   tile_height_bit, map_top_ptr, hmaxb, h, v);
			v += tile_height_bit;
		}
		if (vres > 0) {
			i = hrep;
			h = hs;
			while (i-- > 0) {
				bitblt(tile_ptr, tile_inc_byte, tile_width_bit,
					   vres, map_top_ptr, hmaxb, h, v);
				h += tile_width_bit;
			}
			if (hres > 0)
				bitblt(tile_ptr, tile_inc_byte, hres,
					   vres, map_top_ptr, hmaxb, h, v);
		}
	}
	END();
}

#ifndef NOPS
void write_pbm( PIXEL h, PIXEL v, PIXEL w, PIXEL d, char *raster )
    /*  portable bit map の書き込み */
{
	PIXEL he, ve; /* end points */
	PIXEL hs, hspan, hrep, hres, vspan, vrep, vres, i;
    int   byte_width;

    ENTER( "write_pbm" );

	byte_width = ( w + 7 ) / 8;
	if ( v < vmax && h < hmax
		&& (he = h + w) > 0 && (ve = v + d) > 0 ){
		/* キャラクターの１部でも表示範囲にはいったら... */

		if (he > hmax) he = hmax; /* right trimmed */
		if (ve > vmax) ve = vmax; /* bottom trimmed */
		/* left and top will be trimmed in bitblt() */

   		bitblt(raster, byte_width, he - h, ve - v, 
        		map_top_ptr, hmaxb, h, v); /* left and top will be trimmed */

    }

    END();
}

# ifdef	TILE
void write_tiled_pbm(PIXEL h, PIXEL v, PIXEL w, PIXEL d, char *raster, int tl)
{
	int i, j;

	if (tl) {
	for(j=v; j<vmax; j+=d)
		for(i=h; i<hmax; i+=w)
		write_pbm(i, j, w, 1, raster);
	}
	else write_pbm(h, v, w, 1, raster);
}
# endif
#endif

/* end of file : bitmap.c */

/* additional functions for tpic */

#ifndef NOTPIC

/* tiling functions */

static BUFFER *temp_tile;	/* just for keeping 'em */
static int temp_width, temp_inc, temp_height;

void init_tile(double grayscale)
{	   /* initialize overriding for tiles */
	ENTER("init_tile");

	temp_tile = tile_ptr;		/* just keep 'em */
	temp_width = tile_width_bit;
	temp_inc = tile_inc_byte;
	temp_height = tile_height_bit;

	alter_bitblt_ow((grayscale <= 0) ? TRUE : FALSE);	/* if white, ow */
	set_tile(grayscale);

	END();
}

void fin_tile(void)
{	   /* finish tiling. recover original data */
	ENTER("fin_tile");

	tile_ptr = temp_tile;		/* just recover 'em */
	tile_width_bit = temp_width;
	tile_inc_byte = temp_inc;
	tile_height_bit = temp_height;
	alter_bitblt_ow(FALSE);		/* no overwriting */

	END();
}

void write_tile(PIXEL h, PIXEL v, PIXEL a, PIXEL b)
{
	ENTER("write_tile");

	adjust_tile(h, v);			/* modify pattern by position, if necessary */
	write_rule(h, v, a, b);

	END();
}

#ifndef TPIC_SCATTERED

#define PATTERN_BIT  4	/* maximum = 4 */
#define MAX_PATTERN  10	/* maximum = PATTERN_BIT^2, including full black */

static uchar pattern[MAX_PATTERN - 1][PATTERN_BIT * 2] =
{
/* 4 x 4 patterns (except for full black). lower 4 bits and last 4 bytes
	are just repeated patterns for avoiding rotation of bits */

/* these are rational but too dark because of dots emphasized by printers */
/*		{0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00},
		{0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88},
		{0x00, 0xaa, 0x00, 0x88, 0x00, 0xaa, 0x00, 0x88},
		{0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa},
		{0x00, 0xaa, 0x44, 0xaa, 0x00, 0xaa, 0x44, 0xaa},
		{0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa},
		{0x44, 0xaa, 0x55, 0xaa, 0x44, 0xaa, 0x55, 0xaa},
		{0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa},
		{0xbb, 0x55, 0xaa, 0x55, 0xbb, 0x55, 0xaa, 0x55},
		{0xee, 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55},
		{0xff, 0x55, 0xbb, 0x55, 0xff, 0x55, 0xbb, 0x55},
		{0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55},
		{0xff, 0x55, 0xff, 0x77, 0xff, 0x55, 0xff, 0x77},
		{0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77},
		{0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff} */

/* these are from trial-and-errors */
	{0x00, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00},
	{0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88},
	{0x00, 0x22, 0x44, 0x00, 0x00, 0x22, 0x44, 0x00},
	{0x00, 0x66, 0x44, 0x00, 0x00, 0x66, 0x44, 0x00},
	{0x00, 0xaa, 0x00, 0x88, 0x00, 0xaa, 0x00, 0x88},
	{0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00},
	{0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa},
	{0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa},
	{0xee, 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55}
};

static uchar tile_data[PATTERN_BIT];	/* selected pattern for gray tiling */
static int black;	/* selected pattern number */

void set_tile(double grayscale)
	/* set static parameters: tile_ptr, tile_width_bit, tile_inc_byte and
	tile_height_bit */
	/* gray image is realized by periodic pattern */
{
	static uchar white_data[LINE_LEN] =
	{0x00, 0x00, 0x00, 0x00};	/* white */
	static double max_pat_d = MAX_PATTERN * 1.01;
	/* against float calc err */

	ENTER("set_tile");

	black = (int)(grayscale * max_pat_d);
	if (black >= MAX_PATTERN) {	/* black, fill by append (OR) */
		tile_ptr = (BUFFER *)box_data;
		tile_width_bit = LINE_LEN * ONEBYTE;
		tile_inc_byte = 0;
		tile_height_bit = 10000;
	}
	else if (black <= 0) {		/* white, fill by overwrite (AND) */
		tile_ptr = (BUFFER *)white_data;
		tile_width_bit = LINE_LEN * ONEBYTE;
		tile_inc_byte = 0;
		tile_height_bit = 10000;
	}
	else {						/* gray pattern (4x4), fill by append (OR) */
		tile_ptr = (BUFFER *)tile_data;	/* actual pattern is not copied yet */
		tile_width_bit = PATTERN_BIT;
		tile_inc_byte = 1;
		tile_height_bit = PATTERN_BIT;
	}

	END();
}

void adjust_tile(PIXEL h, PIXEL v)
{	   /* adjust pattern by (h, v) position */
	int i, n, rot_x, rot_y;

	ENTER("adjust_tile");

	if (black > 0 && black < MAX_PATTERN) {	/* gray. rotate pattern */
		rot_x = (unsigned)h % PATTERN_BIT;
		rot_y = (unsigned)v % PATTERN_BIT;
		/* mod for rotation by (h, v) position */
		/* Note: if h or v is negative, this works correctly only for
		PATTERN_BIT = 2, 4, 8 (e.g. -1, -2, -3, -4, -5 -> 3, 2, 1, 0, 3) */

		n = black - 1;
		for (i = 0; i < PATTERN_BIT; i++)
			tile_data[i] = (pattern[n][i + rot_y] << rot_x);
	}
	END();
}

#else /* if TPIC_SCATTERED is defined ..... */

void set_tile(double grayscale)
	/* set static parameters: tile_ptr, tile_width_bit, tile_inc_byte and
	tile_height_bit */
	/* gray image is realized by randomly scattered pattern */
{
	static uchar white_data[LINE_LEN] =
	{0x00, 0x00, 0x00, 0x00};	/* white */
	static uchar tile_data[LINE_LEN];
	int black, i, j;

	ENTER("set_tile");

	black = (int)(grayscale * ONEBYTE);
	if (black >= ONEBYTE) {		/* black, fill by append (OR) */
		tile_ptr = (BUFFER *)box_data;
		tile_width_bit = LINE_LEN * ONEBYTE;
		tile_inc_byte = 0;
		tile_height_bit = 10000;
	}
	else if (black <= 0) {		/* white, fill by overwrite (AND) */
		tile_ptr = (BUFFER *)white_data;
		tile_width_bit = LINE_LEN * ONEBYTE;
		tile_inc_byte = 0;
		tile_height_bit = 10000;
	}
	else {						/* gray (8x4), fill by append (OR) */
		tile_ptr = (BUFFER *)tile_data;
		tile_width_bit = LINE_LEN * ONEBYTE;
		tile_inc_byte = 0;
		tile_height_bit = 10000;

		for (i = 0; i < LINE_LEN; i++) {	/* randomly scattered pattern */
			tile_data[i] = 0;
			for (j = 0; j < ONEBYTE; j++)
				if (rand() % ONEBYTE < black)
					tile_data[i] |= (0x01 << j);
		}
	}

	END();
}

void adjust_tile(PIXEL dummy1, PIXEL dummy2)
{
	return;
}

#endif /* end of ifndef TPIC_SCATTERED ... else ... */

#ifdef VFTPIC

/* vector-font support functions */

static BUFFER *temp_map_top_ptr;	/* keepings for overriding dest bitmap */
static PIXEL temp_hmaxb;

void init_alter_bitmap(BUFFER *dest, PIXEL d_linewidth_byte)
{
	ENTER("init_alter_bitmap");
	temp_map_top_ptr = map_top_ptr;	/* keep 'em */
	temp_hmaxb = hmaxb;
	map_top_ptr = dest;
	hmaxb = d_linewidth_byte;
	END();
}

void fin_alter_bitmap(void)
{
	ENTER("fin_alter_bitmap");
	map_top_ptr = temp_map_top_ptr;	/* recover 'em */
	hmaxb = temp_hmaxb;
	END();
}

#endif /* end of ifdef VFTPIC */

#ifndef NOTPIC_EXTENSION

/* rotation routines */

#define MAX_PIXEL 32766	/* max value of type int */
static PIXEL temp_hmax, temp_vmax;
static BOOL is_trimming_on = TRUE;

pixelpoint turn_off_trimming(void)
{	   /* stop trimming and ret hmax and vmax */
	pixelpoint answer;

	ENTER("turn_off_trimming");
	if (is_trimming_on) { /* record max and turn off */
		temp_hmax = hmax;
		temp_vmax = vmax;
		hmax = vmax = MAX_PIXEL;
		hmin = vmin = -MAX_PIXEL;	/* minimum is always zero, not kept */
		is_trimming_on = FALSE;
	}
	answer.x = temp_hmax;
	answer.y = temp_vmax;
	RETURN(answer);
}

void turn_on_trimming(void)
{
	ENTER("turn_on_trimming");
	if (!is_trimming_on) {
		hmax = temp_hmax;
		vmax = temp_vmax;
		hmin = vmin = 0;
		is_trimming_on = TRUE;
	}
	END();
}

#endif /* end of ifndef NOTPIC_EXTENSION */

#endif /* end of ifndef NOTPIC */

/* end of all */

uchar common_work[COMMON_SIZE];

/* COMMON_SIZE =  2048 -> 128ドットのフォントまで回転可能 */
/* EMS         = 32768 -> 512ドットのフォントまで回転可能 */
/*  2048 = 128^2 / 8, 17 = 128 / 8 + 1
 * 32768 = 512^2 / 8, 65 = 512 / 8 + 1
 * 65536 : 724^2 / 8, 91 = 724 / 8 + 1
       * 118dpi: 128×128 → 78.4pt
       * 360dpi: 128×128 → 25.7pt
       * 640dpi: 128×128 → 14.4pt
       */

BUFFER *
    rotate_raster(PREAMBLE *preamble)
	/* ラスタのデータを90度回転させます。 by Naochan! */
{
 	uchar work2[64];
	uchar *work0;
	BUFFER *new_raster;
	BUFFER *old_raster;
	uint old_height, old_byte_width;
	uint new_width, new_height, new_byte_width;
	uint ix, iy, bit, start, mask, leftshift;
	long r_size, s_size;
	uchar c;
	uint ci;
	uint y_width;
	static int f_rotate;

	new_height = preamble->width;
	new_width = old_height = preamble->height;
	old_byte_width = preamble->byte_width;
	new_byte_width = (new_width + 7) / 8;

	old_raster = preamble->raster;
	if ( (r_size = ((long)new_byte_width) * new_height) <= COMMON_SIZE
		|| new_byte_width > 64 ) {
		new_raster = common_work;
		work0 = work2;
exec:	for (iy = 0; iy < new_height; iy++) {
			y_width = iy * new_byte_width;
			for (ix = 0; ix < new_byte_width; ix++) {
				mask = 0x0080 >> (iy % 8);
				start = (old_height - ix * 8 - 1) * old_byte_width + iy / 8;
				c = 0;
				for (bit = 0; bit < 8; bit++, start -= old_byte_width)
					c += (((old_raster[start] & mask) << (iy % 8)) >> bit);
				new_raster[y_width + ix] = c;
			}
		}
		if (preamble->rotate_ptex & 2) {	/* 文字を左右反転 */
			leftshift = (8 - (new_width % 8)) % 8;
			mask = ((leftshift == 0) ? 0 : (0x00FF >> (8 - leftshift)));
			for (iy = 0; iy < new_height; iy++) {
				y_width = iy * new_byte_width;
				for (ix = 0; ix < new_byte_width; ix++) {
					work0[new_byte_width - ix - 1]
						= leftside_right(new_raster[y_width + ix]);
				}
				for (ix = 0; ix < new_byte_width; ix++) {
					ci = (uint)work0[ix];
					ci <<= 8;
					ci += work0[ix + 1];
					ci <<= leftshift;
					ci &= 0xFF00;
					ci >>= 8;
					new_raster[y_width + ix] = (uchar)ci;
				}
			}
		}
	}
	else{
		if (new_byte_width > COMMON_SIZE) goto err;
		work0 = common_work;
		s_size = ((long)(preamble->byte_width))*preamble->height;
		if (work_buf_size >= r_size) {
			new_raster = work_buf_addr;
			goto exec;
		}
#ifndef	NEMS
		if (max_user_page >= 4 && r_size <= 0x8000L && s_size <= 0x8000L){
			copy_to_user( FP_SEG(preamble->raster), FP_OFF(preamble->raster),
				2, 0, s_size );
			alloc_ems( 0, 1, 2, 3, 4 );
			f_shift_EMS |= 0x4000;
			old_raster = (new_raster = pf_addr) + 0x8000;
			goto exec;
		}
#endif
err:	if(!f_rotate){
			error(BAD_SYSTEM,
				"No working space (%ld byte) to rotate a character"
				, s_size );
			f_rotate = 1;
		}
		new_raster = preamble->raster;
	}
	RETURN(new_raster);
}

unsigned char leftside_right(uchar orig)
	/* バイト左右反転 */
{
	int i;
	uchar work, mask1, mask2;

	work = 0;
	mask1 = 1;
	mask2 = 0x80;

	for (i = 0; i < 8; i++) {
		if (orig & mask1)
			work |= mask2;
		mask1 <<= 1;
		mask2 >>= 1;
	}

	return work;
}
