/*
 *	TEX Device Driver
 *	epsbox.c:	epsbox specials support routines
 *				by uchiyama@bacchus.in.kobe-u.ac.jp		25 September 1992
 *
 *	【注意】
 *	  これは松下電器産業(株)情報システム研究所によって開発された
 *	  jdvi2kps を基に作成されています．したがって以下の関数は
 *	  松下電器産業(株)情報システム研究所に著作権がありますので
 *	  その取扱は jdvi2kps の copyright ファイルに記された内容に
 *	  従わなければなりません．
 *	　■対象となる関数
 *		DoPostScriptBox()	jdvi2kps の postscript.c から必要部分を引用
 *		epsbox_pret()		同上の do_special() から必要部分を引用
 *
 *	Modified for epsfile=, EMS etc. by SHIMA			11 February	 1993
 *	Modified for pbmfile=  by Yakumo					 5 February	 1993
 *	Modified for adjustment of size by Yakumo, SHIMA	14 February	 1993
 *	Include 淺山's GIF decoder (SHIMA)					17 February	 1993
 *	Modified for file= by SHIMA							18 April	 1993
 *  Exclude GIF decoder(SHIMA)							 5 November  1999
 */

#ifdef WIN32
#include "dviout.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>

#define	BMC				1
#define	B_HEAD_EPSF		0

#ifdef	 UNIX
#include <unistd.h>
#include <sys/wait.h>
#else
#include <io.h>
#ifdef MSVC
#include "msvcdir.h"
#else
#include <dir.h>
#endif
#include <process.h>
#ifdef	GCC1
#include <djgppstd.h>
#else
#ifdef MSVC
#include <malloc.h>
#else
#include <alloc.h>
#endif
#endif
#endif

#define _DEF_STDIO_H_
#include "err.h"
#include "inter.h"
#ifndef NOPSFRAG
# include "dviread.h"
#endif

#define	NO_DIVIDE	1

#if NO_DIVIDE
#define	MAX_BMP_SIZE 100000000	/* maximal BMP data size by PIXEL 1000*1000 */
								/* An image is divided if its size is larger */
#else
#define	MAX_BMP_SIZE 1000000
#endif

#define	SIZEOF_BITMAPFILEHEADER	14
#define	SIZEOF_BITMAPINFOHEADER	40


						/* different EPS/PS filenames kept for a page */
#define	MAX_PS_NAME	512
#define	MAX_PS_BUF	0x2000

					/* maximal number of tempolary PBM files for a page */
#define	MAX_PS		999

#ifdef	USE_COLOR
#define	MAX_BMP			0x10000
				/* maximal number of colored objects, 20 byte for a object */
#define	UNIT_BMP		0x1000

#define	MAX_COLOR	256
				/* maximal depth of stack for color specials */

#define	MAX_CH_BMP	0x8000000	/* 64K * 2048 = 128 M byte */
				/* maximal byte to keep colored rotated characters & lines */
#endif

#define	gs_argv	((char **)(tmp_buf + 512))
#define	ps_path	(tmp_buf + 1024)

/* main.c */
extern DVIFILE_INFO dvifile;

/* option.c */
int length_to_sp(char *, SCALED_PT *);

/* int.c prtinit.c */
char *GetTmpDir(void);
extern  int f_tpic_turn_on;	/* default is 1 */
#ifdef	DVI_ADD
FILE *OpenAddFile(char *, char *);
int GetAddMemory(char *, char *, int);
#endif


extern DIMENSION dviout_dimension;
extern int enlarge;
extern int org_mag;

/* err.c */
extern int f_wait;

/* fontdef.c */
BOOL copy_token(char *, char **, int);
BOOL ExecBatch(char *, int);

/* pret.c */
PIXEL get_current_x(void);
PIXEL get_current_y(void);
BOOL papersize_special(char *);
void do_special(char *);
char *find_key(char *, char *);
char *find_key0(char *, char *);
#ifdef	HYPERTEX
void add_hyper_box0(PIXEL, PIXEL, PIXEL, PIXEL);
extern f_hyper;
#endif
#ifndef NOPSFRAG
void save_dvi_state(BOOL);
void restore_dvi_state(void);
void set_current_xy(SCALED_PT , SCALED_PT);
void get_current_xy(SCALED_PT *, SCALED_PT *);
#endif
void set_dviout_initialize(char *);
extern int id_papersize;

/* bitmap.c */
void write_pbm(PIXEL h, PIXEL v, PIXEL w, PIXEL d, char *raster);
void write_tiled_pbm(PIXEL h, PIXEL v, PIXEL w, PIXEL d, char *raster, int tl);
void bitmap_fill(uchar ch);

/* bitblt.c */
void push_rot_matrix(int mode);
void rotate_address(PIXEL *xp, PIXEL *yp);
void alter_bitblt_ow(BOOL flag);

/* sptopxl.asm or size.c (prtsize.c) */
PIXEL sptopixel( SCALED_PT sp );
PIXEL vtopixel( SCALED_PT sp );

/* buffer.c */
void *marea(unsigned int);

/* option.c */
int make_path(char *path, char *dir, char *name, char *ext);

/* putdvi.c */
extern current_page;

/* loadpk.c */
FILE *fopenf(char *name, char *mode);

/* bitmap.c */
void boxpic(PIXEL h, PIXEL v, PIXEL w, PIXEL d);

/* device.c */
void device_pause(void);
void device_cont(void);

#ifdef	WIN32G
/* wmain.c */
void DisplayMessage(char *);
void Detain( void );
void Surmount( void );
void Passable( void );
void Wait( unsigned long int );

/* tabctrl.c */
void SearchFile(char *);
void ReserveStringPara(char *, char *);
void GetGS_LIB(char *);

/* inter.c */
extern int	id_dvi;

/* misc.c */
char *dup_string(char *);
#ifdef	USE_WINAPI
int WinMinExecute(char **, int, BOOL);
extern f_osversion;
#endif

/*
	f_mode_BMP & 0xff =	 2		1	bit color
						 3		4	bit color
					//	 103	4	bit color using 2 colors b/w in palet
						 4		8	bit color
					//	 104	8	bit color using 2 colors b/w in palet
						 5		16	bit color
						 6		24	bit color
						 7		32	bit color
*/
#include "help_id.h"
void ShowWinHelp(int);
#else
#define	DisplayMessage(x)
#define	ShowWinHelp(x)
#endif

// void CheckGraphic(void);

int f_mode_BMP;

#ifndef NOTPIC_EXTENSION
/* tpic.c */
void tpic_rt(char *);
#endif

/* gray.c */
BUFFER *KeepBMPBuf(BUFFER *, int, int, int, int, int, BUFFER **);
int sizeofBMP(BUFFER *);

/* p_out.c */
#ifdef WIN32
#define gray_number g_winData.dviwin.gamma
#else
extern int gray_number;
#endif

#ifdef	USE_ETF
/* ttfont.c */
BOOL f_make_imgetf;
BOOL SetETFimg(char *);
#endif

extern DIMENSION dviout_dimension;

/* called by xxx1() in pret.c. interface is func ptr (esbox_special) */
					/* interpret special. Ret TRUE if found */
static BOOL epsbox_pret(char *special);
BOOL (*epsbox_special)(char *special) = epsbox_pret;
static BOOL put_pbm(char *epsfname, PIXEL h, PIXEL v,
	PIXEL width, PIXEL height, int mode , int fgbox);
void reset_gsps(void);
static void name_pbm(char *name);
static BOOL do_gsps(char *str);
static BOOL DoPostScriptBox(char *epsname, float width, float height,
	float hscale, float vscale, float hhscale, float vvscale, int mode);
static void do_gspostscriptbox(char *epsfname, int x, int y, int a, int b,
	FILE *fp);
static void exec_gs(char* pbm, char** argv, int mode);
static FILE *open_pbm(char *epsname, PIXEL *x, PIXEL *y, int mode);
/* static void putpbm(char *epsfname, PIXEL h, PIXEL v); */
static void get_pbmname(char *filename);
static int find_psname(char *path);
static float get_pt(char *sf);
static void adjust_width(void);
static void output_line(void);
static void count_gsps(void);
static void pret_file(char *);
static char *dvipath(char *);
char *MakeTmpPath(char *);
int ExpandGZ(char *, FILE **, char *);
static BOOL lib_ps(char *);

#if	BMC
BOOL bmp2bmc(char *, unsigned char *, int);
#endif
#ifdef	USE_COLOR
void ClearKeepBMP(void);
static void pret_color(char *, int);
uint GetWMF(char *, int);
void FreeWMF(uint , int);
#endif

#ifdef	UNIX
#define	chg_pathsep(x,y)
#define	Stricmp	strcmp
#else
#define	Stricmp	stricmp
void chg_pathsep(uchar *path, char ch);
#endif

/*-->DoPostScriptBox*/
/**********************************************************************/
/*************************	DoPostScriptBox	 **************************/
/**********************************************************************/

#define	Min(a, b)	((a) > (b) ? (b) : (a))
#define	Max(a, b)	((a) < (b) ? (b) : (a))
#define	Abs(n)		(((n) >= 0) ? (n) : -(n))
#define False 0
#define True 1

int current_gsps;
#ifdef	WIN32G
static int old_id_dvi;
static int f_search_GS;
#endif
static int old_f_GIF;

extern char *pbm_path;
int	f_GS = 1;
BOOL f_gsame = 1;
static int f_scale;
static int f_taterot;

extern int	f_GIF;
BOOL f_gbox;
extern BOOL f_gsize;
extern BOOL f_gow;
extern BOOL f_gclip;
extern char *gs_exe;

static float dpi, DPI, hoffset, voffset;
static int ps_page, total_gsps, add_length;
static int flg_rev;		/* black <-> while Reverse? */
static int bmp_rev;
static int bmp_off;
static int bmp_on;

static int	f_erace;

#ifdef GIF
static int current_f_GIF;
#endif

#define	F_GS		(f_GS&0x0f)
#define	DO_GS		0x1
#define	DO_GSV		0x2
#define	DO_SPBM		0x3
#define	DO_PBM		0x4
#define	DO_GSS		0x5

#define	IS_SCALE	0x008000
#define	IS_HOFFSET	0x004000
#define	IS_VOFFSET	0x002000
#define	IS_TILE		0x001000
#define	IS_POS		0x000800
#define	IS_POSXY	0x000400
#define	IS_BMP		0x000200
#define	IS_BW		0x000100
#define	IS_GSAME	0x010000

#define	IS_BMC		0x020000
#define	IS_PLUG		0x040000
#define	IS_WMF		0x080000
#define	IS_EMF		0x100000
#define IS_PNG		0x200000
#define IS_JPG		0x400000
#define	IS_COL16	0x000400

#define	MAX_KEY		11
#define	KEY_TYPE	0x0f

enum{ EPSBOX = 0,
	  EPS,
	  PS,
	  PBM,
	  GIFF,
	  SPFILE,
	  PSFILE,
	  BMP,
	  PNG,
	  JPG,
	  CCOLOR,
	  BACKGROUND
};

static char *PS_KEY[MAX_KEY] = {
		"epsfile",
		"psfile",
		"pbmfile",
		"giffile",
		"file",
		"PSfile",
		"bmpfile",
		"pngfile",
		"jpgfile",
		"color",
		"background"
};

static char	*key_opt[] ={
	"hsize", "vsize", "hoffset", "voffset", "hscale", "vscale", "scale", 
	"truesize", "llx", "lly", "urx", "ury", "rwi", "rhi", "clip", "reverse", 
	"width", "height", "truedirection",  "watermark",
#ifdef	TILE
	"tile",
#endif
	""};

enum {
	Hsize=0, Vsize, Hoffset, Voffset, Hscale, Vscale, Scale, REAL,
	Llx, Lly, Urx, Ury, Rwi, Rhi, Clip, Rev, Width, Height, REALDIR,
	WATERMARK,
#ifdef	TILE
	,Tile
#endif
};

#ifdef	PLUG
int open_plugin(uchar *, int, uchar **, uchar **);

static char *graph_ext[] =
{
	"jpg",
	"jpe",
	"jpeg",

	"gif",

	"tif",
	"tiff",

	"pcd",

	NULL
};

static int graph_type[] = {0, 0, 0, 1, 2, 2, 3, 4};
#endif

#if	BMC
static uchar *bmc_buf;
static uchar *bmc_pt;
static uchar *bmc_end;

void write_num(unsigned char *s, int byte, int num)
{
	switch(byte){
		case 4:
			s[3] = (num>>24);
		case 3:
			s[2] = (num>>16) & 0xff;
		case 2:
			s[1] = (num>>8) & 0xff;
		default:
			s[0] = num & 0xff;
	}
}

int read_num(unsigned char *s, int byte)
{
	int num = *s;

	switch(byte){
		case 4:
			num += (s[3]<<24);
		case 3:
			num += (s[2]<<16);
		case 2:
			num += (s[1]<<8);
	}
	return num;
}

static int Fseek(FILE *fp, long offset, int whence)
{
	if(fp)
		return fseek(fp, offset, whence);
	if(whence == SEEK_SET)
		bmc_pt = bmc_buf + offset;
	return 0;
}

static size_t Fread(void *ptr, size_t size, size_t n, FILE *fp)
{
	int total;

	if(fp)
		return fread(ptr, size, n, fp);
	total = size*n;
	if(bmc_end - bmc_pt < total)
		total = bmc_end - bmc_pt;
	memcpy(ptr, bmc_pt, total);
	bmc_pt += total;
	return total;
}

static int Getc(FILE *fp)
{
	if(fp)
		return getc(fp);
	return (bmc_pt < bmc_end)? *bmc_pt++:EOF;
}

static int Fclose(FILE *fp)
{
	if(fp)
		return fclose(fp);
	Free0(bmc_buf);
	bmc_buf = bmc_pt = bmc_end = NULL;
	return 0;
}

#else
#define	Fseek(x,y,z)	fseek(x,y,z)
#define	Fread(x,y,z,w)	fread(x,y,z,w)
#define	Fclose(x)		fclose(x)
#define	Getc(x)			getc(x)
#endif

static char *ps_name[MAX_PS_NAME];
static char ps_name_buf[MAX_PS_BUF];

static char tmp_doboxpath[MAXFILE];
static char org_ps_path[MAXFILE];

static FILE *search_ps(char *name)
{
	FILE *fp;
	int	i, ch;
	char ppath[MAXFILE], *tmp;

	strncpy(ps_path, name, MAXFILE-1);
	ps_path[MAXFILE-1] = 0;
	chg_pathsep(ps_path, PATH_SEP);
	if(
#ifdef	DVI_ADD
		(fp = OpenAddFile(ps_path, "r")) != NULL ||
#endif
		(fp = fopenf(ps_path, "r")) != NULL)
		return fp;
	tmp = pbm_path;
	for (i = strlen(current_name); i >= 0; ){
		ps_path[i] = 0;
		if(!i ||
		  (ch = current_name[--i]) == '\\' || ch == '/' || ch == ':')
			break;
	}
	for( ;i >= 0; i--) ps_path[i] = current_name[i]; 
	strcat(ps_path, name);
	for (i = 0; i < 3; i++){
		switch(i){
			case 1:
				ppath[0] = 0;
				if(tmp == NULL)
					continue;
				if(copy_token(ppath, &tmp, DELIMITER))
					i--;
				make_path((char*)ps_path, ppath, name, NULL);
				break;
			case 2:
				strcpy((char *)ps_path, dvipath((char *)ps_path));
				break;
		}
		if ((fp = fopenf((char *)ps_path, "r")) != NULL)
			break;
	}
	return(fp);
}

#ifndef NOPSFRAG
struct header_list {
	struct header_list *next;
	char name[];
};

struct header_list *headers = NULL;

struct fraginfo_list {
	struct fraginfo_list *next;
	float llx, lly, dxx, dxy, dyx, dyy, rot, base;
	char keyword[];
};
struct fraginfo_list *fraginfo = NULL;

#define MAX_POSITIONS 64
struct {
	float x, y;
	float rot, scl;
} psf_position[MAX_POSITIONS];

BOOL f_hide = FALSE;
float psf_hsc = 1, psf_vsc = 1, psf_hof = 0, psf_vof = 0;
SCALED_PT psf_h = 0, psf_v = 0;

static char *psfrag_str[3];
static int f_psfrag = 0;
static BOOL psf_rot = FALSE;
static BOOL f_watermark = 0;

BOOL header_special(char *str, int mode)
{
	struct header_list *p, *q;

	while(*str == ' ') str++;
	if (!strsubcmp(str, "header=")){
#ifdef	WIN32G
		if(strsubcmp(str, "dviout `initialize ")){
			if(!mode)
				set_dviout_initialize(str + 19);
		}else if(papersize_special(str)){
			if(id_papersize != id_dvi){
				if(mode)
					return FALSE;
				else
					set_dviout_initialize(common_work);
			}
			return TRUE;
		}
#endif
		return (FALSE);
	}
	str += 7;
	while(*str == ' ') str++;
	/* check redundancy */
	for (p = headers; p != NULL; p = p->next) {
		if (strcmp(p->name, str) == 0) return (TRUE);
	}
	/* add a header */
	q = (struct header_list *)
		marea(sizeof(struct header_list) + strlen(str) + 1);
	strcpy(q->name, str);
	q->next = NULL;
	if (headers == NULL) {
		headers = q;
	} else {
		for (p = headers; p->next != NULL; p = p->next);
		p->next = q;
	}
	return (TRUE);
}

void header_special_init(FILE *fp)
{
	int code;
	long size;
	char *str;
	struct header_list *p, *q;

	/* clear headers */
	if ((p = headers) != NULL) {
		while (p) {
			q = p->next;
			Free(p);
			p = q;
		}
		headers = NULL;
	}
	if (f_psfrag > 3) f_psfrag = 3;
	while (f_psfrag > 0) {
		Free(psfrag_str[--f_psfrag]);
	}
	f_hide = FALSE;
	save_dvi_state(FALSE);
	/* skip pre & bop */
	fseek(fp, 12, SEEK_CUR);
	code = (uchar)read_byte(fp);
	fseek(fp, code + 45, SEEK_CUR);
	/* scan header specials */
	while ((code = (uchar)read_byte(fp)) != EOP) {
		if (code < XXX1 || code >= FNT_DEF_1) break;
		size = read_n(fp, code - XXX1 + 1);
		if ((str = (char *)marea(size + 1)) == NULL) break;
		fread(str, size, 1, fp);
		str[size] = '\0';
		header_special(str, 0);
		Free(str);
	}
	return;
}

void put_headers(FILE *fp)
{
	struct header_list *p;

	for (p = headers; p != NULL; p = p->next) {
		if(!lib_ps(p->name))
			error(WARNING, "Cannot find '%s'.", p->name);
		fprintf(fp, "(%s) runlibfile\n", p->name); 
	}
}

int psfrag_setposition(int id)
{
	int k, num;
	float scl, rot;
	float x, y;
	char *kw, *cp, pos[8];
	struct fraginfo_list *p;
	
	num = 0;
	cp = kw = psfrag_str[0] + 17;
	for (; *cp; cp++) {
		if (*cp == '(' && !isdigit(cp[-1]) && cp[-1] != '\\') kw = cp;
		if (*cp == '[') {
			if (cp[1] == '[') cp++;
			if (sscanf(cp, "[%d(", &k) == 0 || k != id) continue;
			while (*cp && *cp != '(') cp++;
			if (*cp == '\0') break;
			cp++;
			for (k = 0; k < 7 && *cp; k++, cp++) {
				pos[k] = *cp;
				if (*cp == ')') break; 
			}
			pos[k] = '\0';
			if (sscanf(cp, ")%f %f", &scl, &rot) == 0) continue;
			for (p = fraginfo; p != NULL; p = p->next) {
				if (!strsubcmp(kw, p->keyword)) continue;
				x = (p->llx - psf_hof) + (p->dxx + p->dyx) * 0.5;
				y = (p->lly - psf_vof) + (p->dxy + p->dyy) * 0.5;
				for (k = 0; pos[k] != '\0'; k++) {
				switch (pos[k]) {
					case 't':
						x += p->dyx * 0.5;
						y += p->dyy * 0.5;
						break;
					case 'b':
						x -= p->dyx * 0.5;
						y -= p->dyy * 0.5;
						break;
					case 'r':
						x += p->dxx * 0.5;
						y += p->dxy * 0.5;
						break;
					case 'l':
						x -= p->dxx * 0.5;
						y -= p->dxy * 0.5;
						break;
					case 'B':
						x -= p->dyx * (0.5 - p->base);
						y -= p->dyy * (0.5 - p->base);
						break;
					}
				}
				if (get_rot_matrix(0) == 1) {
					x *= (double)10000/get_rot_matrix(1);
					y *= (double)10000/get_rot_matrix(2);
				}
				psf_position[num].x = x * psf_hsc * 1.00375 * 65536;
				psf_position[num].y = y * psf_vsc * 1.00375 * 65536;
				psf_position[num].rot
					= (360 - p->rot - rot) * 3.14159265 / 180;
				psf_position[num].scl = scl;
				num++;
				if (num >= MAX_POSITIONS) return (num);
			}
		}
	}
	return (num);
}

static char *checkpsfrag(char *str)
{
	int id;
	static int positions = 0;
	SCALED_PT x, y;
	char rotcmd[32];

	if (strsubcmp(str, "ps: /PSfrag where{pop")) {	/* New psfrag? */
		if (f_psfrag > 3) f_psfrag = 3;
		while (f_psfrag > 0) {
			Free(psfrag_str[--f_psfrag]);
		}
		psfrag_str[f_psfrag++] = dup_string(str + 4); 
		return (NULL);
	}
	if (f_psfrag == 1 && strsubcmp(str, "PSfile=")) {
		psfrag_str[f_psfrag++] = dup_string(str); 
		return (NULL);
	}
	if (f_psfrag == 2 && strcmp(str, "ps: /End PSfrag") == 0) {
		psfrag_str[f_psfrag++] = dup_string(str + 4); 
		get_current_xy(&psf_h , &psf_v);
		return (psfrag_str[1]);
	}

	if (f_psfrag >= 3) {
		if (strcmp(str, "ps: /Hide PSfrag") == 0) {
			if (f_psfrag ==4) f_hide = TRUE;
			return (NULL);
		}
		if (strcmp(str, "ps: /Unhide PSfrag") == 0) {
			f_hide = FALSE;
			return (NULL);
		}
		if (strcmp(str, "ps:  { ") == 0) {
			if (f_psfrag ==4) {
				f_hide = TRUE;
				save_dvi_state(TRUE);
			}
			return (NULL);
		}
		if (sscanf(str, "ps:  } %d", &id) > 0
			&& strstr(str, "/Place PSfrag")) { 
			if (f_psfrag ==4) {
				if (f_hide == TRUE) {
					positions = psfrag_setposition(id);
				}
				if (psf_rot == TRUE) {
					tpic_rt(" -1");
					tpic_rt(" -1");
					psf_rot = FALSE;
				}
				if (positions > 0) {
					positions--;
					x = psf_h + (SCALED_PT)psf_position[positions].x;
					y = psf_v - (SCALED_PT)psf_position[positions].y;
					restore_dvi_state();
					set_current_xy(x, y);
					if (psf_position[positions].rot != 0 ||
						psf_position[positions].scl != 1) {
						tpic_rt("  1");
						sprintf(rotcmd, " 0 0 %.8f",
							psf_position[positions].rot);
						tpic_rt(rotcmd);
						tpic_rt("  1");
						sprintf(rotcmd, " %.8f %.8f",
							psf_position[positions].scl,
							psf_position[positions].scl);
						tpic_rt(rotcmd);
						psf_rot = TRUE;
					}
				} else {
					save_dvi_state(FALSE);
				}
			}
			f_hide = FALSE;
			return (NULL);
		}
	}
	return (str);
}

static BOOL lib_ps(char *ps)
{
	char *gs_lib, path[MAXPATH];
	int ch, i, pos = 0;
	static char *SUBPATH[] = {
		"lib\\", "kanji\\", "Resource\\", NULL};

	if(!access(path,0))
		return TRUE;
	gs_lib = getenv("GS_LIB");
	if(gs_lib == NULL){
		if(gs_exe && (pos = strlen(gs_exe)) < (MAXPATH-2) - strlen(ps)){
			strcpy(path, gs_exe);
			while(--pos > 0 && path[pos] != PATH_SEP);
			path[pos+1]=0;
			if(pos > 0){
				if(pos > 3 && !strcmp(path+pos-4, "\\bin\\"))
					pos -= 4;
				for(i=0; SUBPATH[i]; i++){
					strcpy(path+pos+1, SUBPATH[i]);
					strcat(path, ps);
					if(!access(path, 0))
						return TRUE;
				}
			}
		}
	}else{
		for(i = 0, ch = 1; ch; ){
			while((ch = gs_lib[pos++]) != 0 && ch != ';' && i < MAXPATH - 16){
				if(ch == '/')
					ch = '\\';
				path[i++] = ch;
			}
			if(ch != '\\')
				path[i++] = '\\';
			strcpy(path+i, ps);
			if(!access(path, 0))
				return TRUE;
		}
	}
	return FALSE;
}

void scan_fraginfo(char *epsname)
{
	FILE *fp;
	struct fraginfo_list *p, *q;
	char *cp, *cq, *str, *argv[3];
	char tpath[MAXPATH], path[MAXPATH*2], msg[MAXPATH*2];
	int	i, j, f_tmp;

	/* clear headers */
	if ((p = fraginfo) != NULL) {
		while (p) {
			q = p->next;
			Free(p);
			p = q;
		}
		fraginfo = NULL;
	}
	make_path(tmp_buf, NULL, epsname, ".pfi");

	if ((fp = search_ps(tmp_buf)) == NULL){
#if	0
		return;
#else				/* auto generation of *.pfi */
		if(!lib_ps("ps2frag.ps") || (fp = search_ps(epsname)) == NULL)
			return;
		fclose(fp);
mkpfi:	argv[0] = (gs_exe == NULL || !*gs_exe)?
#ifdef	UNIX
			"gs":
#elif defined(WIN32G)||defined(WIN32C)
			"gswin32c.exe":
#else
			"gs.exe":
#endif
			gs_exe;
		sprintf(path, "/c  %s", argv[0]);
		strcpy(tpath, "@tmpi$.@@@");
		if((fp = fopenf(tpath + 1, "w")) == NULL){
			strcpy(tpath+1, MakeTmpPath(tpath+1));
			fp = fopenf(tpath + 1, "w");
			f_tmp = 1;
		}
		else
			f_tmp = 0;

		for(i = 0; path[i]; i++){
			if(path[i] == '^'){
				fprintf(fp, "%s\n", path+i+1);
				break;
			}
		}
		if(f_tmp){
			j = 0;
			strcpy(tmp_buf, MakeTmpPath("tmp.pfi"));
		}else{
			j = strlen(tmp_buf) - 3;
			while(--j > 0){
				if(tmp_buf[j] == '\\'){
					j++;
					break;
				}
			}
		}
		sprintf(path + i, " %s > %s", tpath, tmp_buf+j);
		fprintf(fp, "-dNODISPLAY\n-dBATCH\n-q\nps2frag.ps\n%s\n", ps_path);
		fclose(fp);
		path[i] = 0;
#if	defined(WIN32G)
		sprintf(msg, "%s is making  %s", path+3, tmp_buf+j);
		DisplayMessage(msg);
#else
		error(DIRECT, "\nCalling %s to make %s\n", path+3, tmp_buf+j);
#endif
		path[i] = ' ';
#ifdef	WIN32
		argv[0] = (f_osversion<0)?"command.com":"cmd.exe";
		argv[1] = path;
		argv[2] = NULL;
		WinMinExecute(argv, 0, TRUE);
#else
		syetem(path);
#endif
		DisplayMessage(NULL);
		if((fp = search_ps(tmp_buf+j)) == NULL)
			return;
		else
			unlink(tpath+1);
	}else{
		FILE *fq;
		struct ftime ftimep;
		struct ftime ftimeq;

		if(lib_ps("ps2frag.ps") && (fq = search_ps(epsname)) != NULL){
			getftime(fileno(fp), &ftimep);
			getftime(fileno(fq), &ftimeq); 
			fclose(fq);
			if (*((ulong*)&ftimep) < *((ulong*)&ftimeq)){
				fclose(fp);
				goto mkpfi;
			}
		}
	}
#endif

	f_psfrag++;
	while(fgets(tmp_buf, 256, fp)) {
		if (strsubcmp(tmp_buf, "%PSfragInfo{")) {
			str = cp = tmp_buf + 11;
			*cp++ = '(';
			while (*cp != '\0' && *cp != '}') cp++;
			*cp++ = ')';
			*cp++ = '\0';
		} else if (strsubcmp(tmp_buf, "%PSfragNext")) {
			str = tmp_buf + strlen(tmp_buf) - 1;
			strcpy(str, "(\\\\tex");
			cp = str + 6;
			for (cq = tmp_buf + 11; cq < str; cq++) {
				if (*cq == '\\' || *cq == '(' || *cq == ')') *cp++ = '\\';
				*cp++ = *cq;
			}
			*cp++ = ')';
			*cp++ = '\0';
			fgets(cp, 256, fp);
			cp += 14;
		} else {
			continue;
		}
		if(strstr(psfrag_str[0], str)) {
			/* add a fraginfo */
			q = (struct fraginfo_list *)
				marea(sizeof(struct fraginfo_list) + strlen(str) + 1);
			strcpy(q->keyword, str);
			sscanf(cp, "%f,%f)(%f, %f)(%f, %f){%f}{%f}",
				&q->llx, &q->lly, &q->dxx, &q->dxy, &q->dyx, &q->dyy,
				&q->rot, &q->base);
			q->next = NULL;
			if (fraginfo == NULL) {
				fraginfo = q;
			} else {
				for (p = fraginfo; p->next != NULL; p = p->next);
				p->next = q;
			}
		}
	}
#if 0
	str = tmp_buf;
	for (p = fraginfo; p != NULL; p = p->next) {
		str += sprintf(str, "%s:(%f,%f)(%f,%f)(%f,%f){%f}{%f}\n",
					p->keyword, p->llx, p->lly, p->dxx, p->dxy, p->dyx, p->dyy,
					p->rot, p->base);
	}
	error(WARNING, "%s\n", tmp_buf);
#endif
	fclose(fp);
	return;
}
#endif


/*
 * DoPostScriptBox:
 *	This is where the postscriptbox is handled.
 *	Note that the width and height here are in real points (1/72.27 inch)
 *	as generated from TeX, as opposed to the silly 1/72 inch PS points.
 *	width and height are given by point (1 inch = 72.27 point)
 */

static float bbx, bby, bbh, bbw;
static PIXEL xrotateofs, yrotateofs;

#define	ROTATE90 1

static BOOL DoPostScriptBox(char *epsfname, float width, float height,
	float hsc, float vsc, float hhsc, float vvsc, int mode)
{
#if	!B_HEAD_EPSF
#define	mypsname epsfname
#endif
	BOOL found = FALSE;
	BOOL foundsize = FALSE;
	FILE *spfp, *outfp;
	char line[257];
	float x1, x2, y1, y2;
	float ftmp;
	PIXEL xofs, yofs;
	PIXEL xsize, ysize;
	PIXEL xrealofs, yrealofs;
	PIXEL xrealsize, yrealsize;
	PIXEL xadd, yadd;
	PIXEL x, y;
	int h_skip;
#if	B_HEAD_EPSF
	FILE *spofp;
	int	h_size;
	char *mypsname;
	char myps[257];
#endif
	char *p;
#if !defined(DBGP) && !defined(UNIX)
	struct ftime ftime0;
	struct ftime ftime1;
#endif
	int i;

#define ADD_LENGTH 72 /* big point */

	ENTER("DoPostScriptBox")

  /*
   * Open the PS file.
   */
	if((spfp = search_ps(epsfname)) != NULL){
#ifdef	USE_ETF
		if(f_make_imgetf)
			SetETFimg(ps_path);
		else
#endif
		strcpy(org_ps_path, ps_path);
		i = strlen(ps_path);
		if(i > 3 && !strcmp(ps_path + i - 3, ".gz"))
			ExpandGZ((char *)ps_path, &spfp, "r");
		epsfname = (char *)ps_path;		/* new ps_path in expanded *.gz */
	}else{
		error(WARNING, "unable to open %s(PS)", epsfname);
		return(found);
	}
#if B_HEAD_EPSF
	mypsname = epsfname;
#endif
#if	!defined(DBGP) && !defined(UNIX)
  /*
   * Get time stamp.
   */
	getftime(fileno(spfp), &ftime0);
#endif

	if(	 getc(spfp) == 0xc5 && getc(spfp) == 0xd0
	  && getc(spfp) == 0xd3 && getc(spfp) == 0xc6 ){	/* Binary Header */
#if	!defined(UNIX)
		setmode(fileno(spfp), O_BINARY);
#endif
		h_skip = getc(spfp);
		h_skip += (getc(spfp)<<8);
		h_skip += (getc(spfp)<<16);
		h_skip += (getc(spfp)<<24);
#if B_HEAD_EPSF
		h_size = getc(spfp);
		h_size += (getc(spfp)<<8);
		h_size += (getc(spfp)<<16);
		h_size += (getc(spfp)<<24);
#endif
		fseek(spfp, h_skip, SEEK_SET);
#if	!defined(UNIX)
		setmode(fileno(spfp), O_TEXT);
#endif
	}
	else{
		rewind(spfp);
		h_skip = 0;
	}
  /*
   * Search for BoundingBox or Frame, and rewind.
   */
	if (  (bbw == 0 || bbh == 0)
	   && (	 (mode & KEY_TYPE) == EPSBOX			/* postscriptbox{.. */
		  || (mode & KEY_TYPE) == EPS				/* epsfile= */
#if 0
		  || (mode & KEY_TYPE) == PS				/* psfile= */
#endif
		  || (mode & KEY_TYPE) == PSFILE) ){		/* PSfile= */
		while(fgets(line, 256, spfp)) {
			if((p = strstr(line, "%%BoundingBox:" )) != NULL){
				while (*p++ != ':' );
				if(sscanf(p, "%f %f %f %f", &x1, &y1, &x2, &y2) == 4) {
					bbx = Min(x1, x2);
					bby = Min(y1, y2);
					bbw = Abs(x2 - x1);
					bbh = Abs(y2 - y1);
					foundsize = True;
					break;
				}
			}
		}
		if(! foundsize) {
			error(WARNING, "no BoundingBox found: assuming unit square");
			bbx = 0.0;
			bby = 0.0;
			bbw = 1.0;
			bbh = 1.0;
		}
	}
	fclose(spfp);
#if	0
	if( foundsize && (mode & KEY_TYPE) == PS )
		mode = (mode & ~KEY_TYPE) | PSFILE;
#endif
  /*
   * Emit preamble.
   *  The PS box thinks it will print in bbw PSpoints, or bbw/72 inches.
   *  TeX wants it to fit into width real points, or width/72.27 inches.
   *  The current scale has been reset to 72 dots per inch.
   *  Scale = (width/72.27) / (bbw/72).
   *  72.27/72 = 1.00375
   */

	if ((mode & KEY_TYPE) == PS){
		if (width  == 0) width	= hsc*1.00375;
		if (height == 0) height = vsc*1.00375;
	}
	else if (mode & IS_SCALE){
org:	width  = bbw * hsc * 1.00375;
		height = bbh * vsc * 1.00375;
	}
	else{
		if (width == 0){
			if (height == 0){
				hsc = vsc = 1;
				goto org;
			}
			else width	= bbw * height / bbh;
		}
		else if (height == 0){
			height = bbh * width / bbw;
		}
		hsc = width /(bbw * 1.00375);
		vsc = height/(bbh * 1.00375);
	}
	if(hhsc != 1){
		hsc *= hhsc; width *= hhsc;
	}
	if(vvsc != 1){
		vsc *= vvsc; height *= vvsc;
	}
	if(f_scale == 2){
/*
		ftmp = bbx;
		bbx = bby;
		bby = ftmp;
*/
		ftmp = bbw;
		bbw = bbh;
		bbh = ftmp;
		ftmp = width;
		width = height;
		height = ftmp;
		ftmp = hsc;
		hsc = vsc;
		vsc = ftmp;
	}
	xadd = (PIXEL)ROUND(dpi * Abs(hsc) * add_length / 72.0);
	yadd = (PIXEL)ROUND(DPI * Abs(vsc) * add_length / 72.0);
	xrealsize = (PIXEL)ROUND((Abs(width)  * dpi / 72.27));
	yrealsize = (PIXEL)ROUND((Abs(height) * DPI / 72.27));
	xsize = xrealsize+xadd*2;
	ysize = yrealsize+yadd*2;
	if(f_scale < 1){
		xrealofs = get_current_x();
		yrealofs = get_current_y();
	}else{
		xrealofs = xrotateofs;
		yrealofs = yrotateofs;
	}
	if (((mode & KEY_TYPE) != PS) && (mode & (IS_HOFFSET|IS_VOFFSET))) {
		xrealofs += (PIXEL)ROUND(dpi * hoffset / 72.27);
		yrealofs -= (PIXEL)ROUND(DPI * voffset / 72.27);
	}
	if(hsc < 0)
			xrealofs -= xrealsize;
	if(f_scale == 2){
		if(vsc < 0)
			yrealofs -= yrealsize;
	}else if((mode & KEY_TYPE) == PSFILE || (mode & KEY_TYPE) == EPSBOX){
		if(vsc > 0)
			yrealofs -= yrealsize;
	}else if (vsc < 0)
			yrealofs -= yrealsize;
	xofs = xrealofs - xadd;
	yofs = yrealofs - yadd;

#ifndef NOPSFRAG	/* save scales for psfrag */
	psf_hsc = hsc;
	psf_vsc = vsc;
	psf_hof = bbx;
	psf_vof = bby;
#endif

/****************************************************************************
 1	f_GS(画像表示)？
 2	  Y-> 通常の向き？
 3	  |	  Y-> PBM が存在？
 4	  |	  |	  Y-> PBM が PS より新しい？
 5	  |	  |	  |	  Y-> サイズが正しい、または、SPBM？
 6	  |	  |	  |	  |	  Y-> PBM ファイルを読んで表示する -> put_pbm()
 7	  |	  |	  |	  |	  N-> PS をこのページで未登録で登録可 -> find_psname()
 8	  |	  |	  |	  |		  Y-> PBM または、SPBM？
 9	  |	  |	  |	  |		  |	  Y->23 へ
10	  |	  |	  |	  |		  |	  N->GhostScript を起動して PBM を作成後 6へ
11	  |	  |	  |	  |		  N-> tmpps%d.pbm として作成するため、18 へ
12	  |	  |	  |	  N-> PS をこのページで未登録で登録可
13	  |	  |	  |		  Y-> 8 へ
14	  |	  |	  |		  N-> PS 登録はオーバーフロー？
15	  |	  |	  |			  Y-> tmpps%d.pbm として作成するため、18 へ
16	  |	  |	  |			  N-> 終了(gs_exec.bat 作成のとき起こりうる)
17	  |	  |	  N-> 12 へ
18	  |	  N-> GSS(gs_exec.bat作成)ならばワーニングを出す。tmpps%d.pbm を得る。
	  | 　	  current_gsps <= total_gsps？
19	  |		  Y-> GSS(gs_exec.bat作成)？
20	  |		  |	  Y-> 23 へ
21	  |		  |	  N-> 6 へ
22	  |		  N-> total_gsps = current_gsps として 8 へ
23	  N-> 必要なら外枠表示 -> boxpic() で、終了

注: tmpps%d.pbm の %d は、通常そのページの先頭からのテンポラリPSファイルの通し
  番号となる。ただし、GSS のときは、「対応するPSファイルの前に存在するそのペ
	ージの先頭からの異なるGhostscriptでの処理の数」をさらに足した数となる。
***************************************************************************/

	count_gsps();
	if (!F_GS) goto show_box;
	strcpy(line, epsfname);

	i = strlen(line) - 4;
	if(i > 0){
		if(Stricmp(line + i, ".eps") && Stricmp(line + i + 1, ".ps"))
			strcat(line, ".");
	}
	if (hsc < 0.0 || vsc < 0.0 || (f_scale == 2 && !ptex_d) ){
										/* if not normal PBM	*/
tmp_pbm:
		get_pbmname(line);				/* get PBM name into line	*/
		if (F_GS == DO_GSS && current_gsps > total_gsps)
			error(WARNING, "Need temporary PBM for PS");
										/* check if it has been made */
		if (current_gsps <= total_gsps){
			if (F_GS != DO_GSS) goto use_pbm;
			goto show_box;
		}
	}
										/* check if PBM exists */
	else if ((spfp = open_pbm(line, &x, &y, 1|IS_BW)) != NULL){
#if	!defined(DBGP) && !defined(UNIX)
		getftime(fileno(spfp), &ftime1);
#endif
		fclose(spfp);
										/*	 compare timestamp */
#ifdef	USE_COLOR
		if(	  current_f_GIF >= 2
		  &&  current_f_GIF != (f_mode_BMP & 0xff)
		  && (current_f_GIF != 3 || !(f_mode_BMP & IS_COL16)) )
			goto f_ps;
#endif
#if	!defined(DBGP) && !defined(UNIX)
		if (*((ulong*)&ftime0) <= *((ulong*)&ftime1))
#endif
		{
			int dev, xss, yss;
										/* compare size	 */
			if (F_GS == DO_SPBM)
				goto use_pbm;
			xss = xsize;
			yss = ysize;
			if(f_gsame && current_f_GIF >= 3 && (dev = GetXGray()) > 1){
				xss = (xsize + dev - 1)/dev;
				yss = (ysize + GetYGray() - 1)/GetYGray();					
			}
			if(x == y && ptex_d == 1)
				goto f_ps;
			if(y == yss && (((x+7) & 0xfff8) == ((xss+7) & 0xfff8)))
				goto use_pbm;
										/* use it if it coincides */
		}
					/* check if the PBM has been made in the current page */
f_ps:	if (find_psname(line) == 0) goto tmp_pbm;
		name_pbm(line);
	}
	else{
		switch(find_psname(line)){
			case 0: if (F_GS != DO_GSS)		/* exist */
						goto show_box;
			case 1:	goto tmp_pbm;			/* overflow */
/*			case 2:	break;						saved */
		}
		name_pbm(line);
	}
	if (F_GS == DO_PBM || F_GS == DO_SPBM) goto show_box;

	strcpy(tmp_doboxpath, "tmp$.ps");
	if((outfp = fopenf(tmp_doboxpath, "wt")) == NULL){
		strcpy(tmp_doboxpath, MakeTmpPath(tmp_doboxpath));
		outfp = fopenf(tmp_doboxpath, "wt");
	}
#if !B_HEAD_EPSF
	if(h_skip){
		fputs("(gs_epsf.ps) findlibfile { /.epsfheader where {pop pop pop}"
		"{closefile run}ifelse} {pop} ifelse\n",
		outfp);
	}
#endif
#ifndef NOPSFRAG
	if (f_psfrag == 4) {
		put_headers(outfp);
	}
#endif
	fputs("/NumbDict countdictstack def\n1 dict begin\n/showpage {} def\n",
		outfp);
	fputs("userdict begin\n",outfp);
	fprintf(outfp, "%f %f translate\n",
		Abs(hsc)*add_length, Abs(vsc)*add_length);
	if (((mode & KEY_TYPE) != PS) && (hsc < 0.0 || vsc < 0.0)) {
		fprintf(outfp, "%f %f translate\n",(hsc<0.0)?-width/1.00375:0.0, 
		(vsc<0.0)?-height/1.00375:0.0);
	}
	fprintf(outfp, "%f %f scale\n", hsc, vsc);
	if(f_scale == 2)
	{
			/* if the left top corner of BoundingBox equals (X,Y) */
			/* then	 "-X Y translate" */
			/* the original Bounding Box : (bby, bbx) - (bby + bbw, bbx + bbh) */
		fprintf(outfp, "%f %f translate\n", -bby,  bbx + bbh);
		fprintf(outfp, " 90 neg rotate\n");
	}else
		fprintf(outfp, "%f %f translate\n", -bbx, -bby);
#if	0
	error(C_MSG, 
		"width=%f height=%f:hsc=%f vsc=%f:bbx=%f bby=%f: bbw=%f, bbh=%f", 
			width/1.00375, height/1.00375, hsc, vsc, bbx, bby, bbw, bbh);
	error(DATATITLE, "status");
#endif
#if	B_HEAD_EPSF
	if(h_skip){
		spfp = fopenf(epsfname, "rb");
		fseek(spfp, h_skip, SEEK_SET);
		strcpy(myps, MakeTmpPath("mytmp.ps"));
		spofp = fopenf(mypsname = myps, "wb");
		while((x = getc(spfp))!= EOF && h_size-- > 0)
			putc(x, spofp);
		fclose(spfp);
		fclose(spofp);
	}
#endif
#ifndef NOPSFRAG
	if (f_psfrag == 4) {
		fputs(psfrag_str[0], outfp);
		fputs("\n", outfp);
	}
#endif
	do_gspostscriptbox(mypsname, (PIXEL)ROUND(dpi), (PIXEL)ROUND(DPI), 
		xsize, ysize, outfp);
#if	BMC
	if(bmp2bmc(tmp_buf, NULL, 0))
		unlink(tmp_buf);
#endif
#ifdef	WIN32
	if(f_erace)
#endif
	{
		unlink(tmp_doboxpath);
#if	B_HEAD_EPSF
		if(h_skip)
			unlink(mypsname);
#endif
	}
	if (F_GS == DO_GSS) goto show_box;
use_pbm:
	put_pbm(line, xofs, yofs, xsize, ysize, IS_POS, 0);
show_box:
	if (f_gbox)
		boxpic(xrealofs, yrealofs, xrealsize, yrealsize);
#ifdef	HYPERTEX
	if(f_hyper & F_H_BOX)
		add_hyper_box0(xrealofs, yrealofs, xrealsize, yrealsize);
#endif
	if (total_gsps < current_gsps) total_gsps = current_gsps;
	org_ps_path[0]=0;
	RETURN(found);
}

static float get_pt(char *sf)
{
	SCALED_PT sp;

	if (length_to_sp(sf, &sp) == 0) return((float)sp/65536.0);
	else return(atof(sf)*72.0/72.27);
}

static float get_bp( char* sf )
{
	SCALED_PT sp;

	if (length_to_sp(sf, &sp) == 0) return((float)sp/65536.0*72.27/72.0);
	else return(atof(sf));
}

#ifdef	USE_COLOR
enum{
	C_AUTO_P2, C_REPLACE, C_MERGE_DEF, C_MERGE_BACK, 
	C_PATCH, C_PATCH2, C_AUTOREP
};

BOOL f_spcolor = TRUE;	/* use colored letters? in the page */
int f_rpcolor;		/* 0:auto(p2)	1:replace  2:merge(def) 3:merge(back) */
					/* 4:patch		5:patch2   6:auto(rep) */
int f_ccolor = 0;	/* color code of letter */
					/* -1: without color  0: normal */
					/* 0x1000000:patch(black)	0x1ffffff:patch(white) */
int f_bcolor = -1;	/* background color */
int f_b_bcolor = -1;/* background color for patch2 */
int f_ucolor;		/* The following colored objects are used in the page	*/
					/* 1: color BMP	 2: color char	4: ANTIAREA	 8: fit BMP */

static int f_clevel;	/* 1: done AND	 2: replaced */
static int f_ocolor;	/* former color */
	   int bmp_pt;		/* current number of BMP to be patched later */
static int max_bmp;
static int max_ch_bmp;
static int ccolor_pt;
static BOOL f_manycolor;
static BOOL f_ckeep;
int	colordepth;

int ccolor[MAX_COLOR];

static int ftocol(char *s, char **pt)
{
	float  f;

	f = atof(s);
	while( (*s >='0' && *s <= '9') ||  *s == '.')
		s++;
	while( (*s <= ' ' || *s == ',') && *s)
		s++;
	*pt = s;
	return (((int)(255.01*f)) & 0xff);
}

void set_black(int mode)
{
	static BOOL old_spcolor;
	static int old_ttout;

	if(mode == 1){
		old_ttout = f_ttout;
		f_ttout = 0;
skp:	old_spcolor = f_spcolor;
		f_spcolor = FALSE;
	}else if(mode == -1){
		f_ttout = old_ttout;
		f_spcolor = old_spcolor;
	}else if (mode == 2){
		old_ttout = f_ttout;
		goto skp;
	}
}

static void reset_ccolor(void)
{
	f_manycolor = f_ucolor = f_clevel = colordepth = 0;
	if(id_dvi != old_id_dvi || current_page != ps_page + 1){
		if(f_rpcolor != C_PATCH && f_rpcolor != C_PATCH2){
			ccolor_pt = 0;
			f_ccolor = (f_spcolor)?0:-1;
		}else{
rep:		f_ccolor = ccolor[ccolor_pt = 2] = ccolor[1] = 
				(SetGamma(0)>0)?0x1000000:0x1ffffff;
		}
	}
	if(f_rpcolor == C_PATCH || f_rpcolor == C_PATCH2){
		f_ucolor = 0xf;
		if(f_ccolor < 2)
			goto rep;
	}
	f_bcolor = f_b_bcolor = -1;
}

static void pret_color(char *s, int mode)
{
	static char *pushpop[2] = {"push", "pop"};
	static char *rgb[] = {
		"gray", "rgb", "cmyk", "hsb",

		"Black", "White", "Gray",
		"Red", "Green", "Blue", 
		"Cyan", "Magenta", "Yellow",

		"Orange", "Brown", "Purple", "Violet",
		"Sepia", "Tan", "RedViolet", "VioletRed",
		"YellowGreen", "Goldenrod", "Dandelion", "Apricot",
		"Peach", "Melon", "YellowOrange", "BurntOrange",

		"Bittersweet", "RedOrange", "Mahogany", "BlueGreen",
		"BrickRed", "OrangeRed", "RubineRed", "WildStrawberry", 
		"Salmon", "CarnationPink", "Rhodamine", "Mulberry",
		"Fuchsia", "Lavender", "Thistle", "Orchid",

		"DarkOrchid", "Plum", "RoyalPurple",  "BlueViolet",
		"Periwinkle", "CadetBlue", "CornflowerBlue", "MidnightBlue", 
		"NavyBlue", "RoyalBlue",  "Cerulean", "ProcessBlue",
		"SkyBlue", "Turquoise",	 "TealBlue",  "Aquamarine",

		"Emerald", "Maroon", "JungleGreen", "SeaGreen", 
		"ForestGreen", "PineGreen", "LimeGreen", "GreenYellow",
		"SpringGreen", "OliveGreen", "RawSienna"
	};
	static int col_pal[] = {
		0x000000, 0xffffff, 0x808080,				/* Black */
		0xff0000, 0x00ff00, 0x0000ff,				/* Red */
		0x00ffff, 0xff00ff, 0xffff00,				/* Cyan */

		0xff6422, 0x661300, 0x8d24ff, 0x361fff,		/* Orange */
		0x4d0d00, 0xdc9471, 0x9d11a9, 0xff31ff,		/* Sepia */
		0x8fff43, 0xffe629, 0xffb629, 0xffae7b,		/* YellowGreen */
		0xff804d, 0xff8a80, 0xff9400, 0xff7d00,		/* Peach */

		0xc23000, 0xff3b22, 0xa61916, 0x27ffab,		/* Bittersweet */
		0xb8140b, 0xff0080, 0xff00de, 0xff0b9c,		/* BrickRed */
		0xff789f, 0xff5fff, 0xff2eff, 0xa519fa,		/* Salmon */
		0x7d15eb, 0xff85ff, 0xe169ff, 0xae5cff,		/* Fuchsia */

		0x9933cc, 0x8000ff, 0x401aff, 0x2216f5,		/* DarkOrchid */
		0x6e73ff, 0x616ec5, 0x5adeff, 0x037f92,		/* Periwinkle */
		0x1076ff, 0x0080ff, 0x10e3ff, 0x0bffff,		/* NavyBlue */
		0x61ffe1, 0x27ffcc, 0x23faa5, 0x2effb3,		/* SkyBlue */

		0x00ff80, 0xae1737, 0x03ff7b, 0x50ff80,		/* Emerald */
		0x14e11b, 0x0fc04f, 0x80ff00, 0xd9ff50,		/* ForestGreen */
		0xbdff3e, 0x379907, 0x8d2700				/* SpringGreen */
	};
	char *pt;
	int	i, j, m, n, k, col;
	int hh, ss, b;
	static int f_unknown;

	#define	RGB_SIZE sizeof(rgb)/sizeof(char *)

	if(f_ccolor == -1)
		return;
	count_gsps();
	current_gsps--;
	if(mode == BACKGROUND){
		pt = s;
		goto getcol;
	}
	for(i = 0; i < 2; i++){
		if((pt = find_key(s, pushpop[i])) != NULL)
			break;
	}
	switch(i){
	  case 0:						/* push */
		if(ccolor_pt >= MAX_COLOR){
			error(WARNING, "Too many color");
			return;
		}
		s = pt;
getcol:	for(i=0; i < RGB_SIZE; i++){
			if((pt = find_key(s, rgb[i])) != NULL)
				break;
		}
		switch(i){
		  case 0:		/* gray	 0:black, 1:white */
			col = ftocol(pt, &pt);
			col |= ((col << 8) | (col << 16));
			break;

		  case 1:		/* rgb */
			col	 = ftocol(pt, &pt) << 16;
			col |= ftocol(pt, &pt) << 8;
			col |= ftocol(pt, &pt);
			break;

		  case 2:		/* cymk */
			col	 = (255 - ftocol(pt, &pt)) << 16;	/* red */
			col |= (255 - ftocol(pt, &pt)) << 8;	/* green */
			col |= 255 - ftocol(pt, &pt);			/* blue */
			i = 255 - ftocol(pt, &pt);
			if(i != 255){
				j = (col & 0xff)*i/255;
				j |= ((col & 0xff00)*i/0xff00) << 8;
				col = j + (((col >> 16)*i/0xff) << 16);
			}
			break;

		 case 3:		/* hsb */
			hh = ftocol(pt, &pt)*6;
			ss = ftocol(pt, &pt);
			b  = ftocol(pt, &pt);
			if(!ss){
				col = b*0x10101;
				break;
			}
			i = hh/255;
			hh -= i*255;
			m = b*(255 - ss)/255;
			n = b*(255 - ss*hh/255)/255;
			k = m - n + b;
			switch(i){
				case 1:	col = (n << 16)|(b << 8)|m;
						break;
				case 2: col = (m << 16)|(b << 8)|k;
						break;
				case 3: col = (m << 16)|(n << 8)|b;
						break;
				case 4:	col = (k << 16)|(m << 8)|b;
						break;
				case 5:	col = (b << 16)|(m << 8)|n;
						break;
				default:col = (b << 16)|(k << 8)|m;
						break;
			}
			break;

		  default:
			col = (i >= 4 && i < RGB_SIZE)?col_pal[i-4]:((mode == CCOLOR)?0:-1);
		}
		if(mode == BACKGROUND){
			f_bcolor = f_b_bcolor = col;
			if(f_bcolor == 0xffffff)
			{
				f_bcolor = f_b_bcolor = -1;		// White background
			}
			else{
				f_clevel |= 1;
				f_ocolor = f_bcolor;
				if(f_bcolor == 0){
					bitmap_fill(0xff);
					f_bcolor = -1;
					f_b_bcolor = 0;
					goto bkbk;
				}
			}
			break;
		}else
			colordepth++;
		if(pt != NULL && (find_key(pt, "r")
		  || (f_rpcolor > 1 && f_rpcolor != C_AUTOREP)))
			col |= 0x1000000;
		if((f_rpcolor == C_AUTO_P2 || f_rpcolor == C_AUTOREP) && !col)
bkbk:		col = 0x1000000;
		f_ccolor = ccolor[++ccolor_pt] = col;
		break;

	  case 1:						/* pop */
		if(ccolor_pt > 0){
			f_ccolor = ccolor[--ccolor_pt];
			colordepth--;
		}else
			colordepth = -1024;
		if(ccolor_pt){
			if(f_rpcolor > 1 && f_rpcolor != C_AUTOREP && !f_ccolor)
				f_ccolor = 0x1000000;
		}else
			f_clevel = 0;
		break;

	  default:
		if(!f_unknown++)
			error(WARNING, "Unknown special:%s %s", 
				(mode==CCOLOR)?"color":"background",s);
		break;
	}
	return;
}
#endif

#ifdef	GIF
static Getf_GIF(void)
{
	return ( 
# ifdef USE_COLOR
		f_rpcolor != C_PATCH2 || 
# endif
		f_GIF >= 2 )? f_GIF:2;
}
#endif

static char *Checkpsfig(char *s)
{
	static int flag, clip;
	static float para[6], angle;
	static char command[0x200];
	char *t;
	int i;

	if(strsubcmp(t = s, "ps::[begin] ")){
		s += 12;
		for(i = 0; i < 6; i++){
			para[i] = atof(s)/(72.27/72.0*0x10000);
			while(*s >= '0' && *s <= '9')
				s++;
			while(*s == ' ')
				s++;
		}
		if(para[5] == 0 || !strsubcmp(s, "startTexFig")){
err:		if(flag >= 0){
				error(WARNING, "Cannot understand the special:\n%s", t);
				flag = 0;
			}
		}else{
			flag = 1;
			clip = 0;
		}
end:	return "";
	}else if(strsubcmp(s, "ps: plotfile ")){
		if(flag == 1){
			flag = 2;
			s += 13;
			while(*s == ' ')
				s++;
			strcpy(command, "epsfile=");
			t = command + 8;
			for(i = 0; s[i] > ' '; i++)
				t[i] = s[i];
			t[i] = 0;
			t += strlen(t);
			sprintf(t, " hsize=%fpt vsize=%fpt llx=%f lly=%f urx=%f ury=%f",
				para[0], para[1], para[2], para[3], para[4], para[5]);
			if(clip)
				strcat(t, " clip");
			goto end;
		}else if(flag == 2){
			flag = -1;
			error(WARNING, "Multiple EPSF is not supported for psfig\n");
		}
		goto err;
	}else if(strsubcmp(s, "ps::[end] endTexFig")){
		if(flag != 2)
			goto err;
		flag = 0;
		if(angle){
			angle = (360-angle)*3.14159265/180;
			tpic_rt(" 1");
			sprintf(common_work, " 0 0 %.8f", angle); 
			tpic_rt(common_work);
			epsbox_pret(command);
			angle = 0;
			tpic_rt(" -1");
			goto end;
		}else
			return command;
	}else if(flag == 1 && strsubcmp(s, "ps:: ")){
		if(strstr(s, "doclip")){
			clip = 1;
			goto end;
		}else if(strstr(s, "rotate")){
			angle = atof(s+5);
			goto end;
		}
	}
	return NULL;
}

static BOOL epsbox_pret(char *str)	/* interpret special. Ret TRUE if found */
{
	BOOL found = TRUE;
	char *sf;
	int i, ch, mode;
	float scale, ftmp;
	char epsname[MAXPATH];
	float width, height, hscale=1, vscale=1, hhscale=1, vvscale=1;

	if (!F_GS && !f_gbox) return(FALSE);

	ToDviDir();
	hoffset = voffset = mode = bmp_rev = flg_rev = f_taterot = f_watermark = 0;
	width = height = bbx = bby = bbw = bbh = 0;
	add_length = (f_gow || f_gclip)?0:ADD_LENGTH;
#ifdef	GIF
	current_f_GIF = Getf_GIF();
#endif
	scale = (float)dviout_dimension.mag / 1000.0;
	if (enlarge) scale = scale * enlarge / 1000.0;
	if (f_gsize) scale = scale * 1000.0 / org_mag;
	dpi = dviout_dimension.dpi*scale;
	DPI = dviout_dimension.DPI*scale;
	f_erace = f_wait;

  /* Handling psfig macros */

  /* skip blank */
	while(*str == ' ') str++;
#ifndef NOPSFRAG
	if ((str = checkpsfrag(str)) == NULL) goto quit;
#endif
	if (strlcmp(str, "ps:") == 0){
		sf = Checkpsfig(str);
		if(sf == NULL){
			if(do_gsps(&str[3]) == FALSE)
				return FALSE;
		}else if(*sf){
			str = sf;
			goto epsf;
		}
	} else if (strlcmp(str,"postscriptbox") == 0) {
	/*
	 * Read args
	 */
		if (sscanf(str+13, "{%fpt}{%fpt}{%80[^ {}]}", 
		  &width, &height, epsname) != 3){
			error(WARNING, "badly formed PS command:%s", str);
			goto quit;
		}

dobox:
#ifndef NOPSFRAG
		if (f_psfrag == 3) scan_fraginfo(epsname);
#endif
		DoPostScriptBox(epsname, width, height, hscale, vscale, hhscale, 
		vvscale, mode);
		if(f_scale > 0)
			push_rot_matrix(0);
		f_scale = 0;
	} else if (strlcmp(str, "\" ") == 0) {
		if(f_GS & 0x10)
			goto quit;
		do_gsps(&str[2]);
	} else {
epsf:	for (mode = 0; ; ){
			if( (sf = find_key0(str, PS_KEY[mode++])) != NULL )
				break;
			if (mode >= MAX_KEY){
				found = FALSE;
				goto quit;
			}
		}
#ifdef	USE_COLOR
		if(mode == CCOLOR || mode == BACKGROUND){
			pret_color(sf, mode);
			goto quit;
		}
#endif
		if(sf[0] == '"'){
			i = 0;
			do{
				if( (ch = sf[i+1]) == '"' || i >= MAXPATH - 1)
					ch = 0;
			}while( (epsname[i++] = ch) != 0);
			str = sf + i;
		}else{
			sscanf(sf, "%80[^, ]", epsname);
			str = sf + strlen(epsname);
		}
		for (i = 0; *key_opt[i]; i++){
			if ((sf = find_key(str, key_opt[i])) == NULL) continue;
			switch (i){
				case Hsize:
				case Width:
						width  = get_pt(sf);
						break;

				case Vsize:
				case Height:
						height = get_pt(sf);
						break;

				case Hoffset:
						hoffset = get_pt(sf);
						mode |= IS_HOFFSET;
						break;

				case Voffset:
						voffset = get_pt(sf);
						mode |= IS_VOFFSET;
						break;

				case Scale:
						vscale = atof(sf);

				case Hscale:
						hscale = atof(sf);
						mode |= IS_SCALE;
						break;

				case Vscale:
						vscale = atof(sf);
						mode |= IS_SCALE;
						break;

				case REAL:
						scale = 1;
						dpi = dviout_dimension.dpi;
						DPI = dviout_dimension.DPI;
						break;

				case Llx:
						bbx = atoi(sf);
						break;

				case Lly:
						bby = atof(sf);
						break;

				case Urx:
						bbw = atof(sf);
						break;

				case Ury:
						bbh = atof(sf);
						break;

				case Rwi:
						width = atoi(sf)*0.100375;
						break;

				case Rhi:
						height = atoi(sf)*0.100375;
						break;

				case Clip:
						add_length = 0;
						break;

				case Rev:
						flg_rev = 1;
						break;

				case REALDIR:
						f_taterot = 1;
						break;
				case WATERMARK:
						f_watermark = 1;
						break;
#ifdef	TILE
				case Tile:
						mode |= IS_TILE;
						break;
#endif
			}
		}
		switch(mode & KEY_TYPE){
			case PSFILE:				/* PSfile= */
				if(bbw < bbx){
					ftmp = bbx;
					bbx = bbw;
					bbw = ftmp;
				}
				if(bbh < bby){
					ftmp = bby;
					bby = bbh;
					bbh = ftmp;
				}
				bbw -= bbx;
				bbh -= bby;
			case EPS:					/* epsfile= */
			case PS :					/* psfile= */
				if(ptex_d && !f_taterot){
					char tmp[32];
					tpic_rt(" 1");
//					strcpy(tmp, " 0 0 1.5708");
					strcpy(tmp, " 0 0 1.5708 0 0");
					tpic_rt(tmp);
					f_taterot = -1;
				}
				f_scale = get_rot_matrix(-2);
				if(f_scale > 0){
					if(f_scale == 1){
						hhscale = (double)get_rot_matrix(1)/10000;
						vvscale = (double)get_rot_matrix(2)/10000;
					}else if (f_scale == 2){
						vvscale = -(double)get_rot_matrix(3)/10000;
						hhscale = (double)get_rot_matrix(4)/10000;
					}else if (f_scale == 4)
						hhscale = vvscale = 1;
					xrotateofs = get_current_x();
					yrotateofs = get_current_y();
					rotate_address(&xrotateofs,&yrotateofs);
					push_rot_matrix(1);
				}
				goto dobox;

			/* An extension to handle png, jpg is expected.
			   Since Windows, after 98/2000, itself can handle them.
			   Then, users do not need to prepare plug-in. */
			case BMP:
			case PNG:
			case JPG:
					mode |= IS_BMP;
					current_f_GIF = 2;
					count_gsps();
					current_gsps--;
					goto get_size;

			case PBM:					/* pbmfile= */
#ifdef GIF
					current_f_GIF = 0;
#endif
get_size:			if(ptex_d && !f_taterot){
						char tmp[32];
						tpic_rt(" 1");
//						strcpy(tmp, " 0 0 1.5708");
						strcpy(tmp, " 0 0 1.5708 0 0");
						tpic_rt(tmp);
						f_taterot = -1;
					}
					if( f_watermark ){
						width = dviout_dimension.text_width;
						height = dviout_dimension.text_height;
					}else if(mode & IS_SCALE){
						width  = hscale*scale*100;
						height = vscale*scale*100;
					}else{
						width  *= dpi/72.27;
						height *= DPI/72.27;
					}
					strcpy(org_ps_path, epsname);
					put_pbm(epsname, 0, 0,
						(PIXEL)ROUND(width), (PIXEL)ROUND(height),
						mode & ~KEY_TYPE, f_gbox?7:6);
					org_ps_path[0]=0;
					break;
#ifdef GIF
			case GIFF:					/* giffile= */
					error(WARNING, "GIF is no more supported!");
					break;
#endif
			case SPFILE:				/* file= */
					pret_file(epsname);
					break;
		}
	}
quit:
	if(f_taterot < 0)
		tpic_rt(" -1");
	RETURN(found);
}

void pret_file(char *fname)
{
#	define	MAX_LINE_BUF 0x1000

	FILE *fp;
	char line_buf[MAX_LINE_BUF];
	int ch, i, f_comment, nest;
	char *SP_KEY = "special";

	if ((fp = search_ps(fname)) == NULL){
		error(NO_FILE, "%s", fname);
		return;
	}
	nest = f_comment = 0;
	while((ch = fgetc(fp)) != -1){
		if (ch == '%'){
			f_comment = 1;
			continue;
		}
		if (f_comment){
			if (ch == 0x0a) f_comment = 0;
			continue;
		}
		if (!nest){
			if (ch == '\\'){
				for (i = 0; SP_KEY[i]; i++){
					if (fgetc(fp) != SP_KEY[i]) goto skip;
				}
				nest = 1;
skip:;		}
		}
		else{						/* \special ... */
			if (nest == 1){
				if (ch == '{'){
					i = 0;
					nest = 2;
				}
				else if (isalpha(ch)) nest = 0;
				else continue;
			}
			else if (ch == '}'){
				if (--nest != 1) goto keep;
				line_buf[i] = nest = 0;
				do_special(line_buf);
			}
			else{
				if (ch < ' ') ch = ' ';
keep:			line_buf[i++] = ch;
				if (ch == '{') nest++;
				if (i >= MAX_LINE_BUF - 1){
					error(WARNING, "too long special in %s", fname);
					goto end;
				}
			}
		}
	}
end:
	fclose(fp);
}

void exec_gs(char *pbm, char **argv0, int f_tmpps)
{
	static char *gmode[] =
	{
		"pbmraw",
		"gifmono",
		"bmpmono",
		"bmp16",
		"bmp256",
		"bmp16m"
	};
# ifdef WIN32G
	static int	f_GS_ERROR = -1;
#endif
	char temp[512];
	char tpath[MAXFILE+2];
	char exe[256];
	char newenv1[14];
	char newenv2[16];
	char newenv3[84];
	char *pt;
	char *exec;
	char **argv;
#ifdef	GIF
	char gdevice[32];
#endif
	int i;
	char *msg = common_work + COMMON_SIZE - 0x400;
#ifdef UNIX
		int pid;
#endif
	FILE *fp;

resume:
	if (F_GS == DO_GSS){
		if (current_gsps <= total_gsps)
			return;						/* done already */
#ifdef	UNIX
		exec = "gssub";
#else
		exec = "gssub.exe";
#endif
	}
	else
		exec = (gs_exe == NULL || !*gs_exe)?
#ifdef	UNIX
				"gs":
#elif defined(WIN32G)||defined(WIN32C)
				"gswin32.exe":
#else
				"gs.exe":
#endif
				gs_exe;
										/* get memory to execute gs_exe */
	sprintf(newenv1, "page=%d", current_page);
	putenv(newenv1);
	sprintf(newenv2, "info=%Fp", (DIMENSION far *)&dviout_dimension);
	putenv(newenv2);
	if (gs_exe != NULL && *gs_exe && strlen(gs_exe) < 80){
		sprintf(newenv3, "gsx=%s", gs_exe);
		putenv(newenv3);
	}
	strcpy(temp, "-sOUTPUTFILE=");
	strcat(temp, pbm);
	chg_pathsep(temp, '/');
	argv = argv0;
	*--argv = temp;

#ifdef GIF
	sprintf(gdevice, "-sDEVICE=%s", gmode[current_f_GIF]);
	*--argv = gdevice;
#else
	*--argv = "-sDEVICE=pbmraw";
#endif
	*--argv = "-dNOPAUSE";
	if(F_GS == DO_GS) *--argv = "-q";

	strcpy(tpath, "@tmp$.@@@");
	fp = fopenf(tpath + 1, "w");
	if(fp == NULL){
		strcpy(tpath+1, MakeTmpPath(tpath+1));
		fp = fopenf(tpath + 1, "w");
	}
	if(fp == NULL){
		error(WARNING, "Can't open temporary file for PS");
		return;
	}
	for (i = 0 ; argv[i] != NULL; i++)
		fprintf(fp, "%s\n", argv[i]);
	fclose(fp);
	*--argv = NULL;
	*--argv = tpath;

	strncpy(exe, exec, 256);
	pt = exe + strlen(exe);
	while (--pt >= exe){
		if (*pt == '^'){
			*pt = 0;
			*--argv = pt + 1;
		}
	}
	*--argv = exe;

	device_pause();
#if	defined(WIN32G)
	sprintf(msg, "%s  is making  %s", argv[0], pbm);
	DisplayMessage(msg);
#else
	error(DIRECT, "\nCalling %s to make %s\n", argv[0], pbm);
#endif
#ifdef	UNIX
	if((pid = fork()) == 0) {
		execlp( argv[0], argv[0], argv[1], argv[2], argv[3],
		   argv[4], argv[5], argv[6]);
		error( PROGRAM_STOP, "exec gs: %d", errno );
		exit(1);
	}else if(pid > 0)
		wait(0);
	else
		error( PROGRAM_STOP, "fork failed" );
#else
	if (
# ifdef USE_WINAPI
		WinMinExecute(argv, 0, TRUE) == 0
# else
		spawnvp(P_WAIT, exe, argv) == -1
# endif
	){
		if(F_GS != DO_GSV){
			DisplayMessage(NULL);
			sprintf(temp, "Cannot execute %s(%d)", exec, errno);
# ifdef WIN32G
			if(!f_search_GS){
				if(AskYes("Search Ghostscript?", temp) == TRUE){
					f_search_GS = 1;
					GetGS_LIB(msg);
					if(*msg){
						SetParaString("gsx", msg);
						f_search_GS = 2;
						goto resume;
					}
					else
						error(WARNING,"Cannot find Ghostscript!");
				}else
					f_search_GS = -1;
			}else
# endif
				error(WARNING, temp);
		}
	}else if(F_GS != DO_GSV && F_GS != DO_GSS && access(pbm, 0) == -1){
		f_erace = 0;
		DisplayMessage(NULL);
#ifdef	WIN32G
		Surmount();
		Detain();
		if(id_dvi != f_GS_ERROR){
			f_GS_ERROR = id_dvi;
#endif
# ifndef WIN32G
			error(PROGRAM_STOP,
				"Failed to make %s by the command\n"
				"  %s @%s\n\n"
				"The above %s is a parameter file\n\n"
				"Ignore all graphics?",
					pbm, exec, tpath+1, tpath+1);
# else
			switch(error(ASK, "Failed to make %s by the command\n"
				"  %s @%s\n\n"
				"The file %s is a parameter file\n\n"
				"(A)bort to include %s until this dviout is closed?\n"
				"(R)etry this command for the investigation of this error?\n"
				"(I)gnore this graphic?",
					pbm, exec, tpath+1, tpath+1, f_tmpps?"Direct PS code":"graphics")){
					case 0:		/* ignore */
						break;
					case 1: 	/* retry */
						sprintf(temp, "%s @%s", exec, tpath+1);
						ExecBatch(temp, 0);
						break;
					case 2:		/* abort */
						if(f_tmpps)
							f_GS |= 16;
						else
							f_GS = 0;
						break;
			}
			/* We shall show the help AFTER help message. */
			/* Showing the help is guarded by Detain()-Passable() procedure. */
			ShowWinHelp(IDH_QO9);
			Wait( 1 );
# endif
#ifdef	WIN32G
		}else
			error(WARNING, "Failed to make %s by the command\n"
				"  %s @%s\n\n",	 pbm, exec, tpath+1);
		Passable();
#endif
	}
#ifdef	WIN32G
	else if(f_search_GS == 2){
		if(AskYes("Reserve the path of Ghostscript in Registry?", 
			"Succeeded") == TRUE)
			ReserveStringPara("gsx", GetParaString("gsx"));
		f_search_GS = 3;
	}
#endif
	DisplayMessage(NULL);
#endif
	device_cont();
#ifdef	WIN32
	if(f_erace)
#endif
	unlink(tpath+1);
}


static void do_gspostscriptbox(char *epsfname, int x, int y, int a, int b,
	FILE *fp)
{
	char res[256];
	char geo[30];
	int dev;

	strncpy(res, epsfname, 256);
	chg_pathsep(res, '/');
	fprintf(fp, "(%s) run\n", res);
#ifndef NOPSFRAG
	if (f_psfrag == 4) {
		fputs(psfrag_str[2], fp);
		fputs("\n", fp);
	}
#endif
	fputs("countdictstack NumbDict sub {end} repeat\nshowpage\n",fp);
	fclose(fp);

	if(f_gsame && current_f_GIF >= 3 && (dev = GetXGray()) > 1){
		x = (x + dev - 1)/dev;
		a = (a + dev - 1)/dev;
		dev = GetYGray();
		y = (y + dev - 1)/dev;
		b = (b + dev - 1)/dev;
	}
	sprintf(res, (x==y)?"-r%d":"-r%dx%d", x, y);
	sprintf(geo, "-g%dx%d", a, b);

	if (F_GS != DO_GSS
#ifdef	WIN32
	  && f_erace
#endif
	) unlink(tmp_buf);
	gs_argv[0] = res;
	gs_argv[1] = geo;
#if	!defined(WIN32G)&&!defined(WIN32C)
	gs_argv[2] = "--";
	gs_argv[3] = tmp_doboxpath;
	gs_argv[4] = NULL;
#else
	gs_argv[2] = tmp_doboxpath;
	gs_argv[3] = "quit.ps";
	gs_argv[4] = NULL;
#endif
	exec_gs((char *)tmp_buf, gs_argv, 0);
}

static int ReadInt(FILE *fp)
{
	int num;

	num = Getc(fp);
	num |= Getc(fp)<<8;
	num |= Getc(fp)<<16;
	return( num | (Getc(fp)<<24) );
}

static int bmp_top;

#if	BMC
/*
  id[2]				'B' 'C'
  flag[1]			flag & 1: Not compressed?
  key[1]			key:
  bmc_head_size[4]	
  bmp_head_size[4]	
  byte_width[4]		
  height[4]			
  bit_width[4]		
  bmp_data_size[4]	
  f_mode[1]			kind of BMP, B&W et
  bmp_rev[1]		
  bmp_on[1]			
  bmp_off[1]		
  name[*]			original filename

  bmp_head[*]
  bmp_data[*]
*/
void putint(int num, FILE *fp)
{
	int i;
	for(i = 0; i < 4; i++){
		putc(num & 0xff, fp);
		num >>= 8;
	}
}

static FILE *get_bmpfile(char *fname, int *top, int *width, int *height, 
	int *bit_width)
{
	int	ch, count, col, bmp_width, x;
	int pal[256];
	FILE *fp;

	if(fname == NULL){
		fp = NULL;
		goto skip;
	}
	fp = fopen(fname, "rb");
	if(fp == NULL)
		return NULL;

	if(getc(fp) != 'B' || getc(fp) != 'M')
		return NULL;					/* ID == "BM"? */
	for(ch = 0; ch < 8; ch++)
		getc(fp);
	*top = bmp_top = ReadInt(fp);		/* bfOffBits */
										/* EOF FILEHEADER */

skip:
	ReadInt(fp);
	*bit_width = x = ReadInt(fp);		/* biWidth */
	*height = ReadInt(fp);				/* biHeight */
	Getc(fp); Getc(fp);
	ch = Getc(fp);
	ch += Getc(fp) << 8;				/* biBitCount */
#ifdef	USE_COLOR
	switch(ch){
		case 1:		f_mode_BMP = 2;	
					bmp_width = (x + 7)/8;
					break;
		case 4:		f_mode_BMP = 3;
					bmp_width = (x + 1)/2;
					break;
		case 8:		f_mode_BMP = 4;
					bmp_width = x;
					break;
		case 16:	f_mode_BMP = 6;
					bmp_width = x*2;
					break;
		case 24:	f_mode_BMP = 5;
					bmp_width = x*3;
					break;
		case 32:	f_mode_BMP = 7;
					bmp_width = x*4;
					break;
	}
#else
	if(ch != 1)
		return NULL;
	bmp_width = (x + 7)/8;
#endif
	*width = bmp_width = (bmp_width + 3)&~3;
	ch = 16;
	while(ch-- > 0)
		Getc(fp);
	count  = ReadInt(fp);				/* biCirUsed */
#ifdef	USE_COLOR
	if(count <= 16 && count > 0)
		f_mode_BMP |= IS_COL16;
#endif
	ReadInt(fp);
	if(fp == NULL)
		bmp_top = bmc_pt - bmc_buf;
#ifdef	USE_COLOR
	if( (f_mode_BMP & 0xff) == 2)
#endif
	{
		bmp_rev = (Getc(fp) & 0x80)?0:1;
		if(fp == NULL)
			bmp_top += 8;
		goto quit;
	}
#ifdef	USE_COLOR
	if(f_mode_BMP == 3 || f_mode_BMP == 4){
		if(count == 2){					/* Use 2 colors */
			if(fp == NULL)
				bmp_top += 8;
			ch = Getc(fp);
			if((ch == 0 || ch == 0xff) && 
				ch == Getc(fp) && ch == Getc(fp)){
				Getc(fp);
				ch = Getc(fp);
				if( (ch == 0 || ch == 0xff)
				  && ch == Getc(fp) && ch == Getc(fp)){
					if(ch){
						bmp_on = 1;
						bmp_off = 0;
					 }else{
						bmp_on = 0;
						bmp_off = 1;
					}
					f_mode_BMP |= IS_BW;
				}
			}
		}else{								/* 16 or 256 colors */
			bmp_on = bmp_off = -1;
			if(!(ch = count))
				ch = (f_mode_BMP == 3)?16:256;
			if(fp==NULL)
				bmp_top += count*4;
#if 0
			if(mode & IS_BW){
				for(count = 0; count < 16; count++)
					pal[count] = ReadInt(fp);
				for(; count < ch; count++)
					if(	 pal[count & 0xf] != (col = ReadInt(fp))
					  && col != 0x7f7f7f && col != 0 )
						goto quit;			/* 256 colors in 8 bit */
				f_mode_BMP |= IS_COL16;
				goto quit;					/* 16 colors in 8 bit */
			}
#endif
			for(count = 0; count < ch; count++)
				pal[count] = ReadInt(fp);
			for(count = 16; count < ch; count++){
				if(	 pal[count] != pal[count & 0xf]
				  && pal[count] != 0x7f7f7f
				  && pal[count] != 0 )
					break;
			}
			if (count >= ch)
				f_mode_BMP |= IS_COL16;
			count = 0;

			Fseek(fp, bmp_top, SEEK_SET);
			if((f_mode_BMP & 0xf)== 3){	/* 16 color */
				col = (x + 7)&~7;
				while( (ch = Getc(fp)) != EOF){
					count++;
					if(	 (ch & 0xf) != bmp_off
					  && (ch & 0xf) != bmp_on
					  && count % col < x){
						if(pal[ch & 0xf] == 0xffffff){
							if(bmp_on < 0){
								bmp_on = ch & 0xf;
								goto n16_1;
							}
						}
						else if(pal[ch & 0xf] == 0){
							if(bmp_off < 0){
								bmp_off = ch & 0xf;
								goto n16_1;
							}
						}
						goto quit;
					}
n16_1:				count++;
					ch >>= 4;
					if(	 ch != bmp_off
					  && ch != bmp_on
					  && count % col < x){
					if(pal[ch] == 0xffffff){
							if(bmp_on < 0){
								bmp_on = ch;
								goto n16_2;
							}
						}else if(pal[ch] == 0){
							if(bmp_off < 0){
								bmp_off = ch;
								goto n16_2;
							}
						}
						goto quit;
					}
n16_2:				count++;
				}
			}else{					/* 256 color */
				col = (x + 3)&~3;
				while( (ch = Getc(fp)) != EOF){
					if(	 ch != bmp_off
					  && ch != bmp_on
					  && count % col < x){
						if(pal[ch] == 0){
							if(bmp_off < 0){
								bmp_off = ch;
								goto n256;
							}
						}else if(pal[ch] == 0xffffff){
							if(bmp_on < 0){
								bmp_on = ch;
								goto n256;
							}
						}
						goto quit;
					}
n256:				count++;
				}
			}
bw_ok:		f_mode_BMP |= 0x200|IS_BW;
		}
	}else if(f_mode_BMP == 5 || f_mode_BMP == 6){	/* 24bit or 16bit color */
		if(fp)
			Fseek(fp, bmp_top, SEEK_SET);
		for(;;){
			for(count = x; count > 0; count--){
				if(	 ((ch = Getc(fp))!= 0 && ch != 0xff)
				  ||  ch != Getc(fp)
				  || (f_mode_BMP == 5 && ch != Getc(fp)) ){
					if(ch == EOF)
						goto bw_ok;
					goto quit;
				}
			}
			count  = x * ((f_mode_BMP==5)?3:2) & 3;
			if(count){
				count = 4 - count;
				while(count-- > 0)
					Getc(fp);
			}
		}
	}
#endif
quit:
	return(fp);
}

static uchar *my_comp(uchar *s_buf, int width, int height, 
	int *comp_size, int *key)
{
	uchar *d_buf;
	int w, h, ch, count, size, max_size, back, done, f_comp;
	int ch0;
	int f_count[16];

	/* frequency of the top 4 bits of bytes */
	for(w = 0; w < 16; w++)
		f_count[w] = 0;
	h = 0;
	size = w = back = 1;
	f_count[*s_buf >> 4]++;
	goto fs;
	for(; h < height; h++){
		back = width;
		for(w = 0; w < width; w++){
fs:			f_count[(s_buf[size] ^ s_buf[size-back]) >> 4]++;
			size++;
		}
	}
	count = f_count[1];
	f_comp = 1;
	for(w = 2; w < 16; w++){
		if(count > f_count[w]){
			f_comp = w;
			count = f_count[w];
		}
	} 
	f_comp <<= 4;
	max_size = width*height;
	d_buf = (char*)marea(max_size+count);
	if(d_buf == NULL)
		return NULL;
	/* first byte */
	ch0 = *s_buf++;
	count = size = 0;
	/* remaining bytes */
	w = back = 1;
	h = done = 0;
	goto rem;
	for(; h < height; h++){
		back = width;
		for(w = 0; w < width; w++, s_buf++){
rem:		ch = *s_buf ^ *(s_buf-back);
			if(ch == ch0){
				count++;
				continue;
			}else{
sk0:			if(ch0){
pc:					if( (ch0 & 0xf0) == f_comp){
						d_buf[size++] = f_comp;
						d_buf[size++] = ch0 & 0xf;
					}else
						d_buf[size++] = ch0;
				}
				if(count){
					if(!ch0){
						if(count < 16)
							d_buf[size++] = count + f_comp;
						else{
							d_buf[size++] = f_comp;
							if(count >= 0x1000000){
								d_buf[size++] = 0xfd;
								d_buf[size++] = count >> 24;
								goto sk1;
							}else if(count >= 0x10000){
								d_buf[size++] = 0xfe;
sk1:							d_buf[size++] = (count >> 16) & 0xff;
								goto sk2;
							}else if(count > 0xe0){
								d_buf[size++] = 0xff;
sk2:							d_buf[size++] = (count >> 8) & 0xff;
								goto sk3;
							}else
sk3:							d_buf[size++] = count & 0xff;
						}
					}else{
						if(count == 1){
							count = 0;
							goto pc;
						}
						d_buf[size++] = f_comp;
						if(--count < 0xf9 - 0xe0)
							d_buf[size++] = 0xe0 + count;
						else{
							if(count >= 0x1000000){
								d_buf[size++] = 0xf9;
								d_buf[size++] = count >> 24;
								goto sk4;
							}else if(count >= 0x10000){
								d_buf[size++] = 0xfa;
sk4:							d_buf[size++] = (count >> 16) & 0xff;
								goto sk5;
							}else if(count >= 0x100){
								d_buf[size++] = 0xfb;
sk5:							d_buf[size++] = (count >> 8) & 0xff;
								goto sk6;
							}else{
								d_buf[size++] = 0xfc;
sk6:							d_buf[size++] = count & 0xff;
							}
						}
					}
					count = 0;
				}else if(!ch0)
					d_buf[size++] = 0;
				if(done)
					goto end;
				ch0 = ch;
			}
		}
	}
	done = 1;
		goto sk0;
end:
	if(size >= max_size){
		Free0(d_buf);
		return NULL;
	}
	*key = f_comp;
	*comp_size = size;
	return d_buf;
}

BOOL bmp2bmc(char *name, unsigned char *buff, int s_size)
{
	FILE *fp;
	unsigned char *s_buf, *d_buf;
	int top, width, height, bit_width, d_size, key, flag, pos, skip, i;

	flag = 0;
	if(buff){
		bmc_end = (bmc_buf = s_buf = buff) + s_size;
		bmc_pt = buff + SIZEOF_BITMAPFILEHEADER - 4;
		top = ReadInt(NULL);
	}
	fp = get_bmpfile((buff==NULL)?name:NULL, 
		&top, &width, &height, &bit_width);
	pos = strlen(name);
	if((fp == NULL && buff == NULL) 
	  || pos < 5 || strcmp(name + pos - 4, ".bmp"))
		return FALSE;
	name[pos-1] = 'c';
	for(skip = pos-1; skip >= 0; skip--){
		if(name[skip] == '\\' || name[skip] == '/' || name[skip] == ':')
			break;
	}
	skip++;
	s_size = top + width*height;

	if(buff == NULL){
		fseek(fp, 0L, SEEK_SET);
		s_buf = (char*)marea(s_size);
		fread(s_buf, s_size, 1, fp);
		fclose(fp);
	}

	d_buf = my_comp(s_buf + top, width, height, &d_size, &key);
	fp = fopenf(name, "wb");
	name[pos-1] = 'p';
	if(fp == NULL)
		return FALSE;
	if(d_buf == NULL){
		d_size = width*height;
		flag |= 1;
	}
	putc('B', fp);
	putc('C', fp);
	putc(flag, fp);
	putc(key, fp);
	putint(pos - skip + (32+1), fp);
	putint(top, fp);
	putint(width, fp);
	putint(height, fp); 
	putint(bit_width, fp); 
	putint(top+d_size, fp); 
#ifdef	USE_COLOR
	putc(((f_mode_BMP & 0xf00) >> 4)|(f_mode_BMP & 0x0f), fp); 
#else
	putc(2, fp); 
#endif
	putc(bmp_rev & 0xff, fp); 
	putc(bmp_on & 0xff, fp); 
	putc(bmp_off & 0xff, fp); 
	for(i = skip; i <= pos; i++)
		putc(name[i], fp);

	fwrite(s_buf, top, 1, fp);
	if(d_buf){
		fwrite(d_buf, d_size, 1, fp);
		Free0(d_buf);
	}else
		fwrite(s_buf + top, d_size, 1, fp);
	if(buff == NULL)
		Free0(s_buf);
	else
		bmc_end = bmc_buf = bmc_pt = NULL;
	fclose(fp);
	return TRUE;
}

static void my_decomp(uchar *s_buf, uchar *d_buf, int width, int height, 
	int f_comp)
{
	int size, i, w, h, count, max_size;
	int ch;

	size = 0;
	max_size = width*height; 
	while(size < max_size){
		if((*s_buf & 0xf0) != f_comp){
			d_buf[size++] = *s_buf++;
			continue;
		}
		ch = 0;
		if(!(count = *s_buf++ & 0xf)){
			if(!(*s_buf & 0xf0)){
				d_buf[size++] = (*s_buf++ & 0xf) + f_comp;
				continue;
			}
			count = *s_buf++;
			if(count > 0xfc){
				i = 0;
				while(count++ <= 0x100)
					i = (i << 8) + *s_buf++;
				count = i;
			}
			else if(count > 0xe0){
				ch = d_buf[size-1];
				if(count < 0xf9)
					count -= 0xe0;
				else{
					i = 0;
					while(count++ <= 0xfc)
						i = (i << 8) + *s_buf++;
					count = i;
				}
			}
		}
		count++;
		while(count-- && size < max_size)
		d_buf[size++] = ch;
	}
	h = 0;
	w = count = size = 1;
	goto start;
	for( ; h < height; h++){
		count = width;
		for(w = 0; w < width; w++, size++)
start:			d_buf[size] ^= d_buf[size-count];
	}
}

static uchar *bmc2bmp(FILE *fp, int *x, int *y, int mode)
{
	int key, begin, width, height, size, flag, tmp, i;
	uchar *s_buf, *d_buf;

//	if(fp == NULL)
//		return NULL;
	Fseek(fp, 0, SEEK_SET);
	if(Getc(fp) != 'B' || Getc(fp) != 'C')
		return NULL;
	flag = Getc(fp);
	key = Getc(fp);
	begin = ReadInt(fp) + SIZEOF_BITMAPFILEHEADER;
	bmp_top = ReadInt(fp) - SIZEOF_BITMAPFILEHEADER;
	width = ReadInt(fp);
	*y = height = ReadInt(fp);
	*x = ReadInt(fp);			/* bit_width */
	size = ReadInt(fp) - SIZEOF_BITMAPFILEHEADER;
	tmp = Getc(fp);
	f_mode_BMP = ((tmp & 0xf0) << 4)|(tmp & 0x0f)|IS_BMC;
	bmp_rev = Getc(fp); 
	bmp_on = Getc(fp);
	bmp_off = Getc(fp);
	if(mode & IS_BW)
		return NULL;
	Fseek(fp, begin, SEEK_SET);
	s_buf = (char*)marea(size);
	if(fp != NULL)
		fread(s_buf, size, 1, fp);
	else{
		for(i = 0; i < size; i++)
			s_buf[i] = Getc(fp);
	}
	Fclose(fp);
	size = bmp_top + width*height;
	if(flag & 1){
		bmc_buf = s_buf;
		goto end;
	}
	d_buf = (char*)marea(size);
	memcpy(bmc_buf = d_buf, s_buf, bmp_top);
	my_decomp(s_buf+bmp_top, d_buf+bmp_top, width, height, key);
	Free0(s_buf);
end:
	bmc_end = bmc_buf + size;
	return bmc_pt = bmc_buf;
}

#endif

void reset_gsps(void)
{
	old_f_GIF = -1;
#ifdef	USE_COLOR
	if(!f_ckeep
# ifdef	STR_SEARCH
	  && !f_s_search
# endif
# ifdef	HYPER_TEX
	  && !(f_hyper & F_H_SEARCH)
# endif
	)
		ClearKeepBMP();
#endif
}

static void count_gsps(void)
{

	if (ps_page != current_page
	  || old_f_GIF != Getf_GIF()
#ifdef	WIN32G
	  || old_id_dvi != id_dvi
#endif
	){			/* New page or file */
#ifdef	USE_COLOR
		ClearKeepBMP();
#else
		ps_page = current_page;
		current_gsps = total_gsps = 0;
		ps_name[0] = NULL;
#endif
		old_f_GIF = Getf_GIF();
	}
	current_gsps++;
}

#ifdef UNIX
static void *get_fname(char *path, char *name)
{
	 int   i;

	 i = strlen(path);
	 while(--i >= 0 && path[i] != PATH_SEP);
	 strcpy(name, path + i + 1);
	 i = strlen(name);
	 while(--i > 0){
		  if(name[i] == '.'){
			  name[i] = 0;
			  break;
		  }
	 } 
}
#endif

/*
 * 0: exist	 1:overflow	 2:not exist
 */
static int find_psname(char *path)
{
	int	i;
#ifdef UNIX
		char name[MAXFILE];

		get_fname(path, name);
#else
	char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT];

	fnsplit(path, drive, dir, name, ext);	/* get name from path */
#endif
	for (i = 0 ; i < MAX_PS_NAME; i++ ){
		if (ps_name[i] == NULL){
			ps_name[i] = (i)? ps_name[i-1]+strlen(ps_name[i-1])+2:ps_name_buf;
			if(ps_name[i] + strlen(name) - ps_name_buf >= MAX_PS_BUF - 1){
				ps_name[i] = NULL;
				return 1;
			}
			strcpy(ps_name[i], name);
			if(i <= MAX_PS_NAME - 2)
				ps_name[i+1] = NULL;
			break;
		}
		if (strcmp(ps_name[i], name) == 0) return(0);	/* same PS file */
	}
								/* No same PS file or overflow MAX_PS_NAME */
	return((i == MAX_PS_NAME)? 1:2);
}

static void get_pbmname(char *filename)
{
	if (current_gsps > MAX_PS)
		error(PROGRAM_STOP, "Too many PS codes in a page");
	sprintf(filename, "tmpps%d.pbm", current_gsps );
	name_pbm(filename);
}

int strsubcmp(char *s, char *t)
{
	int	i;
	for(i = 0; t[i]; i++){
		if(s[i] != t[i])
			return 0;
	}
	return i;
}

#ifndef NOTPIC_EXTENSION
#define	KEYSPTOTPIC	5

static char *sptotpic[KEYSPTOTPIC] = {
	" gsave currentpoint currentpoint translate ",
	"neg rotate neg exch neg exch translate",
	" currentpoint grestore moveto",
	" currentpoint currentpoint translate",
	"scale neg exch neg exch translate"
	};
#endif

static BOOL do_gsps(char *str)
{
	char res[30];
	char pbm[30];
	char tmppath[MAXFILE+0x80];
	FILE *fp;
	int dev, xdpi, ydpi;
#ifndef NOTPIC_EXTENSION
	double ang;
	int len;
	char *pt, *pt0;
#endif

#ifndef NOTPIC_EXTENSION
	if( (len = strsubcmp(str, sptotpic[0])) > 0){
		ang = (360-atof(str+len))*3.14159265/180;
		while(str[len] && str[len++] > ' ');
		if(strsubcmp(str+len, sptotpic[1])){
			sprintf(res, " 0 0 %.8f", ang); 
			tpic_rt(" 1");
			tpic_rt(res);
			return True;
		}
	}else if(!strcmp(str, sptotpic[2])){
		tpic_rt(" -1");
		return True;
	}else if( (len = strsubcmp(str, sptotpic[3])) > 0
		  &&  (pt = strstr(str, sptotpic[4])) != NULL){
		  if(pt[strlen(sptotpic[4])] == 0 && pt - str < 0x80){
			if( strsubcmp(pt-4, "div") > 0)
				tpic_rt(" -1");
			else{
				pt0 = str + len;
				while(*pt0 == ' ')
					pt0++;
				while(*pt0 && *pt0 != ' ')
					pt0++;
				tpic_rt(" 1");
				if(ptex_d&&!(f_tpic_turn_on&16))
					sprintf(tmppath, " %.8f %.8f", atof(pt0), atof(str+len));
				else
					sprintf(tmppath, " %.8f %.8f", atof(str+len), atof(pt0));
				tpic_rt(tmppath);
			}
			return True;
		  }
	}
#endif
	if(f_GS & 0x10)
		return FALSE;
	if (F_GS != DO_GS && F_GS != DO_GSV){
		if(F_GS == DO_GSS)
			error(WARNING, "PS code exist");
		else return(FALSE);
	}

	count_gsps();
	get_pbmname(pbm);

	strcpy(tmppath, "tmp$$.ps");
	if (total_gsps < current_gsps){
		if (	(fp = fopenf(tmppath, "wb")) == NULL
			&& (strcpy(tmppath, MakeTmpPath(tmppath)), 
				(fp = fopenf(tmppath, "wb")) == NULL) ){
				error(WARNING, "Can't open temporary PS file");
				return(FALSE);
		}
		xdpi = dviout_dimension.dpi;
		ydpi = dviout_dimension.DPI;
		if(f_gsame && current_f_GIF >= 3 && (dev = GetXGray()) > 1){
			xdpi = (xdpi + dev - 1)/dev;
			ydpi = (ydpi + GetYGray() - 1)/GetYGray();
		}else
			dev = 1;
#ifndef NOPSFRAG
		put_headers(fp);
#endif
		fprintf(fp, "72 0 translate\n"); 
		fwrite(str, strlen(str), sizeof(char), fp);
		fprintf(fp, "\nshowpage\nquit\n" );
		fclose(fp);
		gs_argv[3] = NULL;
		sprintf(res, "-r%dx%d", xdpi, ydpi);
#ifdef	WIN32
		if(f_erace)
#endif
		unlink(tmp_buf);
		gs_argv[0] = res;
#if	!defined(WIN32G)&&!defined(WIN32C)
		gs_argv[1] = "--";
		gs_argv[2] = tmppath;
#else
		gs_argv[1] = tmppath;
		gs_argv[2] = "quit.ps";
#endif
		gs_argv[3] = NULL;
		exec_gs((char *)tmp_buf, gs_argv, 1);
	}
	put_pbm(pbm, 0, 0, 0, 0, (dev==1)?IS_POSXY:(IS_POSXY|IS_GSAME), 
		f_gbox?3:2);
	if (total_gsps < current_gsps) total_gsps = current_gsps;
#ifdef	WIN32
	if(f_erace)
#endif
	unlink(tmppath);
	return(True);
}

static void read_wh(FILE *fp, PIXEL *x, PIXEL *y)
{
	int	temp;
	char c;
	
	temp = 0;
	while( isdigit(c = getc(fp)) )
		temp = temp * 10 + c - '0';
	*x = temp;
	while( !isdigit(c = getc(fp)) );
	temp = c - '0';
	while( isdigit(c = getc(fp)) )
		temp = temp * 10 + c - '0';
	*y = temp;
}

/*
typedef	struct	tagBITMAPFILEHEADER {
	uchar	bfType[2];
	uchar	bfSize[4];
	uchar	bfReserved1[2];
	uchar	bfReserved2[2];
	uchar	bfOffBits[4];
} BITMAPFILEHEADER;

typedef	struct	tagBITMAPINFOHEADER {
	uchar	biSize[4];
	uchar	biWidth[4];
	uchar	biHeight[4];
	uchar	biPlanes[2];
	uchar	biBitCount[2];			// color bits 1, 4, 8, 16, 24
	uchar	biCompression[4];
	uchar	biSizeImage[4];
	uchar	biXPelsPerMeter[4];
	uchar	biYPelsPerMeter[4];
	uchar	biCirUsed[4];			// number of pallets
	uchar	biCirImportant[4];
} BITMAPINFOHEADER;
*/

#ifdef	WIN32
/*
 *		$dir\foo.gz ( = iname )   -> $temp\foo ( = iname)
 *		*fp = fopen(iname, mode)  -> *fp = fopen(iname, mode) if fp != NULL
 *		mode should be "r" or "rb"
 */
int ExpandGZ(char *iname, FILE **fp, char *mode)
{
#define	TMPBSIZE	0x8000

	static BOOL f_gunzip;
	int len, pos, res;
	char *s, fname[MAXFILE+4], fname2[MAXFILE+6], *argv[4];
	FILE *fo, *fi;

	res = 1;
	if((fi = fopen(iname, "rb")) == NULL ||
		(res=1, (s = GetTmpDir()) == NULL))
		return res;
	res = 2;
	strcpy(fname, s);
	pos = strlen(iname);
	while(--pos >= 0 &&iname[pos] != ':' && iname[pos] != '\\');
	len = strlen(fname);
	if(len + strlen(iname) - pos > MAXFILE)
		goto quit;
	sprintf(fname + len, "\\%s", iname+pos+1);
	pos = strlen(fname) - 3;
	fname[pos] = 0;
	fo = fopen(fname, mode);
	res = 3;
	if(fo != NULL){						/* already expanded */
chg:	if(fp != NULL){
			fclose(*fp);
			*fp = fo;
		}else
			fclose(fo);
		strcpy(iname,fname);
quit:	fclose(fi);
		return res;
	}
	res = 4;
	fname[pos] = '.';
	if(strcmp(iname, fname)){						/* copy */
		if((s = (char*)marea(TMPBSIZE)) == NULL || (fo = fopen(fname, "wb")) == NULL)
			goto quit;
		while((len = fread(s, 1, TMPBSIZE, fi)) > 0)
			fwrite(s, 1, len, fo);
		fclose(fo);
		Free(s);
	}
	res = 5;
	argv[0] = "gzip -d";		/* gzip -d */
	argv[1] = fname;
	if(*fname != '"'){			/* filename has a space character? */
		for(s = fname; *s; s++){
			if(*s == ' '){
				sprintf(fname2, "\"%s\"", fname);
				argv[1] = fname2;
				break;
			}
		}
	}
	argv[2] = NULL;
	if(f_gunzip || WinMinExecute(argv, 0, TRUE) == FALSE){
unzip:	res = 6;
		f_gunzip = TRUE;
		argv[0] = "gunzip";
		if(WinMinExecute(argv, 0, TRUE) == FALSE)
			goto fail;
	}
	res = 7;
	fname[pos] = 0;
	fo = fopenf(fname, mode);
	if(fo != NULL){
		res = 0;
		goto chg;
	}
	if(!f_gunzip)
		goto unzip;
fail:
	f_gunzip = FALSE;
	goto quit;
}
#endif


static FILE *open_pbm(char *epsfname, int *x, int *y, int mode)
{
	static int f_plug_error;
	int	ch=0, count, col;
#ifdef	DVI_ADD
	int size;
#endif
#ifdef	PLUG
	char plug_ext[32];
	int	type;
#endif
#ifdef	USE_COLOR
	int pal[256];
#endif
	char ppath[MAXPATH], *tmp;
	FILE *fp;

	tmp = pbm_path;
#ifdef	USE_COLOR
	f_mode_BMP = 0;
#endif
#ifdef	PLUG
	if(mode & IS_BMP){
		plug_ext[0] = 0;
		for(ch = strlen(epsfname); ch > 0; ){
			switch(epsfname[--ch]){
				case '.':
					if(strlen(epsfname+(++ch))>= 31) goto plg1;
					strcpy(plug_ext, epsfname+ch);
					if(	 !Stricmp(plug_ext, "bmp")
					  || !Stricmp(plug_ext, "bmc") ){
						strcpy(plug_ext, "bmc");
						goto plg1;
					 }
					f_mode_BMP |= IS_PLUG;
					for(type = 0; graph_ext[type]; type++){
						if(!Stricmp(plug_ext, graph_ext[type]))
							break;
					}
				case ':':
				case '\\':
				case '/':
					goto plg1;
			}
		}
	}
	if(!ch)
		strcpy(plug_ext, "bmc");
plg1:
#endif
	for(count = 0; count < 4; count++){
		switch(count){
			case 0:
				strcpy(tmp_buf, epsfname);
				break;

			case 1:
				name_pbm(epsfname);
				break;

			case 2:
				if(pbm_path == NULL || !*pbm_path)
					continue;
				tmp_buf[0] = 0;
				if(copy_token(ppath, &tmp, DELIMITER))
					count--;
				make_path((char*)tmp_buf, ppath, epsfname, NULL);
				break;
			case 3:
				dvipath((char *)tmp_buf);
				break;
		}
		for( ch = strlen(tmp_buf) ; ch > 0 && tmp_buf[ch] != '.' ; ch--);
		if(!ch){
			ch = strlen(tmp_buf);
			tmp_buf[ch] = '.';
		}
		switch(current_f_GIF){
			case 0:		tmp = "pbm"; break;
//			case 1:		tmp = "gif"; break;
			default:
#ifdef	PLUG
						if(mode & IS_BMP){
							tmp = plug_ext;
							break;
						}
#endif
#if	BMC
						tmp = "bmc"; break;
#else
						tmp = "bmp"; break;
#endif
		}
		strcpy(tmp_buf + ch + 1, tmp);
		chg_pathsep(tmp_buf, PATH_SEP);
retry:
#ifdef	DVI_ADD
		if (!count){
			if( (mode & IS_BMP)
			 && (!strcmp(tmp, "bmp") || !strcmp(tmp, "bmc")) ){
				if( (size = GetAddMemory((char*)tmp_buf, NULL, 0)) >= 0){
	/* Read directly into memory */
					GetAddMemory((char*)tmp_buf,
						bmc_pt = bmc_buf = (char*)marea(size), size);
					bmc_end = bmc_buf + size;
					fp = 0;
					break;
				}
			}else if( (fp = OpenAddFile((char*)tmp_buf, "rb")) != NULL )
	/* Expanded into temporary directry */
				break;
		}
#endif

		if ((fp = fopenf((char *)tmp_buf, "rb")) != NULL){
#ifdef	WIN32
			if(  !strcmp(tmp_buf + ch, ".gz")
			  && !ExpandGZ((char *)tmp_buf, &fp, "rb") ){
					for(ch = strlen(tmp_buf); ch > 0; ch--)
						if(tmp_buf[ch] == '.')
							break;
				if(  !Stricmp(tmp_buf + ch, ".bmc")
				  || !Stricmp(tmp_buf + ch, ".bmp") )
					f_mode_BMP &= ~IS_PLUG;
			}
#endif
			break;
		}
#if	BMC
		if(!Stricmp(tmp_buf + ch, ".bmc")){
			tmp_buf[ch + 3] = 'p';
			goto retry;
		}
#endif
	}
	if(count == 4){
		if((mode & ~IS_BW)!= 1)
		error(WARNING, "Cannot get %s", tmp_buf);
		return(NULL);
	}
#ifdef PLUG
	if(f_mode_BMP & IS_PLUG){
		fclose(fp);
#ifdef WMF
		if(!strcmp(tmp, "wmf")){
			f_mode_BMP |= IS_WMF;
setsize:	*x = dpi;
			*y = DPI;
			return NULL;
		}else if(!strcmp(tmp, "emf")){
			f_mode_BMP |= IS_EMF;
			goto setsize;
		}
#endif
		tmp = NULL;
		switch(open_plugin(tmp_buf, graph_type[type], &bmc_buf, &bmc_end)){
			case 0:
				bmc_pt = bmc_buf;
				get_bmpfile(NULL, &type, &type, y, x);
				f_mode_BMP |= IS_PLUG;
				bmc_pt = bmc_buf;
				break;
			case 1:
				tmp = "Cannot find plug-in for %s";
				break;
			case 2:
				tmp = "Bad format:%s";
				break;
		}
		if(tmp != NULL){
			if(f_rpcolor == C_PATCH || f_rpcolor == C_PATCH2){
				if(f_plug_error == id_dvi + (current_page << 16))
					return NULL;
				else f_plug_error = id_dvi + (current_page << 16);
			}
			error(WARNING, tmp, tmp_buf);
		}
		return NULL;
	}
#endif
	if ((mode & IS_BMP) || current_f_GIF >= 2){
		if(Getc(fp) != 'B')
			goto err_bmp;
		ch = Getc(fp);
#if BMC
		if(ch == 'C'){				/* (ID=="BC")? */
			if(fp)
				bmc2bmp(fp, x, y, IS_BW);
			else{
				bmc2bmp(fp, x, y, 0);
				f_mode_BMP |= IS_PLUG;
			}
			return fp;
		}else 
#endif
		if(ch != 'M'){		/* (ID=="BM")? */
err_bmp:	error(FILE_FAULT, 
#ifdef	USE_COLOR
				"%s isn't a BMP file",
#else
				"%s isn't a monochrome BMP file", 
#endif
				tmp_buf);
				Fclose(fp);
			return NULL;
		}
		for(ch = 0; ch < 8; ch++)
			Getc(fp);
		bmp_top = ReadInt(fp);			/* bfOffBits */
										/* EOF FILEHEADER */
		ReadInt(fp);
		*x = ReadInt(fp);				/* biWidth */
		*y = ReadInt(fp);				/* biHeight */
		Getc(fp); Getc(fp);
		ch = Getc(fp);
		ch += Getc(fp) << 8;			/* biBitCount */
#ifdef	USE_COLOR
		switch(ch){
			case 1:		f_mode_BMP = 2;	break;
			case 4:		f_mode_BMP = 3;	break;
			case 8:		f_mode_BMP = 4;	break;
			case 16:	f_mode_BMP = 6;	break;
			case 24:	f_mode_BMP = 5;	break;
			case 32:	f_mode_BMP = 7;	break;
		}
		if(!f_mode_BMP)
			goto err_bmp;
#else
		if(ch != 1)			/*	1 + (0 <<8) = 2 color */
			goto err_bmp;
#endif
		if( (mode & IS_BW) && current_f_GIF != 3
#ifdef	USE_COLOR
			&& f_mode_BMP != 4
#endif
			)goto quit;
		ch = 16;
		while(ch-- > 0)
			Getc(fp);
		count  = ReadInt(fp);			/* biCirUsed */
#ifdef	USE_COLOR
		if( (mode & IS_BW) && count <= 16 && count > 0){
			f_mode_BMP |= IS_COL16;
			goto quit;
		}
#endif
		ReadInt(fp);					/* EOF BITMAPINFOHEADER */
#ifdef	USE_COLOR
		if(f_mode_BMP == 2)
#endif
		{
			bmp_rev = (Getc(fp) & 0x80)?0:1;
			goto quit;
		}
#ifdef	USE_COLOR
		if(f_mode_BMP == 3 || f_mode_BMP == 4){
			if(count == 2){					/* Use 2 colors */
				if((ch == 0 || ch == 0xff) && 
					ch == Getc(fp) && ch == Getc(fp)){
					Getc(fp);
					ch = Getc(fp);
					if( (ch == 0 || ch == 0xff)
					  && ch == Getc(fp) && ch == Getc(fp)){
						if(ch){
							bmp_on = 1;
							bmp_off = 0;
						 }else{
							bmp_on = 0;
							bmp_off = 1;
						}
						f_mode_BMP |= IS_BW;
					}
				}
			}else{								/* 16 or 256 colors */
				bmp_on = bmp_off = -1;
				if(!(ch = count))
					ch = (f_mode_BMP == 3)?16:256;
				if(mode & IS_BW){
					for(count = 0; count < 16; count++)
						pal[count] = ReadInt(fp);
					for(; count < ch; count++)
						if(	 pal[count & 0xf] != (col = ReadInt(fp))
						  && col != 0x7f7f7f && col != 0 )
							goto quit;			/* 256 colors in 8 bit */
					f_mode_BMP |= IS_COL16;
					goto quit;					/* 16 colors in 8 bit */
				}
				for(count = 0; count < ch; count++)
					pal[count] = ReadInt(fp);
				count = 0;
				Fseek(fp, bmp_top, SEEK_SET);
				if(f_mode_BMP == 3){	/* 16 color */
					col = (*x + 7)&~7;
					while( (ch = Getc(fp)) != EOF){
						count++;
						if(	 (ch & 0xf) != bmp_off
						  && (ch & 0xf) != bmp_on
						  && count % col < *x){
							if(pal[ch & 0xf] == 0xffffff){
								if(bmp_on < 0){
									bmp_on = ch & 0xf;
									goto n16_1;
								}
							}
							else if(pal[ch & 0xf] == 0){
								if(bmp_off < 0){
									bmp_off = ch & 0xf;
									goto n16_1;
								}
							}
							goto quit;
						}
n16_1:					count++;
						ch >>= 4;
						if(	 ch != bmp_off
						  && ch != bmp_on
						  && count % col < *x){
							if(pal[ch] == 0xffffff){
								if(bmp_on < 0){
									bmp_on = ch;
									goto n16_2;
								}
							}else if(pal[ch] == 0){
								if(bmp_off < 0){
									bmp_off = ch;
									goto n16_2;
								}
							}
							goto quit;
						}
n16_2:					count++;
					}
				}else{					/* 256 color */
					col = (*x + 3)&~3;
					while( (ch = Getc(fp)) != EOF){
						if(	 ch != bmp_off
						  && ch != bmp_on
						  && count % col < *x){
							if(pal[ch] == 0){
								if(bmp_off < 0){
									bmp_off = ch;
									goto n256;
								}
							}else if(pal[ch] == 0xffffff){
								if(bmp_on < 0){
									bmp_on = ch;
									goto n256;
								}
							}
							goto quit;
						}
n256:					count++;
					}
				}
bw_ok:			f_mode_BMP |= 0x200|IS_BW;
			}
		}else if(f_mode_BMP == 5 || f_mode_BMP == 6){	/* 24bit or 16bit color */
			Fseek(fp, bmp_top, SEEK_SET);
			for(;;){
				for(count = *x; count > 0; count--){
					if(	 ((ch = Getc(fp))!= 0 && ch != 0xff)
					  ||  ch != Getc(fp)
					  || (f_mode_BMP == 5 && ch != Getc(fp)) ){
						if(ch == EOF)
							goto bw_ok;
						goto quit;
					}
				}
				count  = *x * ((f_mode_BMP==5)?3:2) & 3;
				if(count){
					count = 4 - count;
					while(count-- > 0)
						Getc(fp);
				}
			}
		}
#endif
quit:
		if(fp == NULL){
			f_mode_BMP |= IS_PLUG;
			memmove(bmc_buf, bmc_buf + SIZEOF_BITMAPFILEHEADER,
				bmc_end - bmc_buf - SIZEOF_BITMAPFILEHEADER);
		}
		return(fp);
	}
	if (getc(fp) != 'P' || getc(fp) != '4' || !isspace(Getc(fp))){
		if (!(mode & ~IS_BW))
			error(FILE_FAULT, "%s isn't a pbm file", tmp_buf);
		fclose(fp);
		return(NULL);
	}
	while ((ch = getc(fp)) == '#'){			/* skip comment lines */
		while (getc(fp) != 0x0a && !feof(fp));
	}
	ungetc(ch, fp);
	read_wh(fp, x, y);
	return(fp);
}

static uint byte_width;
static uint new_byte_width;
static PIXEL x_shift;
static PIXEL x_size, y_size;
static PIXEL x_pos, y_pos;
static PIXEL cur_y, data_y;
static PIXEL pixel_width;
static ulong delta_ox;
static ulong delta_nx;
static ulong delta_xend;
static long delta_oy;
static ulong delta_ny;

#ifdef	TILE
static int f_tile;
#endif

/* #define	high(x) ((x)>>16) */
static uchar ROW[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

static void adjust_width(void)
{
	int	bit, x;
												/* clear buffer */
	for (x = new_byte_width + byte_width; x > byte_width; )
		tmp_buf[--x] = 0;
												/* arrange 1 raster line */
	for (bit = 0x80, x = byte_width, delta_ox = (delta_nx >> 1); ; ){
/*		if (tmp_buf[high(delta_ox) >> 3] & ROW[high(delta_ox) & 7] ) */
		if (tmp_buf[delta_ox >> 19] & ROW[(delta_ox >>16) & 7] )
				tmp_buf[x] |= bit;
		if (!(bit >>= 1)){
			bit = 0x80;
			x++;
		}
		if( (delta_ox += delta_nx) >= delta_xend ) break;
	}
}

static void output_line(void)
{
	int	count = 0;
	int	j;
	if(flg_rev != bmp_rev){
		for(j = 0; j < byte_width; j++)
			tmp_buf[j] = ~tmp_buf[j];
	}
	while(cur_y < y_size && data_y >= ((delta_oy + delta_ny) >> 16)){
		if (x_shift > 0 && count++ == 0) adjust_width();
#ifdef	TILE
		write_tiled_pbm(x_pos, y_pos++, x_size, y_size, 
			(char *)(tmp_buf + x_shift), f_tile);
#else
		write_pbm(x_pos, y_pos++, x_size, 1, (char *)(tmp_buf + x_shift));
#endif
		cur_y++;
		delta_oy += delta_ny;
	}
	data_y++;
}

#ifdef	USE_COLOR
struct bmp_data_s {
	char		*name;
	char		*pt;
	char		*eps;
	short int	x_pos;
	short int	y_pos;
	short int	x_size;
	short int	y_size;
	short int	same;
	short int	f_ow;
}	*bmp_data;

struct bmp_name_s {
	struct	bmp_name_s *next;
	short int	x_pos;
	short int	y_pos;
	short int	x_size;
	short int	y_size;
	char name[];
}	*bmp_name, *bmp_name0;

	/* f_ow */
#define	G_REPLACE	0x0001
#define	G_ANTIAREA	0x0002
#define	G_BMP		0x0004

int AddKeepBMP(int mode)
{
	f_ckeep = (mode)?1:0;
	ps_page = current_page;
	return bmp_pt;
}

static void ClearBMPname(void)
{
	struct bmp_name_s *pt0, *pt1;

	for(pt0 = bmp_name; pt0; pt0 = pt1){
		pt1 = pt0->next;
		Free0(pt0);
	}
	bmp_name = bmp_name0 = NULL;
}

static void Clear0BMP(void)
{
	int i;

	for(i = 0; i < bmp_pt; i++){
		if(bmp_data[i].same < 0){
#ifdef	WMF
			if(bmp_data[i].same == F_WMF || bmp_data[i].same == F_EMF){
				FreeWMF((uint)(bmp_data[i].pt), bmp_data[i].same);
				Free0(bmp_data[i].name);
				Free0(bmp_data[i].eps);
			}else
#endif
			if(bmp_data[i].f_ow & G_BMP)
				Free(bmp_data[i].pt - SIZEOF_BITMAPFILEHEADER);
			else{
				if(bmp_data[i].same == -1 || (bmp_data[i].f_ow & G_ANTIAREA)){
					Free0(bmp_data[i].name);
					Free0(bmp_data[i].eps);
				}
				if(bmp_data[i].pt != NULL)
					Free(bmp_data[i].pt);
			}
		}
		bmp_data[i].name = bmp_data[i].eps = NULL;
	}
	ClearBMPname();
	current_gsps = total_gsps = bmp_pt = max_ch_bmp = 0;
	ps_name[0] = NULL;
}

void ClearKeepBMP(void)
{
	if(f_ckeep){
		f_ckeep = 0;
		ps_page = current_page;
		return;
	}
	Clear0BMP();
	reset_ccolor();
	old_id_dvi = id_dvi;
	ps_page = current_page;
	if(max_bmp)
		Free(bmp_data);
	max_bmp = 0;
}

#if 0
void FreeBMPdata(void)
{
	int	i;

	for(i = 0; i < bmp_pt; i++){
		if(bmp_data[i].same < 0){
#ifdef	WMF
			if(bmp_data[i].same == F_WMF || bmp_data[i].same == F_EMF){
				FreeWMF((uint)(bmp_data[i].pt), bmp_data[i].same);
				Free0(bmp_data[i].name);
				Free0(bmp_data[i].eps);
			}else
#endif
			{
				Free0(bmp_data[i].pt);
				if(bmp_data[i].f_ow & G_ANTIAREA)){
					Free0(bmp_data[i].name);
					Free0(bmp_data[i].eps);
				}
			}
		}
		bmp_data[i].pt = NULL;
	}
}
#endif

int strlen0(char *s)
{
	return (s)?strlen(s):0;
}

int sizeofBMPdata(int num)
{
	int size, same;

	if(num < 0 || num >= bmp_pt)
		return 0;
#ifdef	WMF
	if((same = bmp_data[num].same) == F_EMF || same == F_WMF)
		return sizeof(struct bmp_data_s) + strlen0(bmp_data[num].name)
		 + strlen0(bmp_data[num].eps);
#endif
	if(bmp_data[num].f_ow & G_BMP){
		return sizeof(struct  bmp_data_s) + SIZEOF_BITMAPFILEHEADER
		+ sizeofBMP(bmp_data[num].pt);
	}
	size = (same <= -2)?
		sizeof(struct bmp_data_s):
		(strlen0(bmp_data[num].name)+strlen0(bmp_data[num].eps)
		  +(sizeof(struct bmp_data_s)+1));
	if(same < 0){
		size += sizeofBMP(bmp_data[num].pt);
		if(same <= -2 && (bmp_data[num].f_ow & G_ANTIAREA))
			size += sizeofBMP(bmp_data[num].name);
	}
	return size;
}

static BOOL ExpandBMPdata(void)
{
	struct bmp_data_s *p;

	if(max_bmp > (MAX_BMP - UNIT_BMP))
		return FALSE;
	if(!max_bmp){
		bmp_data = (struct bmp_data_s *)marea(
					sizeof(struct bmp_data_s)*(UNIT_BMP+2));
		if(bmp_data){
			max_bmp = UNIT_BMP;
			return TRUE;
		}
		return FALSE;
	}
	p = (struct bmp_data_s *)marea(
		sizeof(struct bmp_data_s)*(max_bmp + UNIT_BMP + 2));
	if(p == NULL)
		return FALSE;
	memcpy(p, bmp_data, sizeof(struct bmp_data_s)*max_bmp);
	Free(bmp_data);
	max_bmp += UNIT_BMP;
	bmp_data = p;
	return TRUE;
}

char *GetBMPname(int num, int type)
{
	int mode;

	return ( num < 0 || num >= bmp_pt
	  || ((mode = bmp_data[num].same) < -1 && mode > F_WMF) )?
		NULL:(type?bmp_data[num].eps:bmp_data[num].name);
}

/*
  type =  1:			 copy rectangle area (for figure)
		  0, -1, -2, -3: merge
		 -4:			 replace with transparent background (for characters)
		 -8:			 copy rectangle area (for character)
*/
char *GetBMPdata(int num, int *x_pos, int *y_pos, int *x_size, int *y_size, 
	int *type)
{
	int same, mode, size, tmp;
	FILE *fp;

	if (
#ifdef	DOUBLE_PAGE
		!f_ckeep && 
#endif
		(ps_page != current_page || old_id_dvi != id_dvi))
		ClearKeepBMP();

	if(num < 0 || num >= bmp_pt)
		return NULL;
	if(bmp_data[num].pt != NULL){
ret:	*x_pos = bmp_data[num].x_pos;
		*y_pos = bmp_data[num].y_pos;
		*x_size = bmp_data[num].x_size;
		*y_size = bmp_data[num].y_size;
		mode = bmp_data[num].same;
		tmp = *type;
		*type = (mode >= -1)?((bmp_data[num].f_ow & G_REPLACE)?1:0):
				((mode == -8)?1:mode);
/*		if(*type == -2 && f_rpcolor) */
/*			*type = -4; */
// error(11, "(%d %d)", mode, tmp);
			return (mode >= 0 || !tmp || !(bmp_data[num].f_ow & G_ANTIAREA))?
													/* (!anti-areasing)? */
			bmp_data[num].pt:bmp_data[num].name;
	}
	if( (same = bmp_data[num].same) >= 0 && bmp_data[same].pt != NULL ){
		bmp_data[num].pt = bmp_data[same].pt;
		goto ret;
	}
#ifdef	WMF
	if(same == F_WMF || same == F_EMF){
		bmp_data[num].pt = (uchar *)GetWMF(bmp_data[num].name, same);
		goto ret;
	}
#endif
	if ((fp = fopenf(bmp_data[num].name, "rb")) == NULL)
		return NULL;
	getc(fp); 
#if	BMC
	if(getc(fp) == 'C')
		bmp_data[num].pt = bmc2bmp(fp, &tmp, &tmp, 0);
	else
#endif
	{
#if	1
		size = filelength(fileno(fp)) - SIZEOF_BITMAPFILEHEADER;
		ReadInt(fp); 
#else
		size = ReadInt(fp) - SIZEOF_BITMAPFILEHEADER;
#endif
		ReadInt(fp);ReadInt(fp);
		if( size <= 0 || (bmp_data[num].pt = (char*)marea(size)) == NULL ){
			fclose(fp);
			return NULL;
		}
		fread(bmp_data[num].pt, size, 1, fp);	/* read with BITMAPINFOHEADER */
		fclose(fp);
	}
	if(same >= 0)
		bmp_data[same].pt = bmp_data[num].pt;
	goto ret;
}

BOOL PutColoredChar(BUFFER *buf, int x_byte, int x_size, int y_size, 
	int x_pos, int y_pos, int fr_color, int bk_color)
{
	BUFFER *at;
	int type;

	if(f_ccolor < -1 || (f_rpcolor == C_PATCH2 && !f_ttout) )
		return FALSE;
	type = -2;								/* merge */
	if(fr_color < 0){
		if(fr_color == -2)					/* replace */
			type = -8;
		fr_color = f_ccolor & 0xffffff;		/* color of letter */
		if(!fr_color && (gray_number < 0))
			fr_color = 0xffffff;			/* white letter */
		bk_color = (gray_number < 0)?0:0xffffff;	/* background */
		if(fr_color == bk_color){
			bk_color = (gray_number < 0)?0xffffff:0;
			if(type == -8)
				goto copy;
			type = -3;						/* erace */
		}else if(type == -8)
			goto copy;
		else if(f_ccolor & 0x1000000)		/* replace mode/special */
			type = -4;						/* erace & put */
	}
	if(f_clevel && (f_rpcolor == C_AUTO_P2 || f_rpcolor == C_AUTOREP) && type != -3){
											/* automode & used AND */
		if( (f_clevel & 2) || (fr_color & f_ocolor) != fr_color)
			type = -4;						/* replaced or non-darker color */
	}
	if(gray_number > 0){					/* Black */
		if(fr_color == 0 && bk_color == 0xffffff){
black:		if(	 (!f_ucolor && f_rpcolor != C_PATCH && f_rpcolor != C_PATCH2)
											/* no color used (incl graphic) */
			  || ((f_rpcolor == C_AUTO_P2 || f_rpcolor == C_AUTOREP) && !(f_clevel & 2))
											/* auto mode & not replaced */
			  ||  f_rpcolor == C_REPLACE )			/* merge mode */
				return FALSE;
			type = -2;
		}
	}else if(fr_color == 0xffffff && bk_color == 0)
		goto black;
	if(f_rpcolor == C_MERGE_BACK && type == -4)
		bk_color = (ccolor_pt > 1)?ccolor[ccolor_pt-1]:
					((f_bcolor < 0)?bk_color:f_bcolor);
	else if((f_rpcolor == C_MERGE_DEF || f_rpcolor == C_PATCH) && type == -4 
		&& (f_bcolor & 0xffffff) != 0xffffff )
		bk_color = f_bcolor & 0xffffff;
copy:
	count_gsps();
	current_gsps--;

	if(	 (bmp_pt >= max_bmp && !ExpandBMPdata())
	  || ( (max_ch_bmp += x_byte*y_size) > MAX_CH_BMP ) ){
		if(!f_manycolor){
			error(WARNING, "Too many colored BMP/characters in a page");
			f_manycolor = 1;
		}
		return FALSE;
	}
	else if( (bmp_data[bmp_pt].pt = 
	  KeepBMPBuf(buf, x_byte, x_size, y_size, fr_color, bk_color, &at) )
	   == NULL)
		return FALSE;
	f_ucolor |= 2;
	f_clevel |= (type <= -3)?3:1;
	f_ocolor = fr_color;
	if(at != NULL)
		f_ucolor |= 4;
	bmp_data[bmp_pt].name = (at == NULL)?"":at;
	bmp_data[bmp_pt].eps = NULL;
	bmp_data[bmp_pt].same = type;
	bmp_data[bmp_pt].x_pos = x_pos;
	bmp_data[bmp_pt].y_pos = y_pos;
	bmp_data[bmp_pt].x_size = x_size;
	bmp_data[bmp_pt].y_size = y_size;
	bmp_data[bmp_pt++].f_ow = (at != NULL)?G_ANTIAREA:0;
#ifdef	WIN32G
	if(f_ttout){
		TTBMPOut(0);
		Clear0BMP();
	}
#endif
	return TRUE;
}

static void DivideBMPdata(int num, int dev)
{
	int dest_y_size, head_size, byte_width, height, col, pal, count, y0, y1;
	uchar *buf, *tmp;

	if(bmp_pt + (++dev) >= max_bmp && !ExpandBMPdata()){
		error(WARNING, "Too many colored BMP/characters in a page");
skp:	bmp_pt++;
		return;
	}
	dest_y_size = bmp_data[bmp_pt].y_size;
	buf = bmp_data[bmp_pt].pt;
	col = read_num(buf+14, 2);
	byte_width = ((read_num(buf+4,4)*col+31)/32)*4;
	height = read_num(buf+8,4);
	pal = read_num(buf+32, 4);
	if(col < 16){
		if(pal == 0)
			pal = (1<<col);
	}else if(col == 16 || col == 32){		/* 16, 32 */
		switch(read_num(buf+16, 4)){
			case 0:			/* BI_RGB: */
				break;
			case 3:			/* BI_BITFIELDS: */
				pal = 3;
				break;
			default:
				goto skp;
		}
	}
	head_size = 4*pal + SIZEOF_BITMAPINFOHEADER;
	for(count = 0; count < dev; count++){
		bmp_data[bmp_pt+count].name = 
		bmp_data[bmp_pt+count].eps = NULL;
		bmp_data[bmp_pt+count].same = -1;
		bmp_data[bmp_pt+count].x_pos = bmp_data[bmp_pt].x_pos;
		bmp_data[bmp_pt+count].x_size = bmp_data[bmp_pt].x_size;
		bmp_data[bmp_pt+count].f_ow = bmp_data[bmp_pt].f_ow;
		if(count)
			bmp_data[bmp_pt+count].y_pos = bmp_data[bmp_pt+count-1].y_pos
				+ bmp_data[bmp_pt+count-1].y_size;
		if(count == dev-1)
			bmp_data[bmp_pt+count].y_size = dest_y_size - 
				bmp_data[bmp_pt+count].y_pos + bmp_data[bmp_pt].y_pos;
		else{
			col = dest_y_size*(count+1)/dev - 
				bmp_data[bmp_pt+count].y_pos + bmp_data[bmp_pt].y_pos;
			bmp_data[bmp_pt+count].y_size = col;
			/* /GetYGray()*GetYGray(); */
		} 
		y0 = height*
			(bmp_data[bmp_pt+count].y_pos - bmp_data[bmp_pt].y_pos)
			/dest_y_size;
		y1 = height*
			(bmp_data[bmp_pt+count].y_pos + bmp_data[bmp_pt+count].y_size
			 - bmp_data[bmp_pt].y_pos)/dest_y_size;
		bmp_data[bmp_pt+count].pt = 
			tmp = (char*)marea(head_size + (y1 - y0)*byte_width);
		memcpy(tmp, buf, head_size);
		memcpy(tmp + head_size, buf + head_size + (height - y1)*byte_width,
			(y1-y0)*byte_width);
		write_num(tmp+8, 4, y1-y0);
		write_num(tmp+20, 4, (y1-y0)*byte_width);
	}
	Free0(buf);
	bmp_pt += dev;
}

static void KeepBMPname(char *name, int x_pos, int y_pos, int x_size, int y_size)
{
	struct bmp_name_s *pt;
	pt = (struct bmp_name_s *)
		marea(strlen(name)+sizeof(struct bmp_name_s)+1);
	pt->x_pos = x_pos;
	pt->y_pos = y_pos;
	pt->x_size = x_size;
	pt->y_size = y_size;
	pt->next = NULL;
	strcpy(pt->name, name);
	if(!bmp_name0)
		bmp_name = bmp_name0 = pt;
	else{
		bmp_name0->next = pt;
		bmp_name0 = pt;
	}
}

/*
   name : filename of BMP
		: NULL means that BMP data exists at bmc_buf
		  (Susie's plug-in	or	cross/16 pages)

   dev	== -1:	name == NULL --> BITMAPFILEHEADER is attatched precceding 
								 to bmc_buf (cross/16 pages)
		==	0:	BITMAPFILEHEADER doesn't exist
		>=	1:	keep BMP data devided into	dev	 pieces
*/
static void KeepBMP(char *name, int x_pos, int y_pos, int x_size, int y_size, 
	int dev)
{
	int	i;

	if(!F_GS){
		// 2008.08.17 by Otobe (if name == tmp_buf, MUST NOT free it!)
		if(name != NULL && name != tmp_buf)
			Free(name);
		else
			Free0(bmc_buf - SIZEOF_BITMAPFILEHEADER);
		return;
	}
	if(bmp_pt >= max_bmp && !ExpandBMPdata()){
		error(WARNING, "Too many colored BMP/characters in a page");
		return;
	}
#ifdef	WMF
	if(f_mode_BMP&(IS_WMF|IS_EMF)){
		bmp_data[bmp_pt].same = (f_mode_BMP&IS_EMF)?F_EMF:F_WMF;
		dev = 0;
		goto find0;
	}else
#endif
	bmp_data[bmp_pt].same = -1;
#ifdef	PLUG
	if(name == NULL){
		bmp_data[bmp_pt].name = NULL;
		bmp_data[bmp_pt].eps = (org_ps_path[0])?dup_string(org_ps_path):NULL;
		bmp_data[bmp_pt].pt = bmc_buf;
		bmc_buf = bmc_pt = bmc_end = NULL;
		goto find1;
	}
#endif
	if(dev <= 0){
		for(i = 0; i < bmp_pt && i < 0x7ffff; i++){
			if(bmp_data[i].name == NULL || strcmp(bmp_data[i].name, name))
				continue;
			if(	 bmp_data[i].x_pos == x_pos
			  && bmp_data[i].y_pos == y_pos
			  && bmp_data[i].x_size == x_size
			  && bmp_data[i].y_size == y_size )
				return;					/* same object with same position */
			bmp_data[bmp_pt].same = i;
			bmp_data[bmp_pt].name = bmp_data[i].name;
			bmp_data[bmp_pt].eps = bmp_data[i].eps;
			goto find;
		}
	}
find0:
	bmp_data[bmp_pt].name = dup_string(name);
	bmp_data[bmp_pt].eps = (org_ps_path[0])?dup_string(org_ps_path):NULL;
find:
	bmp_data[bmp_pt].pt = NULL;
find1:
	bmp_data[bmp_pt].x_pos = x_pos;
	bmp_data[bmp_pt].y_pos = y_pos;
	bmp_data[bmp_pt].x_size = x_size;
	bmp_data[bmp_pt].y_size = y_size;
	bmp_data[bmp_pt++].f_ow = ((f_gow)?G_REPLACE:0)|((dev<0)?G_BMP:0);

	if(dev > 0){
		if(bmp_data[bmp_pt-1].pt == NULL){
			GetBMPdata(bmp_pt-1, &x_pos, &x_pos, &x_pos, &x_pos, &x_pos);
			Free0(bmp_data[bmp_pt-1].name);
			Free0(bmp_data[bmp_pt-1].eps);
			bmp_data[bmp_pt-1].name = bmp_data[bmp_pt-1].eps = NULL;
		}
		DivideBMPdata(--bmp_pt, dev);
	}
	f_ucolor |= 1;
	if(f_gsame && GetXDpi() > 1)
		f_ucolor |= 8;
#ifdef	WIN32G
	if(f_ttout){
		TTBMPOut(0);
		Clear0BMP();
	}
#endif
}

void DisplayBMP(uchar *buf, int x_pos, int y_pos, int x_size, int y_size, 
	int mode)
{
	int tmp;

	bmc_buf = buf + SIZEOF_BITMAPFILEHEADER;
	tmp = f_gow;
	if(mode)
		f_gow = (mode == 1)?1:0;
	KeepBMP(NULL, x_pos, y_pos, x_size, y_size, -1);
	f_gow = tmp;

}
#endif

static BOOL put_pbm(char *pbmfname, PIXEL h, PIXEL v, 
	PIXEL width, PIXEL height, int mode, int fgbox)
{
	FILE *fp;
	int i, bmp_width, bmp_byte_width, tmp, size, old_spcolor, x_realpos;
	PIXEL x, y, x2 = 0, y2 = 0;
	int	f_topdown = 0;
#ifdef	USE_COLOR
	int col, j, k;
	BUFFER *s, *t;
#endif
	if ((fp = open_pbm(pbmfname, &x2, &y2, 
		(mode & IS_BMP)|((F_GS == DO_GSS)?1:0))) == NULL){
#ifdef	PLUG
			if(!(f_mode_BMP & IS_PLUG) || bmc_buf == NULL)
# ifdef WMF
				if(!(f_mode_BMP & (IS_EMF|IS_WMF)))
# endif
#endif
			return(FALSE);
	}
#ifdef	USE_ETF
	if(f_make_imgetf && (fgbox & 4))
		SetETFimg(tmp_buf);
#endif
	if(y2 < 0){
		y2 = -y2;
		f_topdown = 1;
	}
	if (mode & IS_SCALE){
			x = (PIXEL)ROUND((((float)x2) *	 width) / 100.0);
			y = (PIXEL)ROUND((((float)y2) * height) / 100.0);
	}
	else{
		y = height;
		if (width == 0){
			if (height == 0){
				x = x2;
				y = y2;
			}
			else
				x = (((long)y) * x2 + (y2 >> 1))/y2;
		}
		else{
			x = width;
			if (height == 0)
				y = (((long)x) * y2 + (x2 >> 1))/x2;
		}
	}
#ifdef	TILE
	f_tile = mode & IS_TILE;
#endif
	if (x + width > 8 * (COMMON_SIZE - 258)) {
		error(WARNING, "tmp_buf overflow!: %ddots", width);
		fclose(fp);
		return FALSE;
	}

	if ( !(mode & IS_POS)
#ifdef	TILE
		&& !f_tile
#endif
		) {
		x_pos = get_current_x();
		y_pos = get_current_y();
	}
	else{
		x_pos = h;
		y_pos = v;
	}
	x_size = x;
	y_size = y;
	if (mode & IS_POSXY){
		x_pos -= dpi;
		y_pos += -y_size;
	}
	x_realpos = x_pos;
	if(f_taterot == 1 && ptex_d == 1)
		x_realpos -= x_size;
	if (fgbox & 1)	boxpic(x_realpos, y_pos, x_size, y_size);
#ifdef	HYPERTEX
	if ((f_hyper & F_H_BOX) && (fgbox & 2))
		add_hyper_box0(x_realpos, y_pos, x_size, y_size);
#endif
#ifdef	USE_COLOR
#ifdef WMF
								/* colored DIB or EMF or WMF */
	if( ((f_mode_BMP & (IS_EMF|IS_WMF|0xff)) > 2 && !(f_mode_BMP & IS_BW))
								/* if patch mode, then patch DIB */
	   || ((f_rpcolor == C_PATCH || f_rpcolor == C_PATCH2) && current_f_GIF >= 2) ){
#else
	if((f_mode_BMP & 0xff) > 2 && !(f_mode_BMP & IS_BW)){
#endif
		if(mode & IS_GSAME){
			x_size *= GetXGray();
			x_size *= GetYGray();
		}
		if(get_rot_matrix(0)){
			rotate_address(&x_pos, &y_pos);
			error(WARNING, "Cannot rotate the figure %s", pbmfname);
		}
		size = x2*y2;
		if(size < x_size * y_size)
			size = x_size*y_size;
		size /= MAX_BMP_SIZE;
		x_realpos = x_pos;
		if(f_taterot == 1 && ptex_d == 1)
			x_realpos -= x_size;
		KeepBMP(
#ifdef	PLUG
			((f_mode_BMP&(IS_PLUG|IS_EMF|IS_WMF))==IS_PLUG)?NULL:
#endif
			tmp_buf, x_realpos, y_pos, x_size, y_size, size);
		find_psname(pbmfname);
#if	BMC
		if(fp == NULL)
			return TRUE;
#endif
		goto f_end;
	}
#endif
#if	BMC
	if((f_mode_BMP & IS_BMC) && fp != NULL){
		fseek(fp, 0, SEEK_SET);
		bmc2bmp(fp, &tmp, &tmp, 0);
		fp = NULL;
	}
#endif

	delta_nx = (((long)x2) << 16) / x_size;
	delta_xend = delta_nx * x_size + (delta_nx >> 1);
	delta_ny = (((long)y2) << 16) / y_size;
	delta_oy = -((signed long)delta_ny >> 1);
	byte_width = (x2 + 7) / 8;
	pixel_width = x2;
	new_byte_width = (x_size + 7) / 8;
	x_shift = (((x_size + 7) & 0xfff8) == ((x2 + 7) & 0xfff8))? 0:byte_width;
	cur_y = data_y = 0;
	if (x_shift != 0 || F_GS != DO_GS)
		error(DIRECT, "Figure (%d,%d)->(%d,%d)\n",
			x2, y2,(x_shift == 0)?x2:x_size, y_size);
	bmp_width = byte_width;
#ifdef	USE_COLOR
	switch(f_mode_BMP & 0xff){
		case 3:		/* 16 color */
			bmp_width = (x2 + 1)/2;
			break;
		case 4:		/* 256 color */
			bmp_width = x2;
			break;
		case 5:		/* full color, 24 bit */
			bmp_width = x2*3;
			break;
		case 6:		/* 16 bit color */
			bmp_width = x2*2;
			break;
		case 7:		/* 32 bit color */
			bmp_width = x2*4;
			break;
	}
	if((f_mode_BMP & 0xff) >= 2){
		bmp_width = (bmp_width + 3)&~3;
		if((f_mode_BMP & 0xff) > 2)
			bmp_byte_width = x2;
	}
	old_spcolor = f_spcolor;
	f_spcolor = FALSE;						/* for B/W image data */
#else
	bmp_width = (byte_width + 3)&~3;
#endif
	KeepBMPname(org_ps_path, x_realpos, y_pos, x_size, y_size);
	if(f_gow)
		alter_bitblt_ow(TRUE);
	if(f_taterot == 1)
		x_pos -= x_size;
	for(i = 0; i < y2; i++){
		if((mode & IS_BMP) || current_f_GIF == 2
#ifdef	USE_COLOR
		  || (f_mode_BMP & IS_BW)
#endif
		)
		Fseek(fp, bmp_top + bmp_width*((f_topdown)?i:(y2-i-1)), SEEK_SET);
		Fread(tmp_buf, sizeof(char), bmp_width, fp);
#ifdef	USE_COLOR
		if(f_mode_BMP & IS_BW){
			s = t = tmp_buf;
			col = 0xff;
			k = 0x80;
			switch(f_mode_BMP & 0xff){
			  case 3:							/* 16 colors */
				for(j = 0; j < bmp_byte_width; j++){
					if((tmp_buf[j] >> 4) == bmp_on)
						col -= k;
					k >>= 1;
					if((tmp_buf[j] & 0xf) == bmp_on)
						col -= k;
					if(k <= 1){
						*s++ = col;
						col = 0xff;
						k = 0x80;
					}else
						k >>= 1;
				}
				*s = col;
				break;

			  case 4:							/* 256 colors */
				for(j = 0; j < bmp_byte_width; j++){
					if(*t++ == bmp_on)
						col -= k;
					if(k <= 1){
						*s++ = col;
						col = 0xff;
						k = 0x80;
					}else
						k >>= 1;
				}
				*s = col;
				break;

			  case 5:
			  case 6:
				for(j = 0; j < bmp_byte_width; j++){
					if(*t)
						col -= k;
					if((f_mode_BMP & 0xff)== 5)
						t += 3;	
					else
						t += 4;
					if(k <= 1){
						*s++ = col;
						col = 0xff;
						k = 0x80;
					}else
						k >>= 1;
				}
				*s = col;
				break;
			}
		}
#endif
		output_line();
	}
#ifdef	USE_COLOR
	f_spcolor = old_spcolor;
#endif
	if(f_gow)
		alter_bitblt_ow(FALSE);
f_end:
	Fclose(fp);
	return TRUE;
}

static void name_pbm(char *path)
{
#ifdef UNIX
	char name[MAXFILE];
	char top_path[MAXFILE], *tmp;
	int i, j;

	get_fname(path, name);
#else
	char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT];
	char top_path[MAXFILE], *tmp;

	fnsplit(path, drive, dir, name, ext);	/* get name from path */
	strcat(name, ".");
#endif

	top_path[0] = 0;
	tmp = pbm_path;
	if(pbm_path)
		copy_token(top_path, &tmp, DELIMITER);
#ifdef GIF
	make_path((char *)tmp_buf, top_path, name, 
		(!current_f_GIF)?".pbm":((current_f_GIF==1)?".gif":".bmp"));
#else
	make_path((char *)tmp_buf, top_path, name, ".pbm");
#endif
}

char *MakeTmpPath(char *name)
{
	int len;
	static char tpath[MAXFILE+4];
	tpath[MAXFILE-2] = 0;

	if(SetPath(tpath, "^?")){
		len = strlen(tpath);
#ifdef	UNIX
		if(len > 0 && tpath[len-1] != '/')
			strcat(tpath, "/");
#else
		if(len > 0 && tpath[len-1] != '\\')
			strcat(tpath, "\\");
#endif
	}else
		tpath[0] = 0;
	len = strlen(tpath);
	strncpy(tpath + len, name, MAXFILE+2 - len);
	tpath[MAXFILE-1] = 0;
	return tpath;
}

static char *dvipath(char *path)
{
	int pos;

#ifdef UNIX
	char name[MAXFILE];

	get_fname(path, name);
#else
	char drive[MAXDRIVE], dir[MAXDIR], name[MAXFILE], ext[MAXEXT];

	fnsplit(path, drive, dir, name, ext);
#endif
	strcpy(tmp_buf, current_name);
	for(pos = strlen(tmp_buf); pos >= 0; pos--){
		if(tmp_buf[pos] == '\\' || tmp_buf[pos] == '/' || tmp_buf[pos] == ':')
			break;
	}
	strcpy(tmp_buf+pos+1, name);
#ifndef	UNIX
	strcat(tmp_buf, ext);
#endif
	return (char *)tmp_buf;
}

BOOL SetPath(char *path, char *s)
{
	int len;
	char *t;
	char top[0x200];

	if(s[0] == '^'){
		switch(s[1]){
			case 'x':
				strcpy(top, GetOutPath("exe"));
				len = strlen(top) - 4;
				while(len > 0
				  && top[len] != '\\' && top[len] != ':' && top[len] != '/')
					len--;
				top[len] = 0;
cpy:			len = strlen(top);
				if(len + strlen(s+=2) >= MAX_PATH-1)
					error(PROGRAM_STOP, "Too long filename %s%s\n", top, s);
				strcpy(top+len, s);
				strcpy(path, top);
				return TRUE;
#ifdef	USE_WINAPI
			case 'w':
				get_windows_directory(top);
				goto cpy;
#endif
			case 'T':
				if((t = getenv("TEXMFMAIN")) == NULL)
					t = getenv("TEXMF");
				if(t != NULL){
					strcpy(top, t);
					chg_pathsep(top, PATH_SEP);
					goto cpy;
				}
				break;

			case 'F':
				t = GetAddFile(s+3);
				if(t != NULL){
					strcpy(path, t);
					return TRUE;
				}
				break;

			case '?':
				if((t=getenv("TMP")) != NULL || (t=getenv("TEMP")) != NULL){
					strcpy(top, t);
					len = strlen(top) - 1;
					if(top[len] == PATH_SEP)
						top[len] = 0;
					goto cpy;
				}
				if(*s == PATH_SEP)
					s++;
				break;
		}
	}
	if(s != path){
		if(strlen(s) > MAX_PATH -1)
			error(PROGRAM_STOP, "Too long filename %s\n", s);
		strcpy(path, s);
	}
	return FALSE;
}

#ifndef	UNIX
void chg_pathsep(uchar *path, char ch)
{
	while(*path){
		if(issjis1(*path) && path[1]
#ifdef	WIN32G
		&& IsJapanese()
#endif
		){
			path++;
		}else if (*path == '/' || *path =='\\') *path = ch;
		path++;
	}
}
#endif
