/*
 *		Routine to use scalable/downloaded font of LIPS3 (dviprt)
 *								30 June	1992, written by SHIMA
 *		Modifyed by OkI for LIPS3 & ESC/Page 14 Nov. 1992.
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define _DEF_DOS_H_
#include "dd.h"
#include "prtout.h"
#include "err.h"
#include "prtctl.h"
#include "lips3.h"

#define VDF_GOTH 1
#define VDF_GGOTH 2
#define VDF_OUTLINE 4

/* lips3.c local */
static void pr_attr(int flag);
static void pr_normal(int flag);
static uint change_code(uint code);

/* p_out.c function */
static void lips_init(void);
static void lips_page_format(int ff_rotate, int f_copy);
static void lips_end(void);
static void set_lips3_font(FONT_INFO *, KFONT *, int, int, int);
static void move_cap(PIXEL, PIXEL);
static void move_homepoint(PIXEL, PIXEL);
static void pre_put_char(FONT_INFO *, PREAMBLE *, uint *, PIXEL *, PIXEL *);
static void put_jis_font(uint);
static void put_dl_font(uint);
static long get_dlhsize(int num);
static void pre_download(FONT_INFO *, DL_INFO *, int, int);
static void download_rastor(FONT_INFO *, DL_INFO *, uint, int);
static void post_download(FONT_INFO *, DL_INFO *);
static void lips_font_rotate(int);
static void tate_yoko(int);
static void lips_drawbox(PIXEL, PIXEL, PIXEL, PIXEL, int);

static void put_jis_font_VD(uint code);
static char *vd_int(int i);

static void nop();
#ifndef NO_NTTRPL
extern BOOL ntt_subst;
#endif
#ifdef	FDOWN
static int e_lbp_font = -1;	/* current font in G0 */

#endif
static int j_lbp_font = -1;	/* current font in G1 */
static tate_yoko_mode = 0;	/* 0 : 横書きモード, 1 : 縦書きモード */
static int font_angle = 0;	/* フォントの角度 */

static BOOL vd_mode_used = FALSE;	/* vd_mode を一度でも使ったか？*/
static char use_VD_flag;			/* 次の印字でVD_modeを使用するか？*/

extern PIXEL vert_divide;
extern BOOL f_rotate; /* -V などによる回転があるか否かのフラグ */
                    /* -y=...L や -V で TRUE になっている。 */
extern int last_dir;/* 最後に描画したフォントの種類．
					 * これが異なるときには再呼びだしが必要になる
					 * 0:DnLd l->r, 1:DnLd b->t, 2:DnLd r->l 3:DnLd t->d
					 * 4:漢字 l->r, 5:漢字 b->t, 6:漢字 r->l 7:漢字 t->d
					 * 8:漢字 (VD) */

extern long ptex_dpi_adj;
extern int on_edge_font;	/* 紙面からぎりぎりはみ出したjis fontを示す*/

extern DIMENSION dviout_dimension;

/* externals from prtinit.c */
extern char *youshi;	/* 用紙指定用コマンド文字列 */

#ifndef NNSZ
extern int length_to_dot(char *, int *, int);
#endif

#ifdef FDOWN
extern int maxdwidth;	/* download font width limit */
extern int maxdheight;	/* download font height limit */
extern int maxdfont;	/* num of kinds of download limit*/
#ifdef JDWN
extern int f_gaiji;
#endif
#endif

#ifdef	JDWN
extern int calc_realsize(PREAMBLE *, struct REAL_SIZE *);
#endif
 
/* lips_init で p_out の変数のデフォルトをセットする */
extern int weight_org;
extern int k_base_l;
extern int k_base_d;
extern int k_scale_l;
extern int lbp_orig_dpi;	/* LIPS3本来の dpi 値デフォルト300 */
#define	str_exp	tmp_buf
/* extern char str_exp[];	*/ /* 出力文字列作業用 */

/* externals from pret.c */
extern int g_font;

PREAMBLE *get_font(uint *, FONT_INFO *);
static uint change_code(uint code);

/* p_out.c routine call */
void pr_putnc(char *, int);
void pr_puts(char *);
void pr_putsn(char *, int);
void pr_putc(char);
void pr_int2(uint num);

int AtoI(char **);

static struct LIPS_LFONT lips_data[] =
{
	{"Mincho-Medium.J83", 80},
	{"Gothic-Medium.J83", 81},
	{"User", 80}
};
LBP_FUNC lips3_func =
{
	lips_init,	/* 初期化ルーチン */
	lips_page_format,	/* 初期化補助・ページフォーマットセット */
	lips_end,	/* 終了処理ルーチン */
	set_lips3_font,	/* 内蔵漢字フォントの設定 */
	move_cap,	/* CAPの絶対移動 */
	move_homepoint,	/* 描画原点の移動 */
	pre_put_char,	/* put_char 前処理 */
	put_jis_font,	/* put_char:jis漢字出力 */
	put_dl_font,	/* put_char:downloadフォント出力*/
	get_dlhsize,	/* dl data の ヘッダサイズ */
	pre_download,	/* download の前処理 */
	download_rastor,	/* ラスタイメージdownload */
	post_download,	/* download 後処理 */
	lips_drawbox,	/* -box 用 box 描画 */
	lips_font_rotate,	/* キャラクタを回転するコマンド */
	tate_yoko,	/* キャラクタを回転するコマンド */
	lips_data	/* lips内蔵フォントデータ */
};

static void nop()
{
}

static void pr_attr(int flag)
{
	if (flag & F_GOTH)
		pr_puts(BOLD);
	if (flag & F_SHADOW)
		pr_puts(SHADOW);
	if (flag & F_OUTLINE)
		pr_puts(OUTLINE);
	if (flag & F_FILL)
		pr_puts(PFILL);
	if (flag & F_GGOTH)
		pr_puts(BBOLD);
}

static void pr_normal(int flag)
{
	if (flag & (F_GOTH | F_GGOTH))
		pr_puts(NO_BOLD);
	if (flag & F_SHADOW)
		pr_puts(NO_SHADOW);
	if (flag & F_OUTLINE)
		pr_puts(NO_OUTLINE);
	if (flag & F_FILL)
		pr_puts(NO_PFILL);
}

void lips_end(void)
{
#ifndef NOTPIC_EXTENSION
	if (vd_mode_used){
		pr_puts(GOTO_VD_MODE);
		pr_puts(END_PICT);
		pr_puts(GOTO_TEXT_MODE);
	}
#endif
}

void lips_init(void)
{
	char *s;
	int paper, yoko, tate, houkou, kyuushi, c, landscape;

	if (k_base_l == 10000)
		k_base_l = K_BASE_L;
	if (k_scale_l == 10000)
		k_scale_l = K_SCALE_L;
	if (lbp_orig_dpi == 0)
		lbp_orig_dpi = LBP_ORIG_DPI;	/* LIPS3本来のdpi値300 */

	k_base_d = K_BASE_D;
	weight_org = WEIGHT;

#ifdef FDOWN
	maxdwidth = MAXDWIDTH;		/* maximal width of download font cell */
	maxdheight = MAXDHEIGHT;	/* maximal height of download font cell */
	maxdfont = MAXDFONT;		/* maximal number of download font sets */
#ifdef JDWN
	if (f_gaiji) return;
#endif
#endif

	pr_puts("\x1b" "%@");		/*  3 bytes: Text mode of LIPS */
	pr_putsn("\x90" "31;%u;1J\x9c", lbp_orig_dpi);
	/* 11 bytes: Start job: LIPS3, JIS code*/
	pr_puts(
			   "\x1b" "<"		/*  2 bytes: Software reset */
			   "\x9b" "11h"		/*  4 bytes: Unit is size */
			   "\x9b" "7 I"		/*  4 bytes: Size parameter is dot */
			   "\220" "2y"		/*  3 bytes: Display on LCD */
			   "DVI printing"	/* 12 bytes: Message */
			   "\234"			/*  1 byte : */
		);
	/*************************************************************
	-y 指定による用紙指定
*/
	s = youshi;
	/* Default : use installed cassette */
init:
	landscape = f_rotate;
	yoko = tate = paper = 0;
	kyuushi = -1;
	while (*s) {
		switch (toupper(*(s++))) {
		  case '/':
			  goto init;
		  case 'A':
			  if ((c = *(s++)) == '5')
				  paper = 16;	/* A5 portrait */
			  else if (c == '3')
				  paper = 12;	/* A3 portrait */
			  else
				  paper = 14;	/* A4 portrait */
			  goto label1;
		  case 'B':
			  kyuushi = -1;
			  if (*(s++) == '4')
				  paper = 24;	/* B4 portrait */
			  else
				  paper = 26;	/* B5 portrait */
			  goto label1;
		  case 'H':			/* Postcard */
			  paper = 18;
label1:
			  landscape = f_rotate;
			  while (isdigit(*s))
				  s++;
			  break;
		  case 'T':			/* Set user number */
			  landscape=f_rotate;
			  paper = AtoI(&s);
			  break;
		  case 'F':			/* Free size */
			  landscape=f_rotate;
			  paper = 80;
#ifdef	NNSZ
			  tate = 0;
			  yoko = tate = AtoI(&s);
			  if (*s == ':' || *s == ';') {
				  s++;
			  	  tate = AtoI(&s);
			  }
#else
			  s += length_to_dot(s, &yoko, 0);
			  if (*s == ':' || *s == ';'){
				  s++;
				  s += length_to_dot(s, &tate, 1);
			  }
#endif
			  else{
				tate = yoko;
			  }
			  break;
		  case 'L':
			  landscape=TRUE;
			  goto label2;
		  case 'P':
		  	  landscape=FALSE;
label2:
			  if (isdigit(*s))
			  	  kyuushi = AtoI(&s);
			  break;
		}
	}
	if (landscape) {
		paper++;				/* portrait --> landscape */
	}
	pr_puts("\x9b" "?2;3;23;25h");	/* 12 bytes: No auto-FF, No move CAP,
												 Poor man's bold */
	pr_puts("\x9b" "?1;4;5;6;27l");	/* 13 bytes: No auto-LF, up margine,
											 LF without CR, FF without CR
												 No original attribute */
	sprintf(str_exp, "\x9b" "%u;%u;%up", paper, yoko, tate);
	pr_puts(str_exp);		/* 用紙設定: paper<>80,81 ではyoko,takeは無視 */

	/* -y=A4P のように給紙指定を省略した場合 LBP での設定を優先 */
	if (kyuushi>=0)
		pr_putsn("\x09b" "%uq", kyuushi);	/*給紙モードの設定*/

	pr_putsn("\x09b" "%u;0 G",vert_divide);	/* 6+α bytes: VMI = vert_unit_bit, HMI = 0 */
	/* これは必ず用紙設定の後ろにすること！ */
/*
#ifndef	NOTATEGAKI
	if (tategaki) {
		pr_puts("\x9b" "?29h");
	}
#endif
*/
	/*************************************************************
	pTeX の縦書き時の印字位置補正計算用
*/
	ptex_dpi_adj = (long)lbp_orig_dpi *100L;

}

static int graytab[] =
{9,	   /* 真っ白 （使用していない）*/
 12,   /* 薄いグレー */
 13,   /* 濃いグレー */
 3	   /* 真っ黒 （使用していない）*/
};
static void lips_drawbox(PIXEL vs, PIXEL hs, PIXEL height, PIXEL width, int tone)
{
	int graylevel;
	int vd, hd;
	graylevel = graytab[tone];
	move_cap(vs, hs);
	vd=-height;
	hd=width;
#ifndef NOTPIC_EXTENSION
	switch(font_angle){
		case   0:	break;
		case  90:	vd=-width; hd=-height;	break;
		case 180:	vd=+height;hd=-width;	break;
		case 270:	vd= width; hd= height;	break;
		default:{	double angle;int s1,c1,s2,c2;
					pr_puts("\x9b{");
					angle = (double)font_angle * M_PI / 180.0;
					s1 = (int)(sin(angle)*height);
					c1 = (int)(cos(angle)*height);
					s2 = (int)(sin(angle)*width);
					c2 = (int)(cos(angle)*width);
					move_cap(vs-=c1, hs-=s1);
					pr_puts("\x9b;1}\x9b{");
					move_cap(vs-=s2, hs+=c2);
					pr_puts("\x9b;1}\x9b{");
					move_cap(vs+=c1, hs+=s1);
					pr_puts("\x9b;1}\x9b{");
					move_cap(vs+=s2, hs-=c2);
					pr_puts("\x9b;1}");
					return;
				}
	}
#endif
	pr_puts("\x9b{");
	move_cap(vs + vd, hs + hd);
	pr_putsn("\x9b;;;%d}", graylevel);
}

static void set_lips3_font(FONT_INFO *fontc, KFONT *kf, int attr, int weight, int face)
{
	int width,height;

	ENTER("set_lips3_font_size");
	/* select font */
	g_font = (fontc->f_goth & (F_ATTR | F_LBP));	/*内蔵フォントで使う属性を得る*/

	pr_putc(SHIFTOUT);			/* call G1 */
	pr_puts(G1GRPH2);			/* select Graphic Set */
	pr_putc(JIS83 - 0x80);
	if ( fontc->f_goth & F_TATE ){
		width = kf->height;
		height = kf->width;
	}
	else{
		width = kf->width;
		height = kf->height;
	}
	pr_putsn(CHR_PITCH, ptex_dpi_adj/width);	/* select pitch */
	pr_putsn(CHR_SIZE, height);	/* select font height */
	pr_putsn(FWEIGHT, weight);	/* select weight, style=23 */
	pr_putsn(FACE, face);		/* select face */
#ifndef NO_NTTRPL
	if (ntt_subst && (fontc->code_offset >= 0))
		pr_putsn(ASSIGN_G1, fontc->family_code);
	else
#endif
	pr_putsn(ASSIGN_G1, fontc->font_code);	/* assign font_number */
	pr_putc(SHIFTIN);			/* recover G0 */
	j_lbp_font = -1;
#ifndef NOTTPIC_EXTENSION
 	/* VD mode での印字のため */
	fontc->lbp_font_inf = (face-0x80) & 0xf;
	fontc->lbp_font_inf |= ((attr&(F_GOTH|F_GGOTH))!=0)<<4;
	fontc->lbp_font_inf |= ((attr&F_GGOTH)!=0)<<5;
	fontc->lbp_font_inf |= ((attr&F_OUTLINE)!=0)<<6;
	fontc->lbp_font_inf |= (int)(((long)height*100L/width) & 0xff)<<8;
#endif
	END();
}

static PIXEL v_offset = 0, h_offset = 0;	/* Refered by move_cap & move_homepoint */
static PIXEL last_V = 0, last_H = 0;	/* Last CAP position */
static PIXEL VD_last_V = 0, VD_last_H = 0;	/* Last CAP position on VD mode*/

/* debugged by 泉　雅晴氏, modified by OkI */
static void move_cap(PIXEL v, PIXEL h)
{
	/* 90単位以外の文字回転 or 420dot以上の文字 or on_edge_font==TRUE */
	if (use_VD_flag){
		VD_last_H = h+h_offset;
		VD_last_V = v+v_offset;
		goto end_move_cap;
	}
	if (v == -1) {				/* reset last CAP position */
end_move_cap:
		last_V = last_H = -1;
		return;
	}
	v += v_offset;
	h += h_offset;
	if (v == last_V && h > last_H)
		sprintf(str_exp, MOVE_RIGHT, h - last_H);
	else if (h == last_H && v > last_V)
		sprintf(str_exp, MOVE_BELOW, v - last_V);
	else {
		sprintf(str_exp, MOVE_CAP, v, h);
		/* When v==0 (h==0), CAP moves the posion of v==1(h==1) not 0.
	   Then relative move of -1 dot is required after then.         */
		if (v == 0)
			strcat(str_exp, MOVE_ABOVE1);
		if (h == 0)
			strcat(str_exp, MOVE_LEFT1);
	}
	pr_puts(str_exp);
	last_V = v;
	last_H = h;
}

/* x,y の順が逆になっていることに注意！ */
static void move_homepoint(PIXEL v, PIXEL h)
{
	v_offset = 0;
	h_offset = 0;
	move_cap(v, h);
	pr_puts(SET_POS);
	pr_puts("\x9b" "0t");
	v_offset = v;
	h_offset = h;
	last_H = last_V = -1;
}

static int f = -1;
static int last_attr = -1;
static int knjwidth;
static int knjheight;
static int knjface;
static int knjfg;

/*以下のルーチンは put_out_char から呼ばれます．*/
static void pre_put_char(FONT_INFO *font, PREAMBLE *pxl, uint *code, PIXEL *h, PIXEL *v)
{
#ifndef NO_NTTRPL
	if (ntt_subst && (font->code_offset >= 0)) {
		if (f != font->family_code) {
			f = font->family_code;
			goto Normal;
		}
	}
	else
#endif
	if (f != font->font_code) {
		f = font->font_code;
Normal:	pr_normal(last_attr);
		last_attr = 0;
	}
	if (*code & 0xff00){
		knjwidth = pxl->width;
		knjheight = (int)((long) (pxl->height) * ((font->lbp_font_inf & 0xff00) >> 8) / 100);
		use_VD_flag = 0;
		if (knjheight > 420 || knjwidth > 420
#ifndef NOTPIC_EXTENSION
		|| font_angle % 90 != 0
#endif
		|| on_edge_font){
			use_VD_flag++;
			knjface = (font->lbp_font_inf & 0xf) + 0x80;
			knjfg = (font->lbp_font_inf & 0x70) >> 4;
			
			if (!vd_mode_used){
				pr_puts(GOTO_VD_MODE);
				pr_puts(VD_FONT_DECL);
				pr_puts(VD_GSET_DECL);
				vd_mode_used = TRUE;
				pr_puts(START_PICT);			/* start picture */
				pr_puts(SET_VD_UNIT);			/* set VD mode unit (= dot) */
				pr_puts(DRAW_START);			/* set VD mode unit (= dot) */
				vd_mode_used = TRUE;
				pr_puts(GOTO_TEXT_MODE);
			}
		}
	}
	on_edge_font=0;
}

static void lips_font_rotate(int ang)
{
/*	pr_putsn("\x9b" "%d&t", ang); */
	font_angle = ang;
}

static void put_jis_font(uint code)
{
	if (tate_yoko_mode == 1) {
		/* 縦書き用フォントにコード変換 */
		code = change_code(code);
	}

/* VD mode is used when the character rotated or larger than 420 dot is used. */
	if (use_VD_flag){
		put_jis_font_VD(code);
		use_VD_flag=0;
		return;
	}

	if (last_dir > 7 || last_dir < 4 || f != j_lbp_font)
		pr_putsn(CHANGE_G1, j_lbp_font = f);	/* change G1 font */

	if ((font_angle / 90) != last_dir && (font_angle / 90) + 4 != last_dir
#if 0  /* ndef NOTPIC_EXTENSION */
	&& (font_angle % 90 == 0)
#endif
	)
		pr_putsn("\x9b" "%d&t", font_angle);

	last_dir = 4 + (font_angle / 90);	/*漢字スケーラブルフォント*/

	if ((g_font & F_ATTR) != last_attr)
		pr_attr(last_attr = (g_font & F_ATTR));
	pr_int2(code | 0x8080);		/* output JIS code */
}

#define	MUL 100
static void put_jis_font_VD(uint code)
{
	static int last_angle=0;
	static int last_f=-1;
	int xstp,ystp;

	last_dir = 8;
	pr_puts(GOTO_VD_MODE);
	sprintf(str_exp, VD_CHANGE_G0, vd_int(knjface - 0x7f));
	pr_puts(str_exp);
	sprintf(str_exp, VD_CHANGE_G1, vd_int(knjface - 0x7f));
	pr_puts(str_exp);
	{
		double angle;
		int s,c;
		angle = (double)font_angle * M_PI / 180.0;
		pr_putc(VD_FONT_ROT);
		s = (int)(sin(angle)*MUL);
		c = (int)(cos(angle)*MUL);
		pr_puts(vd_int(-s));
		pr_puts(vd_int(-c));
		s *= (double)knjwidth/(double)knjheight;
		c *= (double)knjwidth/(double)knjheight;
		pr_puts(vd_int(c));
		pr_puts(vd_int(-s));
		pr_putc('\x1e');
		xstp = (c>50)-(c<-50);
		ystp = (s<-50)-(s>50);
	}
	pr_puts(VD_FONT_LEVEL);
	sprintf(str_exp, VD_FONT_HEIGHT, vd_int(knjheight));
	pr_puts(str_exp);
	if (knjfg & VDF_OUTLINE){
		pr_puts(VD_OUTLINE);
	}else{
		pr_puts(VD_NORMAL);
	}
	{char ct=0;
repeat:
	pr_puts(VD_PUT_CHAR1);
	pr_puts(vd_int(VD_last_H));
	pr_puts(vd_int(VD_last_V+60));
	pr_puts(VD_PUT_CHAR2);
	pr_int2(code | 0x8080);
	pr_puts("\x1e");
	ct++;
	if ( (ct==1 && (knjfg & VDF_GOTH)) || (ct==2 && (knjfg & VDF_GGOTH))){
		last_H+=xstp;
		last_V+=ystp;
#if	0
		printf("[repeat]");
#endif
		goto repeat;
	}}
	pr_puts(GOTO_TEXT_MODE);
}
#undef MUL

#define	SHIFT_ASSIGN	0x200

static void put_dl_font(uint code)
	/* p_tex フラグに応じてダウンロードフォントを適宜回転して印刷 */
{
	if (code & 0x80) {
		f += SHIFT_ASSIGN;
		code &= 0x7f;
	}
	if (last_dir>3 || last_dir<0 || f != e_lbp_font)	/* change G0 font */
		pr_putsn(CHANGE_G0, e_lbp_font = f);

	if (((font_angle / 90) != last_dir && (font_angle / 90) + 4 != last_dir)
	&& (font_angle % 90 == 0))
		pr_putsn("\x9b" "%d&t", font_angle);

	last_dir = (font_angle / 90);
	if (code <= 0x20 || code == 0x7f)
		pr_puts(SPECIALC);
	pr_putc(code);				/* output ASC code */
}

static void tate_yoko(int mode)
{
	/* mode = 0 : 横書きモード, 1 : 縦書きモード */
	tate_yoko_mode = mode;
}
#ifdef	FDOWN

static long get_dlhsize(int num)
{
	return (long)num *D_HEAD;
}

static void pre_download(FONT_INFO *dfont, DL_INFO *dl,
						 int num_dfont, int flag)
{
	if (flag)
		dl->assign_num += SHIFT_ASSIGN;
	pr_putsn("\220%d;1x\234", dl->assign_num);	/* assign a number to FONT */

	sprintf(str_exp, "\233%ld;%d;0;0;%d;", dl->total_send - dl->total_off,
			dl->numoffonts, 3840 + num_dfont);
	pr_puts(str_exp);			/* total bytes to send */
	/* total number of characters */
	/* default mark = always 0 */
	/* font orientation 0: portrait */
	/* graphic set number */

	pr_putsn("8;20;100;0;0;200;%d;", dl->maxwidth);
	/* spacing flag 8: fixed pitch, real size */
	/* pitch (characters/inch)*100 */
	/* character size */
	/* style */
	/* weight */
	/* shotai number */
	/* cell width */

	pr_putsn("%d;1;2;0;0;0;1.p", dl->maxheight + 1);
	/* cell height */
	/* baseline */
	/* under line */
	/* flag of length of character code */
	/* level to keep 0: temporary */
	/* signature of baseline */
	/* flag of control characters */

}


static void download_rastor(FONT_INFO *dfont, DL_INFO *dl, uint code, int flag)
{
	PREAMBLE *preamble;
	uint tmp;
	BUFFER *pat;
	BUFFER *pat0;
	struct REAL_SIZE size;
	int width, height, bit_off, bit_get, i;

	tmp = flag + code;
	preamble = get_font(&tmp, dfont);
	calc_realsize(preamble, &size);

	pr_putc(code);						/* character code */
	pr_int2(width = size.right - size.left);
										/* real width */
	pr_int2(size.left);					/* x-offset */
	pr_int2(height = size.bottom - size.top);
										/* real height */
	pr_int2(size.bottom - preamble->height);	/* y-offset */

	bit_off = size.left & 7;
	bit_get = 8 - bit_off;

	pat0 = preamble->raster + size.top*preamble->byte_width + size.left/8;
	while (height--){
		pat = pat0;
		for(i = width; i > 0; i -= 8){
			tmp = *pat++;
			if (bit_off){
				tmp <<= bit_off;
				if(i > bit_get) tmp |= ((uchar)*pat >> bit_get);
			}
			pr_putc(tmp & 0xff);
		}
		pat0 += preamble->byte_width;
	}
}

static void post_download(FONT_INFO *dfont, DL_INFO *dl)
{
}

#endif

static uint change_code(uint code)
{
	ENTER(change_code);
	if (code < 0x2122 || (code > 0x2166 && code < 0x2421) || code > 0x2576)
		return code;

	if (code >= 0x2141 && code <= 0x2145)
		code += 0x70c;
	else if (code >= 0x2146 && code <= 0x2149)
		code += 0xce2;
	else if (code >= 0x214a && code <= 0x215b)
		code += 0x708;
	else if (code >= 0x2162 && code <= 0x2166)
		code += 0xcce;
	else {
		switch (code) {
		  case 0x2122:
		  case 0x2123:
			  code += 0x724;
			  break;
		  case 0x2124:
		  case 0x2125:
			  code += 0xcfd;
			  break;
		  case 0x2127:
		  case 0x2128:
			  code += 0xd06;
			  break;
		  case 0x2131:
		  case 0x2132:
			  code += 0x717;
			  break;
		  case 0x213c:
		  case 0x213d:
		  case 0x213e:
			  code += 0x70e;
			  break;
		  case 0x215d:
			  code = 0x2e2f;
			  break;
		  case 0x2161:
			  code = 0x2846;
			  break;
		  case 0x2162:
			  code = 0x2e30;
			  break;
		  case 0x2421:
			  code = 0x2865;
			  break;
		  case 0x2423:
			  code = 0x2866;
			  break;
		  case 0x2425:
			  code = 0x2867;
			  break;
		  case 0x2427:
			  code = 0x2868;
			  break;
		  case 0x2429:
			  code = 0x2869;
			  break;
		  case 0x2443:
			  code = 0x286e;
			  break;
		  case 0x2463:
			  code = 0x286a;
			  break;
		  case 0x2465:
			  code = 0x286b;
			  break;
		  case 0x2467:
			  code = 0x286c;
			  break;
		  case 0x246e:
			  code = 0x286e;
			  break;
		  case 0x2521:
			  code = 0x286f;
			  break;
		  case 0x2523:
			  code = 0x2870;
			  break;
		  case 0x2525:
			  code = 0x2871;
			  break;
		  case 0x2527:
			  code = 0x2872;
			  break;
		  case 0x2529:
			  code = 0x2873;
			  break;
		  case 0x2543:
			  code = 0x2878;
			  break;
		  case 0x2563:
			  code = 0x2874;
			  break;
		  case 0x2565:
			  code = 0x2875;
			  break;
		  case 0x2567:
			  code = 0x2876;
			  break;
		  case 0x256e:
			  code = 0x2877;
			  break;
		  case 0x2575:
			  code = 0x2879;
			  break;
		  case 0x2576:
			  code = 0x287a;
			  break;
		}
	}
	RETURN(code);
}
static void lips_page_format(int ff_rotate, int f_copy)
{
	if (ff_rotate) {
		pr_puts(ROTATE);
		move_homepoint(0, 0);	/* ホームポジション記憶番号に再設定する */
	}
	if (f_copy)
		pr_putsn(COPYS, f_copy);
}

#ifndef NOTPIC_EXTENSION
static char *vd_int(int i)
{
	static char st[4];
	char *pt;
	int neg=0;

	if (i<0){
		i=-i;
		neg++;
	}
	pt = st;
	if (i > 1023)
		*(pt++) = (((i >> 10) & 0x3f) | 0x40);
	if (i > 15)
		*(pt++) = (((i >> 4) & 0x3f) | 0x40);
	*(pt++) = ((i & 15) | ((neg)? 0x20 : 0x30));
	*pt = 0;
	return st;
}
#endif
