/* COPYRIGHT (C) 1990, 1992 Aladdin Enterprises.  All rights reserved.
   Distributed by Free Software Foundation, Inc.
   
   This file is part of Ghostscript.
   
   Ghostscript is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
   to anyone for the consequences of using it or for whether it serves any
   particular purpose or works at all, unless he says so in writing.  Refer
   to the Ghostscript General Public License for full details.
   
   Everyone is granted permission to copy, modify and redistribute
   Ghostscript, but only under the conditions described in the Ghostscript
   General Public License.  A copy of this license is supposed to have been
   given to you along with Ghostscript so you can know your rights and
   responsibilities.  It should be in a file named COPYING.  Among other
   things, the copyright notice and this notice must be preserved on all
   copies.  */

/* dviprlib.c */

#include "stdio_.h"
#include "ctype_.h"
#include "malloc_.h"
#include "string_.h"
#include "gstypes.h"
#include "gsmemory.h"
#include "gp.h"

/* include library header. */
#define dviprlib_implementation
#include "dviprlib.h"

/* The remainder of this file is a copy of the library for dviprt. */


/***** From rcfg.c *****/
/* $Id: dviprlib.c,v 1.3 2002/07/20 21:03:20 tillkamppeter Exp $ */


/*--- forward declarations ---*/
private int dviprt_read_S_cfg(P2(dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_read_QR_cfg(P2(dviprt_cfg_t *,dviprt_cfg_i *));
     
/*--- library functions ---*/
int 
dviprt_readcfg(char *ifname,dviprt_cfg_t *pcfg,uchar *pcodebuf,int codebuf_s,
    uchar *pworkbuf,int workbuf_s)
{
  int code;
  int ver;
  dviprt_cfg_i info;
  
  info.fname = ifname;
  info.line_no = -1;
  if (ifname) {
    info.file = fopen(ifname,gp_fmode_rb);
    if (info.file == NULL) {
      dviprt_printcfgerror(&info,"Cannot open.\n",-1);
      return CFG_ERROR_FILE_OPEN;
    }
  }
  else {
    info.file = stdin;
  }
  
  fseek(info.file,16,0);
  ver = fgetc(info.file);
  fseek(info.file,0,0);
  info.codebuf = pcodebuf;
  info.readbuf = pworkbuf;
  info.codebuf_size = codebuf_s;
  info.readbuf_size = workbuf_s;
  code = (ver == 'S') ? dviprt_read_S_cfg(pcfg,&info) 
    : dviprt_read_QR_cfg(pcfg,&info);
  
  if (ifname) fclose(info.file);
  return code;
}

/*--- internal routines ---*/
private int 
dviprt_read_S_cfg(dviprt_cfg_t *pcfg,dviprt_cfg_i *pinfo)
{
  FILE *ifp;
  long intoff,stroff,codeoff;
  int i,count;
  uchar *pbuf,*rbuf;
  int code;
  char *ptype;
  int n;
  
  if ((code = dviprt_setcfgbuffer_(pinfo,100,0)) < 0) return code;
  dviprt_initcfg_(pcfg,pinfo);
  
  ifp = pinfo->file;
  rbuf = pinfo->readbuf;
  
  if (fread(rbuf,20,1,ifp) < 1) {
    dviprt_printcfgerror(pinfo,"Read error.\n",-1);
  }
  if (rbuf[17] != 0xff || rbuf[18] != 0xff) {
  not_cfg:
    dviprt_printcfgerror(pinfo,"This file does not seem *.CFG.\n",-1);
    return CFG_ERROR_OTHER;
  }
  if (memcmp(rbuf,CFG_MAGIC_NUMBER,2))
    goto not_cfg;
  pcfg->version = rbuf[2] | ((uint)rbuf[3] << 8);
  if (pcfg->version > CFG_VERSION) {
    sprintf(dviprt_message_buffer,
	    "This *.CFG file is too new version(ver.%u).\n",pcfg->version);
    dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
    return CFG_ERROR_OTHER;
  }
  
#define bytes2long(p) ((p)[0] | ((long)(p)[1]<<8) | \
		       ((long)(p)[2]<<16) | ((long)(p)[3]<<24))
  intoff = bytes2long(rbuf+4);
  stroff = bytes2long(rbuf+8);
  codeoff = bytes2long(rbuf+12);
#undef bytes2long
  
  fseek(ifp,intoff,0);
  count = fgetc(ifp);
  fread(rbuf,count*3,1,ifp);
  
  pbuf = rbuf;
  for (i=0;i<count;i++) {
    n = pbuf[0];
    if (n >= CFG_INTEGER_TYPE_COUNT) {
      ptype = "integer";
    unknown_no:
      sprintf(dviprt_message_buffer,
	      "Unknown %s type value No.%d is found.\n",ptype,n);
      dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
      return CFG_ERROR_OTHER;
    }
    pcfg->integer[n] = pbuf[1] | ((uint)pbuf[2]<<8);
    pbuf += 3;
  }
  
  fseek(ifp,stroff,0);
  count = fgetc(ifp);
  pbuf = NULL;
  for (i=0;i<count;i++) {
    int l;
    fread(rbuf,3,1,ifp);
    n = rbuf[0];
    l = rbuf[1] | ((uint)rbuf[2]<<8);
    if (n >= CFG_STRINGS_TYPE_COUNT) {
      ptype = "strings";
      goto unknown_no;
    }
    if (pinfo->codebuf == NULL) {
      pcfg->strings[n] = (uchar *)malloc(l+1);
      if (pcfg->strings[n] == NULL) {
      no_memory:
        dviprt_printcfgerror(pinfo,"Memory exhausted.\n",-1);
        return CFG_ERROR_MEMORY;
      }
    }
    else {
      pcfg->strings[n] = pinfo->pcodebuf;
      pinfo->pcodebuf += (l+1);
    }
    fread(pcfg->strings[n],l,1,ifp);
    *(pcfg->strings[n]+l) = 0;
  }
  
  fseek(ifp,codeoff,0);
  count = fgetc(ifp);
  for (i=0;i<count;i++) {
    int l;
    fread(rbuf,3,1,ifp);
    n = rbuf[0];
    l = rbuf[1] | ((uint)rbuf[2]<<8);
    
    if (n >= CFG_PRTCODE_TYPE_COUNT) {
      ptype = "printer code";
      goto unknown_no;
    }
    if (pinfo->codebuf == NULL) {
      pcfg->prtcode[n] = (uchar *)malloc(l+1);
      if (pcfg->prtcode[n] == NULL)
        goto no_memory;
    }
    else {
      pcfg->prtcode[n] = pinfo->pcodebuf;
      pinfo->pcodebuf += (l+1);
    }
    fread(pcfg->prtcode[n],l,1,ifp);
    *(pcfg->prtcode[n]+l) = 0;
    pcfg->prtcode_size[n] = l;
  }
  dviprt_resetcfgbuffer_(pinfo);
  return 0;
}

private int 
dviprt_read_QR_cfg(dviprt_cfg_t *pcfg,dviprt_cfg_i *pinfo)
{
#define	TYPE_BIT		0xc0
  
#define	NO_NUM			0
#define	BINARY_LTOH		1
#define	BINARY_HTOL		2
#define	DECIMAL_3		3
#define	DECIMAL_4		4
#define	DECIMAL_5		5
#define	DECIMAL_V		6
  
#define	TOTAL_BYTE		0x80
#define	ISO_NUMBER		0x40
#define	DIVIDEBY_2		0x10
#define	DIVIDE_ALL		0x30
#define	MULT_CONST		0x08
  enum {
    BIT_IMAGE_MODE,
    NORML_MODE,
    SEND_BIT_IMAGE,
    SKIP_SPACES,
    LINE_FEED,
    FORM_FEED,
    AFTER_BIT_IMAGE,
    BIT_ROW_HEADER,
  };
  uchar *cfg_buf,*ptr;
  int ch, type, f_cont, f_type, pos, i, j, k, lens;
  int f_r_format;
  long offset;
  int old2new[] = {
    CFG_BIT_IMAGE_MODE,
    CFG_NORMAL_MODE,
    CFG_SEND_BIT_IMAGE,
    CFG_SKIP_SPACES,
    CFG_LINE_FEED,
    CFG_FORM_FEED,
    CFG_AFTER_BIT_IMAGE,
    CFG_BIT_ROW_HEADER,
  };
  
  ch =dviprt_setcfgbuffer_(pinfo,300,TEMP_CODEBUF_SIZE);
  if (ch < 0) return CFG_ERROR_MEMORY;
  dviprt_initcfg_(pcfg,pinfo);
  cfg_buf = pinfo->readbuf;
  if (fread(cfg_buf,30,1,pinfo->file) < 1) {
    dviprt_printcfgerror(pinfo,"Read error.\n",-1);
  }
  if (cfg_buf[16] == 'P') {
    dviprt_printcfgerror(pinfo,"This is made by old version.\n",-1);
    return CFG_ERROR_OTHER;
  }
  else if (cfg_buf[16] == 'Q')
    f_r_format = 0;
  else if (cfg_buf[16] == 'R')
    f_r_format = 1;
  else
    f_r_format = -1;
  if (f_r_format == -1 || cfg_buf[18] != 0xff) {
    dviprt_printcfgerror(pinfo,"This is not the *.CFG file for dviprt.\n",-1);
    return CFG_ERROR_OTHER;
  }
  cfg_buf[16] = '\0';
  pcfg->version = 0;
  if (pinfo->temp_codebuf_f) {
    pcfg->strings[CFG_NAME] = malloc(strlen(cfg_buf)+1);
    if (pcfg->strings[CFG_NAME] == NULL) {
    no_memory:
      dviprt_printcfgerror(pinfo,"Memory exhausted.\n",-1);
      return CFG_ERROR_MEMORY;
    }
  }
  else {
    pcfg->strings[CFG_NAME] = pinfo->pcodebuf;
    pinfo->pcodebuf += strlen(cfg_buf);
    pinfo->pcodebuf++;
  }
  strcpy(pcfg->strings[CFG_NAME],cfg_buf);
  
  pcfg->integer[CFG_UPPER_POS] =
    (cfg_buf[17] & (CFG_LEFT_IS_LOW|CFG_NON_MOVING));
  pcfg->integer[CFG_ENCODE] =
    (cfg_buf[17] & 0x10) ? CFG_ENCODE_HEX : CFG_ENCODE_NULL;
  pcfg->integer[CFG_PINS] = ((uint) (cfg_buf[17]) & 0x0f);
  
  ptr = cfg_buf+23;
  pcfg->integer[CFG_MINIMAL_UNIT] = (uint)ptr[0] | ((uint)ptr[1]<<8);
  pcfg->integer[CFG_MAXIMAL_UNIT] = (uint)ptr[2] | ((uint)ptr[3]<<8);
  pcfg->integer[CFG_DPI] =
    f_r_format ? ((uint)ptr[4] | ((uint)ptr[5]<<8)) : 180;
  if (cfg_buf[20])
    pcfg->integer[CFG_CONSTANT] = cfg_buf[20];
  offset = cfg_buf[19];
  fseek(pinfo->file,offset,0);
  
  for (i = 0; i <= BIT_ROW_HEADER; i++) {
    uchar *pstart,*plength;
    uchar prev = 1;
    if (pinfo->temp_codebuf_f) {
      pinfo->pcodebuf = pinfo->codebuf;
    }
    pstart = pinfo->pcodebuf;
    do {
      lens = fgetc(pinfo->file);
      if (lens == EOF) break;
      fread(cfg_buf,lens+3,1,pinfo->file);
      ptr = cfg_buf;
      f_cont = *ptr++;
      pos = *ptr++;
      f_type = *ptr++;
      type = f_type & 0x7;
      
      for (j = 0; j < lens; j++) {
	ch = *ptr++;
	if (pos == j && type != NO_NUM) {
	  uchar *pfmt = pinfo->pcodebuf++;
	  plength = pinfo->pcodebuf++;
	  *pinfo->pcodebuf++ = CFG_VAL_DEFAULT;
	  *plength = 1;
	  j++;
	  ptr++;
	  switch (type) {
	  case (BINARY_LTOH):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_BIN_LTOH | 2;
	    break;
	  case (BINARY_HTOL):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_BIN_HTOL | 2;
	    break;
	  case (DECIMAL_3):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL | 3;
	    j++;
	    ptr++;
	    break;
	  case (DECIMAL_4):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL | 4;
	    j += 2;
	    ptr += 2;
	    break;
	  case (DECIMAL_5):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL | 5;
	    j += 3;
	    ptr += 3;
	    break;
	  case (DECIMAL_V):
	    *pfmt = CFG_FMT_BIT | CFG_FMT_DECIMAL;
	    j++;
	    ptr++;
	    break;
	  default:
	    sprintf(dviprt_message_buffer,"Unknown format %02X",type);
	    dviprt_printcfgerror(pinfo,dviprt_message_buffer,-1);
	    goto ex_func;
	  }
	  if (f_type & TOTAL_BYTE) {
	    *pinfo->pcodebuf++ = CFG_VAL_PINS_BYTE;
	    *pinfo->pcodebuf++ = CFG_OP_MUL;
	    (*plength) += 2;
	  }
	  if ((k = (f_type & DIVIDE_ALL)) != 0) {
	    *pinfo->pcodebuf = 0;
	    for (; k > 0; k -= DIVIDEBY_2) {
	      (*pinfo->pcodebuf)++;
	    }
	    pinfo->pcodebuf++;
	    *pinfo->pcodebuf++ = CFG_OP_SHR;
	    (*plength) += 2;
	  }
	  if (f_type & ISO_NUMBER) {
	    *pfmt |= CFG_FMT_ISO_BIT;
	  }
	  if (f_type & MULT_CONST) {
	    *pinfo->pcodebuf++ = CFG_VAL_CONSTANT;
	    *pinfo->pcodebuf++ = CFG_OP_MUL;
	    (*plength) += 2;
	  }
	  prev = 1;
	}
	else {
	  if (prev == 1 || *plength >= 127) {
	    plength = pinfo->pcodebuf++;
	    *plength = 0;
	  }
	  (*plength)++;
	  *pinfo->pcodebuf++ = ch;
	  prev = 0;
	}
      }
    } while (f_cont & 0x80);
    *pinfo->pcodebuf++ = 0;
    { int n = old2new[i];
      uint l = pinfo->pcodebuf-pstart;
      pcfg->prtcode_size[n] = l - 1;
      if (pinfo->temp_codebuf_f) { /* allocate buffer */
     	pcfg->prtcode[n] = (uchar *)malloc(l);
        if (pcfg->prtcode[n] == NULL)
          goto no_memory;
	memcpy(pcfg->prtcode[n],pstart,l);
      }
      else {
	pcfg->prtcode[n] = pstart;
      }
    }
  }
 ex_func:
  dviprt_resetcfgbuffer_(pinfo);
  return 0;
}
/***** End of rcfg.c *****/


/***** From rsrc.c *****/
/* $Id: dviprlib.c,v 1.3 2002/07/20 21:03:20 tillkamppeter Exp $ */


typedef struct {
  char *name;
  signed char type;
  uchar no;
  uchar spec_f;
  uchar req_f;
  char *info;
} dviprt_cfg_item_t;

typedef struct {
  long min;
  long max;
} dviprt_cfg_limit_t;

/*--- forward declarations ---*/
private int dviprt_set_select
  (P4(dviprt_cfg_item_t *,uchar **,dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_set_integer
  (P4(dviprt_cfg_item_t *, uchar *, dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_set_strings
  (P4(dviprt_cfg_item_t *,uchar *,dviprt_cfg_t *,dviprt_cfg_i *));
private int dviprt_set_rpexpr
  (P6(dviprt_cfg_item_t *,uchar *,int , dviprt_cfg_t *,dviprt_cfg_i *,int));
private int dviprt_set_code
  (P4(dviprt_cfg_item_t *,uchar *,dviprt_cfg_t *,dviprt_cfg_i *));

private long dviprt_oct2long(P3(uchar *,uchar *,uchar **));
private long dviprt_dec2long(P3(uchar *,uchar *,uchar **));
private long dviprt_hex2long(P3(uchar *,uchar *,uchar **));
     
private int dviprt_printtokenerror(P4(dviprt_cfg_i *,char *,int ,int));
     
/*--- macros ---*/
#define strlcmp(tmplt,str,len) \
  (!(strncmp(tmplt,str,(int)(len)) == 0 && (int)(len) == strlen(tmplt)))
#define set_version(pcfg,v) ((pcfg)->version = MAX(v,(pcfg)->version))
     
enum {
  ERROR_UNKNOWN_VALUE,ERROR_UNKNOWN_FORMAT,ERROR_UNKNOWN_ESCSEQ,
  ERROR_OUTOFRANGE,
  ERROR_INVALID_VALUE,
  ERROR_COMPLICATED_EXPR,
  ERROR_INCOMPLETE,
};

/*--- library functions ---*/
int 
dviprt_readsrc(char *fname,dviprt_cfg_t *pcfg,uchar *pcodebuf,int codebuf_s,
    uchar *pworkbuf,int workbuf_s)
{
  dviprt_cfg_i info;
  int code;
  FILE *ifp;
  dviprt_cfg_item_t *pitem;
  int enc = CFG_ENCODE_NULL;
  enum { T_INTEGER,T_STRINGS,T_CODE,T_SELECT,T_UPPERPOS};
  static dviprt_cfg_limit_t pins_limit = { 8, 128 };
  static dviprt_cfg_limit_t positive_limit = { 1, 0x7fff };
  static dviprt_cfg_limit_t nonnegative_limit = { 0, 0x7fff};
  static dviprt_cfg_item_t dviprt_items[] = {
    {NULL,T_STRINGS,CFG_NAME,0,1,NULL},
    {NULL,T_INTEGER,CFG_PINS,0,1,(char*)&pins_limit},
    {NULL,T_INTEGER,CFG_MINIMAL_UNIT,0,0,(char*)&positive_limit},
    {NULL,T_INTEGER,CFG_MAXIMAL_UNIT,0,0,(char*)&positive_limit},
    {NULL,T_INTEGER,CFG_DPI,0,0,(char*)&positive_limit},
    {NULL,T_INTEGER,CFG_CONSTANT,0,0,(char*)&nonnegative_limit},
    {NULL,T_INTEGER,CFG_Y_DPI,0,0,(char*)&positive_limit},
    {NULL,T_CODE,CFG_BIT_IMAGE_MODE,0,1,NULL},
    {NULL,T_CODE,CFG_SEND_BIT_IMAGE,0,1,NULL},
    {NULL,T_CODE,CFG_BIT_ROW_HEADER,0,0,NULL},
    {NULL,T_CODE,CFG_AFTER_BIT_IMAGE,0,0,NULL},
    {NULL,T_CODE,CFG_LINE_FEED,0,0,NULL},
    {NULL,T_CODE,CFG_FORM_FEED,0,0,NULL},
    {NULL,T_CODE,CFG_NORMAL_MODE,0,1,NULL},
    {NULL,T_CODE,CFG_SKIP_SPACES,0,1,NULL},
    {NULL,T_UPPERPOS,CFG_UPPER_POS,0,1,NULL},
    {NULL,T_SELECT,CFG_ENCODE,0,0,(char*)dviprt_encodename},
    {NULL,-1},
  };
  static dviprt_cfg_item_t encode_info = {
    "encode",T_STRINGS,CFG_ENCODE_INFO,0,0,NULL
    };
  int prtcode_output_bytes[CFG_PRTCODE_TYPE_COUNT];
  
  info.line_no = -1;
  info.fname = fname;
  if (fname) {
    info.file = fopen(fname,"r");
    if (info.file == NULL) {
      dviprt_printcfgerror(&info,"Cannot open.\n",-1);
      return CFG_ERROR_FILE_OPEN;
    }
  }
  else {
    ifp = stdin;
  }
  ifp = info.file;
  
  info.codebuf = pcodebuf;
  info.readbuf = pworkbuf;
  info.codebuf_size = codebuf_s;
  info.readbuf_size = workbuf_s;
  /* allocate buffer */
  if (dviprt_setcfgbuffer_(&info,TEMP_READBUF_SIZE,TEMP_CODEBUF_SIZE) < 0) {
    fclose(info.file);
    return CFG_ERROR_MEMORY;
  }
  
  /* initialize */
  dviprt_initcfg_(pcfg,&info);
  for (pitem = dviprt_items;pitem->type>=0;pitem++) {
    if (pitem->name == NULL) {
      switch (pitem->type) {
      case T_INTEGER:
      case T_SELECT:
      case T_UPPERPOS:
        pitem->name = dviprt_integername[pitem->no];
        break;
      case T_STRINGS:
        pitem->name = dviprt_stringsname[pitem->no];
        break;
      case T_CODE:
        pitem->name = dviprt_prtcodename[pitem->no];
        break;
      }
    }
    pitem->spec_f = 0;
  }
  encode_info.spec_f = 0;
  { int i;
    for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++)
      prtcode_output_bytes[i] = 0;
  }
  
  pcfg->version = 1;
  for ( ; ; ) {
    uchar *pbuf = info.readbuf;
    uchar *pchar;
    
    if (fgets(info.readbuf,info.readbuf_size,ifp) == NULL) break;
    info.line_no++;
    {
      int len = strlen(pbuf);
      if ((pbuf[0] < 'a' || pbuf[0] > 'z') && pbuf[0] != '_') {
        while (pbuf[len-1] != '\n') {
          if (fgets(info.readbuf,info.readbuf_size,ifp) == NULL)
            goto end_scan;
          len = strlen(pbuf);
        }
        continue;
      }
      if ( len > 0 && pbuf[len-1] == '\n')
        pbuf[len-1] = 0;
    }
    while (*pbuf && *pbuf != ':') pbuf++;
    if (*pbuf != ':') {
      dviprt_printcfgerror(&info,"Character ':' is expected.\n",-1);
      code = CFG_ERROR_SYNTAX;
      goto end_process;
    }
    pchar = pbuf-1;
    while (pchar >= info.readbuf && isspace(*pchar)) pchar--;
    *++pchar = 0;
    pbuf++;
    for (pitem = dviprt_items;pitem->name;pitem++) {
      if (strcmp(pitem->name,info.readbuf) == 0) break;
    }
    if (pitem->name == NULL) {
      dviprt_printcfgerror(&info,"Unknown item `",-1);
      dviprt_printmessage(info.readbuf,-1);
      dviprt_printmessage("'.\n",-1);
      code = CFG_ERROR_RANGE;
      goto end_process;
    }
  parse_more:
    while (*pbuf && isspace(*pbuf)) pbuf++;
    if (pitem->spec_f) {
      dviprt_printcfgerror(&info,NULL,0);
      sprintf(dviprt_message_buffer,
	      "Item `%s' is specified twice.\n",pitem->name);
      dviprt_printmessage(dviprt_message_buffer,-1);
      code = CFG_ERROR_SYNTAX;
      goto end_process;
    }
    switch (pitem->type) {
    case T_INTEGER:
      if ((code = dviprt_set_integer(pitem,pbuf,pcfg,&info)) < 0)
        goto end_process;
      if (pitem->no == CFG_PINS) {
        if (pcfg->integer[CFG_PINS] % 8) {
          dviprt_printcfgerror(&info,"Value must be a multiple of 8.\n",-1);
          code = CFG_ERROR_RANGE;
          goto end_process;
        }
        pcfg->integer[CFG_PINS] /= 8;
      }
      break;
    case T_STRINGS:
      if (info.temp_codebuf_f)
        info.pcodebuf = info.codebuf;
      if ((code = dviprt_set_strings(pitem,pbuf,pcfg,&info)) < 0)
    	goto end_process;
      if (info.temp_codebuf_f) {
        pcfg->strings[pitem->no] =
          (uchar*)malloc(strlen(pcfg->strings[pitem->no])+1);
        if (pcfg->strings[pitem->no] == NULL) {
          goto no_more_memory;
        }
        strcpy(pcfg->strings[pitem->no],info.codebuf);
      }
      break;
    case T_CODE:
      if (info.temp_codebuf_f)
        info.pcodebuf = info.codebuf;
      if ((code = dviprt_set_code(pitem,pbuf,pcfg,&info)) < 0)
        goto end_process;
      prtcode_output_bytes[pitem->no] = code;
      if (info.temp_codebuf_f) {
        pcfg->prtcode[pitem->no] =
          (uchar*)malloc(pcfg->prtcode_size[pitem->no]+1);
        if (pcfg->prtcode[pitem->no] == NULL) {
        no_more_memory:
          dviprt_printcfgerror(&info,"Memory exhausted.\n",-1);
          code = CFG_ERROR_MEMORY;
          goto end_process;
        }
        memcpy(pcfg->prtcode[pitem->no],info.codebuf,
	       pcfg->prtcode_size[pitem->no]+1);
      }
      break;
    case T_SELECT:
      if ((code = dviprt_set_select(pitem,&pbuf,pcfg,&info)) < 0)
        goto end_process;
      if (pitem->no == CFG_ENCODE) {
        pitem = &encode_info;
        goto parse_more;
      }
      break;
    case T_UPPERPOS:
      { uchar *ptmp;
        uchar upos=0;
        uchar opt = 0;
        if (*pbuf == 0) {
          dviprt_printcfgerror(&info,"No value.\n",-1);
          code = CFG_ERROR_SYNTAX;
          goto end_process;
        }
        while (*pbuf) {
          ptmp = pbuf;
          while (*ptmp && !isspace(*ptmp)) ptmp++;
          if (strlcmp("HIGH_BIT",pbuf,ptmp-pbuf) == 0)
            upos = CFG_TOP_IS_HIGH;
          else if (strlcmp("LOW_BIT",pbuf,ptmp-pbuf) == 0)
            upos = CFG_TOP_IS_LOW;
          else if (strlcmp("LEFT_IS_HIGH",pbuf,ptmp-pbuf) == 0)
            upos = CFG_LEFT_IS_HIGH;
          else if (strlcmp("LEFT_IS_LOW",pbuf,ptmp-pbuf) == 0)
            upos = CFG_LEFT_IS_LOW;
          else if (strlcmp("NON_MOVING",pbuf,ptmp-pbuf) == 0)
            opt = CFG_NON_MOVING;
          else if (strlcmp("HEX_MODE",pbuf,ptmp-pbuf) == 0)
            enc = CFG_ENCODE_HEX;
          else {
            dviprt_printtokenerror(&info,pbuf,(int)(ptmp-pbuf),ERROR_UNKNOWN_VALUE);
            code = CFG_ERROR_RANGE;
            goto end_process;
          }
          pbuf = ptmp;
          while (*pbuf && isspace(*pbuf)) pbuf++;
        }
        pcfg->integer[CFG_UPPER_POS] = upos | opt;
      }
      break;
    }
    pitem->spec_f = 1;
  }
 end_scan:
  
  info.line_no = -1;
  code = 0;
  for (pitem = dviprt_items;pitem->name;pitem++) {
    if (!pitem->spec_f && pitem->req_f) {
      sprintf(dviprt_message_buffer,"%s not found.\n",pitem->name);
      dviprt_printcfgerror(&info,dviprt_message_buffer,-1);
      code++;
    }
  }
  if (code) { code = CFG_ERROR_RANGE; goto end_process; }
  
  if (pcfg->prtcode[CFG_LINE_FEED] == NULL) {
    if (info.temp_codebuf_f) {
      pcfg->prtcode[CFG_LINE_FEED] = info.pcodebuf;
      info.pcodebuf += 4;
    }
    else pcfg->prtcode[CFG_LINE_FEED] = (byte*)malloc(4);
    memcpy(pcfg->prtcode[CFG_LINE_FEED],"\002\x0d\x0a\000",4);
    pcfg->prtcode_size[CFG_LINE_FEED] = 3;
  }
  if (pcfg->prtcode[CFG_FORM_FEED] == NULL) {
    if (info.temp_codebuf_f) {
      pcfg->prtcode[CFG_FORM_FEED] = info.pcodebuf;
      info.pcodebuf += 4;
    }
    else pcfg->prtcode[CFG_FORM_FEED] = (byte*)malloc(4);
    memcpy(pcfg->prtcode[CFG_FORM_FEED],"\002\x0d\x0c\000",4);
    pcfg->prtcode_size[CFG_FORM_FEED] = 3;
  }
  if (pcfg->integer[CFG_DPI] < 0 && pcfg->integer[CFG_Y_DPI] < 0) {
    pcfg->integer[CFG_DPI] = 180;
  }
  else if (pcfg->integer[CFG_DPI] < 0 || pcfg->integer[CFG_Y_DPI] < 0) {
    if (pcfg->integer[CFG_DPI] < 0)
      pcfg->integer[CFG_DPI] = pcfg->integer[CFG_Y_DPI];
    pcfg->integer[CFG_Y_DPI] = -1;
  }
  else if (pcfg->integer[CFG_DPI] == pcfg->integer[CFG_Y_DPI]) {
    pcfg->integer[CFG_Y_DPI] = -1;
  }
  else if (pcfg->integer[CFG_Y_DPI] >= 0) { /* has y_dpi. */
    set_version(pcfg,2);
  }
  if (pcfg->integer[CFG_ENCODE] < 0) {
    pcfg->integer[CFG_ENCODE] = enc;
  }
  if (pcfg->integer[CFG_MAXIMAL_UNIT] < 0) {
    pcfg->integer[CFG_MAXIMAL_UNIT] = 0x7fff;
  }
  if (pcfg->integer[CFG_MINIMAL_UNIT] < 0) {
    uint v;
    v = (MAX(prtcode_output_bytes[CFG_SEND_BIT_IMAGE],0) +
         MAX(prtcode_output_bytes[CFG_AFTER_BIT_IMAGE],0) +
         MAX(prtcode_output_bytes[CFG_SKIP_SPACES],0))
      / (pcfg->integer[CFG_PINS]*8) +
	MAX(prtcode_output_bytes[CFG_BIT_ROW_HEADER],0);
    if (v == 0) v = 1;
    pcfg->integer[CFG_MINIMAL_UNIT] = v;
  }
  
  for (pitem = dviprt_items;pitem->type>=0;pitem++) {
    if (pitem->spec_f == 0) {
      sprintf(dviprt_message_buffer,": %s:",pitem->name);
      switch (pitem->type) {
      case T_INTEGER:
        if (pcfg->integer[pitem->no] >= 0) {
          uint v = pcfg->integer[pitem->no];
          dviprt_printmessage(fname,-1);
          dviprt_printmessage(dviprt_message_buffer,-1);
          sprintf(dviprt_message_buffer," %d\n",v);
          dviprt_printmessage(dviprt_message_buffer,-1);
        }
        break;
      default: break; /* do nothing */
      }
    }
  }
  
 end_process:
  if (fname) fclose(ifp);
  dviprt_resetcfgbuffer_(&info);
  
  return code;
}

/*--- internal routines ---*/
private int 
dviprt_set_integer(dviprt_cfg_item_t *pitem,uchar *buf,dviprt_cfg_t *pcfg,
    dviprt_cfg_i *pinfo)
{
  uchar *pbuf = buf;
  long v = 0;
  long max = -1 ,min = -1;
  
  if (pitem->info != NULL) {
    dviprt_cfg_limit_t *plimit = (dviprt_cfg_limit_t *)pitem->info;
    min = plimit->min;
    max = plimit->max;
  }
  if (min < 0) min = 0;
  if (max < 0) max = 0xffff;
  if (*pbuf == 0) {
    dviprt_printcfgerror(pinfo,"No value.\n",-1);
    return CFG_ERROR_SYNTAX;
  }
  while (*pbuf) {
    if (!isdigit(*pbuf)) {
      if (isspace(*pbuf)) break;
      else goto invalid_val;
    }
    v = v*10 + *pbuf - '0';
    if (v > max) {
    out_of_range:
      dviprt_printtokenerror(pinfo,buf,strlen(buf),ERROR_OUTOFRANGE);
      dviprt_printcfgerror(pinfo,"",-1);
      sprintf(dviprt_message_buffer,
	      "(%u <= value <= %u).\n",(uint)min,(uint)max);
      dviprt_printmessage(dviprt_message_buffer,-1);
      return CFG_ERROR_RANGE;
    }
    pbuf++;
  }
  if (v < min) goto out_of_range;
  
  while (*pbuf) {
    if (!isspace(*pbuf)) {
    invalid_val:
      dviprt_printtokenerror(pinfo,buf,strlen(buf),ERROR_INVALID_VALUE);
      return CFG_ERROR_RANGE;
    }
    pbuf++;
  }
  pcfg->integer[pitem->no] = v;
  
  return 0;
}

private int 
dviprt_set_strings(dviprt_cfg_item_t *pitem,uchar *buf,dviprt_cfg_t *pcfg,
    dviprt_cfg_i *pinfo)
{
  uchar *pend;
  long len;
  pend = buf+strlen(buf)-1;
  while (pend >= buf && isspace(*pend)) pend--;
  pend++;
  len = pend - buf;
  if (len > 0x7fffL) {
    dviprt_printcfgerror(pinfo,"Too long strings.\n",-1);
    return CFG_ERROR_RANGE;
  }
  
  pcfg->strings[pitem->no] = pinfo->pcodebuf;
  strncpy(pinfo->pcodebuf,buf,(int)len);
  pinfo->pcodebuf[len] = 0;
  pinfo->pcodebuf += len;
  pinfo->pcodebuf++;
  return 0;
}

private int
dviprt_set_select(dviprt_cfg_item_t *pitem,uchar **buf,dviprt_cfg_t *pcfg,
    dviprt_cfg_i *pinfo)
{
  int i;
  uchar *ptmp = *buf;
  uchar *pstart = *buf;
  uchar **opt;
  if (*pstart == 0) {
    dviprt_printcfgerror(pinfo,"No value.\n",-1);
    return CFG_ERROR_SYNTAX;
  }
  while (*ptmp && !isspace(*ptmp)) ptmp++;
  
  for (i=0,opt=(uchar**)pitem->info;*opt;i++,opt++) {
    if (strlcmp(*opt,pstart,ptmp-pstart) == 0) {
      pcfg->integer[pitem->no] = i;
      *buf = ptmp;
      return 0;
    }
  }
  dviprt_printtokenerror(pinfo,pstart,(int)(ptmp-pstart),ERROR_UNKNOWN_VALUE);
  return CFG_ERROR_RANGE;
}

#define CFG_TOKEN_ERROR     -1
#define CFG_TOKEN_LIMIT_BIT 0x100
#define CFG_TOKEN_FMT       0x200

private int 
dviprt_get_codetype_token(dviprt_cfg_i *pinfo,uchar *pstart,uchar *pend,uchar *stopescseqchars,
    uchar *limitchars)
{
  while (pstart < pend && isspace(*pstart)) pstart++;
  if (pstart >= pend) {
    pinfo->token = pinfo->endtoken = pstart;
    return CFG_TOKEN_LIMIT_BIT;
  }
  else if (strchr(limitchars,*pstart)) {
    pinfo->token = pstart;
    pinfo->endtoken = pstart+1;
    return CFG_TOKEN_LIMIT_BIT | *pstart;
  }
  else if (*pstart == '\\') {
    int c;
    long v;
    uchar *pexpr,*pnext;
    
    pexpr = pinfo->token = pstart++;
    while (pstart < pend && !isspace(*pstart) &&
           *pstart != '\\' && !strchr(stopescseqchars,*pstart)) {
      pstart++;
    }
    pinfo->endtoken = pstart;
    if (pinfo->token + 1 == pinfo->endtoken) { /* '\\' only */
      return '\\';
    }
    pexpr++;
    if (pinfo->endtoken - pexpr == 1) {
      if (isdigit(*pexpr)) goto parse_decimal_numb;
      switch (*pexpr) {
      case 't': c = '\t'; break; /* tab */
      case 'v': c = '\v'; break; /* tab */
      case 'n': c = '\n'; break; /* line feed */
      case 'f': c = '\f'; break; /* form feed */
      case 'r': c = '\r'; break; /* carrige return */
      case 'e': c = 0x1b; break; /* escape code */
      case 's': c = 0x20; break; /* space */
      default:
        dviprt_printtokenerror(pinfo,pinfo->token,2,ERROR_UNKNOWN_ESCSEQ);
        return CFG_TOKEN_ERROR;
      }
      return c;
    }
    else if (strlcmp("SP",pexpr,pinfo->endtoken - pexpr) == 0)
      return 0x20;
    else if (strlcmp("ESC",pexpr,pinfo->endtoken - pexpr) == 0)
      return 0x1b;
    switch (*pexpr) {
    case 'x':
    case 'X':
      v = dviprt_hex2long(pexpr+1,pinfo->endtoken,&pnext);
    check_numb_range:
      if (pstart != pnext) {
        dviprt_printtokenerror(pinfo,pinfo->token,
			       (int)(pinfo->endtoken - pinfo->token), ERROR_INVALID_VALUE);
        return CFG_TOKEN_ERROR;
      }
      if (v >= 256) {
        dviprt_printtokenerror(pinfo,pinfo->token,
			       (int)(pinfo->endtoken - pinfo->token), ERROR_OUTOFRANGE);
        return CFG_TOKEN_ERROR;
      }
      pinfo->endtoken = pnext;
      return v;
    case '0':
      v = dviprt_oct2long(pexpr,pinfo->endtoken,&pnext);
      goto check_numb_range;
    case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    parse_decimal_numb:
      v = dviprt_dec2long(pexpr,pinfo->endtoken,&pnext);
      goto check_numb_range;
    default:
      return CFG_TOKEN_FMT;
    }
  }
  else {
    pinfo->token = pstart;
    pinfo->endtoken = pstart+1;
    return *pstart;
  }
}

private long 
dviprt_dec2long(uchar *start,uchar *end,uchar **next)
{
  long v = 0;
  while (start < end) {
    int c = *start;
    if (isdigit(c)) v = v*10 + c - '0';
    else break;
    start++;
  }
  *next = start;
  return v;
}

private long 
dviprt_oct2long(uchar *start,uchar *end,uchar **next)
{
  long v = 0;
  while (start < end) {
    int c = *start;
    if (c >= '0' && c <= '7') v = v*8 + c - '0';
    else break;
    start++;
  }
  *next = start;
  return v;
}

private long 
dviprt_hex2long(uchar *start,uchar *end,uchar **next)
{
  long v = 0;
  while (start < end) {
    int c = *start;
    if (isdigit(c)) v = v*16 + c - '0';
    else if (c >= 'A' && c <= 'F') v = v*16 + c - 'A' + 10;
    else if (c >= 'a' && c <= 'f') v = v*16 + c - 'a' + 10;
    else break;
    start++;
  }
  *next = start;
  return v;
}

private int 
dviprt_set_rpexpr(dviprt_cfg_item_t *pitem,uchar *pbuf,int len,dviprt_cfg_t *pcfg,
    dviprt_cfg_i *pinfo,int sp)
{
  uchar *pend = pbuf + len;
  uchar *plastop = NULL;
  int code;
  
  /* get left expr */
  while (pbuf < pend) {
    int par_count = 0;
    uchar *pcur = pbuf;
    while (pcur < pend) {
      if (*pcur == '(') par_count++;
      else if (*pcur == ')') par_count--;
      else if (!isdigit(*pcur) && !isalpha(*pcur) && par_count == 0) {
        /* operator */
        plastop = pcur;
      }
      pcur++;
    }
    if (par_count != 0) {
      dviprt_printtokenerror(pinfo,pbuf,(int)(pend-pbuf),ERROR_INCOMPLETE);
      return CFG_ERROR_SYNTAX;
    }
    if (plastop == NULL) {
      if (*pbuf != '(') break;
      pbuf++;
      pend--;
    }
    else break;
  }
  
  if (plastop == NULL) { /* no operator */
    ulong v;
    uchar *pdummy;
    if (*pbuf == '0') {
      uchar a,b,c;
      v = dviprt_oct2long(pbuf,pend,&pdummy);
    check_intval:
      if (pdummy != pend) goto unknown_value;
      if (v > 0xffff) {
	dviprt_printtokenerror(pinfo,pbuf,(int)(pend-pbuf),ERROR_OUTOFRANGE);
	return CFG_ERROR_RANGE;
      }
      a = v & 0x7f;
      b = (v>>7) & 0x7f;
      c = (v>>14) & 0x03;
      if (c) {
        *pinfo->pcodebuf++ = c;
        *pinfo->pcodebuf++ = 14;
        *pinfo->pcodebuf++ = CFG_OP_SHL;
      }
      if (b) {
        *pinfo->pcodebuf++ = b;
        *pinfo->pcodebuf++ = 7;
        *pinfo->pcodebuf++ = CFG_OP_SHL;
        if (c) *pinfo->pcodebuf++ = CFG_OP_OR;
      }
      if (a) {
        *pinfo->pcodebuf++ = a;
        if (b || c) *pinfo->pcodebuf++ = CFG_OP_OR;
      }
      code = 0;
    }
    else if (isdigit(*pbuf)) {
      v = dviprt_dec2long(pbuf,pend,&pdummy);
      goto check_intval;
    }
    else if (pend - pbuf > 1 && (*pbuf == 'x' || *pbuf == 'X')) {
      v = dviprt_hex2long(pbuf+1,pend,&pdummy);
      goto check_intval;
    }
    else if (pend - pbuf > 1) {
    unknown_value:
      dviprt_printtokenerror(pinfo,pbuf,(int)(pend-pbuf),ERROR_UNKNOWN_VALUE);
      return CFG_ERROR_RANGE;
    }
    else {
      switch (*pbuf) {
      case 'd': v = CFG_VAL_DEFAULT;
        if (pitem->no != CFG_SEND_BIT_IMAGE &&
            pitem->no != CFG_BIT_ROW_HEADER &&
            pitem->no != CFG_AFTER_BIT_IMAGE &&
            pitem->no != CFG_SKIP_SPACES)
          goto unavailable_value;
        break;
      case 'c': v = CFG_VAL_CONSTANT; break;
      case 'w': v = CFG_VAL_WIDTH; break;
      case 'h': v = CFG_VAL_HEIGHT; break;
      case 'r': v = CFG_VAL_X_DPI; break;
      case 'R': v = CFG_VAL_Y_DPI; break;
      case 'p': v = CFG_VAL_PAGE; break;
      case 'x': v = CFG_VAL_X_POS; break;
      case 'y': v = CFG_VAL_Y_POS; break;
      case 'v': v = CFG_VAL_PINS_BYTE; break;
      case 's':
        v = CFG_VAL_DATASIZE;
        if (pitem->no != CFG_SEND_BIT_IMAGE &&
            pitem->no != CFG_BIT_ROW_HEADER &&
            pitem->no != CFG_AFTER_BIT_IMAGE) {
        unavailable_value:
          dviprt_printcfgerror(pinfo,"",-1);
          sprintf(dviprt_message_buffer,"Variable `%c' in ",(int)*pbuf);
          dviprt_printmessage(dviprt_message_buffer,-1);
          dviprt_printmessage(pbuf,(int)(pend-pbuf));
          sprintf(dviprt_message_buffer," cannot be used in %s.\n",pitem->name);
          dviprt_printmessage(dviprt_message_buffer,-1);
          return CFG_ERROR_RANGE;
        }
        break;
      default:
        goto unknown_value;
      }
      *pinfo->pcodebuf++ = v;
      code = 0;
    }
  }
  else { /* has operator */
    uchar op;
    
    code = dviprt_set_rpexpr(pitem,pbuf,(int)(plastop-pbuf),pcfg,pinfo,sp+1);
    if (code < 0) return code;
    code = dviprt_set_rpexpr(pitem,plastop+1,(int)(pend-plastop-1),pcfg,pinfo,sp+2);
    if (code < 0) return code;
    
    switch (*plastop) {
    case '+': op = CFG_OP_ADD; break;
    case '-': op = CFG_OP_SUB; break;
    case '*': op = CFG_OP_MUL; break;
    case '/': op = CFG_OP_DIV; break;
    case '%': op = CFG_OP_MOD; break;
    case '<': op = CFG_OP_SHL; break;
    case '>': op = CFG_OP_SHR; break;
    case '&': op = CFG_OP_AND; break;
    case '|': op = CFG_OP_OR ; break;
    case '^': op = CFG_OP_XOR; break;
    default:
      dviprt_printcfgerror(pinfo,NULL,0);
      sprintf(dviprt_message_buffer,"Unknown operator %c in ",(int)*pbuf);
      dviprt_printmessage(dviprt_message_buffer,-1);
      dviprt_printmessage(pbuf,(int)(pend-pbuf));
      dviprt_printmessage(".\n",-1);
      return CFG_ERROR_SYNTAX;
    }
    *pinfo->pcodebuf++ = op;
  }
  
  return code;
}

private int 
dviprt_set_code(dviprt_cfg_item_t *pitem,uchar *buf,dviprt_cfg_t *pcfg,
    dviprt_cfg_i *pinfo)
{
  long prev_line;
  int prev_type = 1;
  uchar *pcount;
  uchar *pcode_begin;
  uchar *rbuf;
  int obytes = 0;
  
  prev_line = ftell(pinfo->file);
  pcode_begin = pinfo->pcodebuf;
  rbuf = pinfo->readbuf;
  
  for ( ; ; ) {
    while (*buf) {
      int c;
      c = dviprt_get_codetype_token(pinfo,buf,buf+strlen(buf),",","");
      if (c == CFG_TOKEN_LIMIT_BIT) break; /* no elements remain */
      else if (c == CFG_TOKEN_ERROR) return CFG_ERROR_SYNTAX;
      if ( c < 256) {        /* character code (raw data) */
        if (prev_type) {
        new_unit:
          pcount = pinfo->pcodebuf++;
          (*pcount) = 0;
          prev_type = 0;
        }
        if (*pcount == 127) goto new_unit;
        (*pcount)++;
        *pinfo->pcodebuf++ = c;
        buf = pinfo->endtoken;
        obytes++;
      }
      else if (c == CFG_TOKEN_FMT) { /* format */
        uchar *pexpr = pinfo->token;
        int div=0,iso=0,mul=0,tl=0;
        int cols=0;
	int fmt;
        uchar *plength;
        uchar *pstart;
        
        buf = pinfo->token+1;
        
        /* formats */
        switch (*buf) {
        case 'b': fmt = CFG_FMT_BIN_LTOH; break;
        case 'B': fmt = CFG_FMT_BIN_HTOL; break;
        case 'H': fmt = CFG_FMT_HEX_UPPER; break;
        case 'h': fmt = CFG_FMT_HEX_LOWER; break;
        case 'd': fmt = CFG_FMT_DECIMAL; break;
        case 'o': fmt = CFG_FMT_OCTAL; break;
        case 's':
          buf++;
          if (*buf != 't') goto unknown_format;
          fmt = CFG_FMT_STRINGS;
          break;
        default:
        unknown_format:
          dviprt_printtokenerror(pinfo,pexpr,(int)(pinfo->endtoken-pexpr),
				 ERROR_UNKNOWN_FORMAT);
          return CFG_ERROR_SYNTAX;
        }
        buf++;
	
        /* columns */
        if (fmt == CFG_FMT_STRINGS) ;
        else {
          if (buf >= pinfo->endtoken) {
            dviprt_printtokenerror(pinfo,pexpr,(int)(pinfo->token-pexpr),ERROR_INCOMPLETE);
            return CFG_ERROR_SYNTAX;
          }
          
          if (!(*buf >= '1' && *buf <= '7') && *buf != '?') {
          invalid_cols:
            dviprt_printtokenerror(pinfo,pexpr,(int)(pinfo->endtoken-pexpr),
				   ERROR_UNKNOWN_FORMAT);
            return CFG_ERROR_SYNTAX;
          }
          cols = (*buf == '?') ? 0 : *buf - '0';
          if (cols == 0 &&
              (fmt == CFG_FMT_BIN_LTOH || fmt == CFG_FMT_BIN_HTOL))
            goto invalid_cols;
	  
          buf++;
          obytes += (cols == 0) ? 5 : cols;
        }
        
        /* additional format */
        while (buf < pinfo->endtoken) {
          switch (*buf) {
          case 'D': div++; break;
          case 'I': iso++; break;
          case 'M': mul++; break;
          case 'T': tl++; break;
          default:
            dviprt_printtokenerror(pinfo,pexpr,(int)(buf-pexpr),ERROR_UNKNOWN_FORMAT);
            return CFG_ERROR_SYNTAX;
          }
          if (div > 3 || iso > 1 || mul > 1 || tl > 1) {
            dviprt_printtokenerror(pinfo,pexpr,(int)(buf-pexpr),ERROR_UNKNOWN_FORMAT);
            return CFG_ERROR_SYNTAX;
          }
          buf++;
        }
        *pinfo->pcodebuf++ =
          CFG_FMT_BIT | fmt | (iso ? CFG_FMT_ISO_BIT : 0) | cols;
        plength = pinfo->pcodebuf;
        pinfo->pcodebuf++;
        pstart = pinfo->pcodebuf;
        
        if (*buf == ',' && *(buf+1) != '\"') {
	  int code;
          buf++;
          pinfo->token = buf;
          while (*pinfo->token && *pinfo->token != ',' &&
                 *pinfo->token != '\\' && !isspace(*pinfo->token))
            pinfo->token++;
	  if (pinfo->token == buf) {
            dviprt_printcfgerror(pinfo,"No expression is specified in ",-1);
            dviprt_printmessage(pexpr,(int)(buf-pexpr));
            dviprt_printmessage(".\n",-1);
            return CFG_ERROR_SYNTAX;
          }
          if ((code = dviprt_set_rpexpr(pitem,buf,(int)(pinfo->token-buf),pcfg,pinfo,0)) < 0)
  	    return code;
          buf = pinfo->token;
        }
        else {
          *pinfo->pcodebuf++ = CFG_VAL_DEFAULT;
        }
        if (mul) {
          *pinfo->pcodebuf++ = CFG_VAL_CONSTANT;
          *pinfo->pcodebuf++ = CFG_OP_MUL;
        }
        if (tl) {
          *pinfo->pcodebuf++ = CFG_VAL_PINS_BYTE;
          *pinfo->pcodebuf++ = CFG_OP_MUL;
        }
        if (div) {
          *pinfo->pcodebuf++ = div;
          *pinfo->pcodebuf++ = CFG_OP_SHR;
        }
	{
	  int length = pinfo->pcodebuf-pstart;
	  if (length > 255) {
	    dviprt_printtokenerror(pinfo,pexpr,(int)(buf-pexpr),ERROR_COMPLICATED_EXPR);
	    return CFG_ERROR_RANGE;
	  }
	  *plength++ = length & 0xff;
	}
        if (fmt == CFG_FMT_STRINGS) {
          uchar *pslen = pinfo->pcodebuf++;
          int len;
          if (strlen(buf) < 2 || *buf != ',' || *(buf+1) != '\"') {
	    dviprt_printcfgerror(pinfo,"No strings specified in ",-1);
	    dviprt_printmessage(pexpr,(int)(buf-pexpr));
	    dviprt_printmessage(".\n",-1);
            return CFG_ERROR_SYNTAX;
          }
          buf += 2;
          for (len=0; ;len++) {
            c = dviprt_get_codetype_token(pinfo,buf,buf+strlen(buf),"\"","\"");
            if (c == CFG_TOKEN_ERROR) return CFG_ERROR_SYNTAX;
            else if (c == CFG_TOKEN_FMT) {
              dviprt_printcfgerror(pinfo,"The format ",-1);
              dviprt_printmessage(pinfo->token,
				  (int)(pinfo->endtoken-pinfo->token));
              dviprt_printmessage(" cannot to be specified here.\n",-1);
              return CFG_ERROR_SYNTAX;
            }
            else if (c & CFG_TOKEN_LIMIT_BIT) {
              if ((c & 0xff) != '\"') {
                dviprt_printcfgerror(pinfo,
				     "Strings must be enclosed with "
				     "double quotations (\").\n",-1);
                return CFG_ERROR_SYNTAX;
              }
              buf = pinfo->endtoken;
              break;
            }
            *pinfo->pcodebuf++ = c;
            buf = pinfo->endtoken;
          }
          if (len > 255) {
            dviprt_printcfgerror(pinfo,"Too long strings.\n",-1);
            return CFG_ERROR_RANGE;
          }
	  *pslen = len;
	}
        prev_type = 1;
      }
      else {
	dviprt_printcfgerror(pinfo,"Parse error. Unexpected token ",-1);
	dviprt_printmessage(pinfo->token,(int)(pinfo->endtoken-pinfo->token));
	dviprt_printmessage(".\n",-1);
	return CFG_ERROR_SYNTAX;
      }
    }
  next_line:
    if (fgets(rbuf,pinfo->readbuf_size,pinfo->file) == NULL) break;
    if (!isspace(rbuf[0]) && rbuf[0] != ';') {
      fseek(pinfo->file,prev_line,0);
      break;
    }
    prev_line = ftell(pinfo->file);
    pinfo->line_no++;
    buf = rbuf;
    while (*buf && isspace(*buf)) buf++;
    if (*buf == ';')
      goto next_line; /* comment */
    {
      int len = strlen(rbuf);
      if (len > 0 && rbuf[len-1] == '\n')
        rbuf[len-1] = 0;
    }
  }
  pcfg->prtcode[pitem->no] = pcode_begin;
  pcfg->prtcode_size[pitem->no] = (pinfo->pcodebuf - pcode_begin) & 0xffff;
  *pinfo->pcodebuf++ = 0;
  return obytes;
}

private char *
dviprt_src_errorno2message(int type)
{
  switch (type) {
  case ERROR_OUTOFRANGE:
    return "Out of range.\n";
  case ERROR_UNKNOWN_VALUE:
    return "Unknown value.\n";
  case ERROR_UNKNOWN_ESCSEQ:
    return "Unknown escape sequence.\n";
  case ERROR_COMPLICATED_EXPR:
    return "Too complicated expression.\n";
  case ERROR_INCOMPLETE:
    return "Incomplete specification.\n";
  case ERROR_UNKNOWN_FORMAT:
    return "Unknown format.\n";
  case ERROR_INVALID_VALUE:
    return "Invalid value.\n";
  default:
    return NULL;
  }
}

private int 
dviprt_printtokenerror(dviprt_cfg_i *pinfo,char *token,int len,int type)
{
  char *msg;
  
  dviprt_printcfgerror(pinfo,token,len);
  dviprt_printmessage("\n",-1);
  
  if ((msg = dviprt_src_errorno2message(type)) != NULL)
    dviprt_printcfgerror(pinfo,msg,-1);
  return 0;
}

#undef strlcmp
#undef set_version
/***** End of rsrc.c *****/


/***** From util.c *****/
/* $Id: dviprlib.c,v 1.3 2002/07/20 21:03:20 tillkamppeter Exp $ */


char *dviprt_integername[] = { CFG_INTEGER_NAME, NULL };
char *dviprt_stringsname[] = { CFG_STRINGS_NAME, NULL };
char *dviprt_prtcodename[] = { CFG_PRTCODE_NAME, NULL };
char *dviprt_encodename[] = { CFG_ENCODE_NAME, NULL };

#if 0
private FILE *dviprt_messagestream = stderr;
#else  /* patch for glibc 2.1.x by Shin Fukui <shita@april.co.jp> */
private FILE *dviprt_messagestream;
#endif

/*--- library functions ---*/
int
dviprt_setmessagestream(FILE *fp)
{
  dviprt_messagestream = fp;
  return 0;
}

/*--- internal routines ---*/
liblocal int 
dviprt_initcfg_(dviprt_cfg_t *pcfg,dviprt_cfg_i *pinfo)
{
  int i;
  
  for (i=0;i<CFG_INTEGER_TYPE_COUNT;i++)
    pcfg->integer[i] = -1;
  for (i=0;i<CFG_STRINGS_TYPE_COUNT;i++)
    pcfg->strings[i] = NULL;
  for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++) {
    pcfg->prtcode[i] = NULL;
    pcfg->prtcode_size[i] = 0;
  }
  pinfo->pcodebuf = pinfo->codebuf;
  pinfo->line_no = 0;
  return 0;
}

liblocal int 
dviprt_setcfgbuffer_(dviprt_cfg_i *pinfo,int rsize,int csize)
{
  pinfo->temp_readbuf_f = pinfo->temp_codebuf_f = 0;
  
  if (pinfo->readbuf == NULL) {
    pinfo->readbuf_size = rsize;
    if (rsize>0) {
      pinfo->temp_readbuf_f = 1;
      pinfo->readbuf = (uchar *)malloc(rsize);
      if (pinfo->readbuf == NULL) {
      no_mem:
        dviprt_printmessage(pinfo->fname,-1);
        dviprt_printmessage("Memory exhausted.\n",-1);
        return CFG_ERROR_MEMORY;
      }
    }
  }
  if (pinfo->codebuf == NULL) {
    pinfo->codebuf_size = csize;
    if (csize>0) {
      pinfo->temp_codebuf_f = 1;
      pinfo->codebuf = (uchar *)malloc(csize);
      if (pinfo->codebuf == NULL) goto no_mem;
    }
  }
  return 0;
}

liblocal int 
dviprt_resetcfgbuffer_(dviprt_cfg_i *pinfo)
{
  if (pinfo->temp_readbuf_f) free(pinfo->readbuf);
  if (pinfo->temp_codebuf_f) free(pinfo->codebuf);
  pinfo->temp_codebuf_f = pinfo->temp_readbuf_f = 0;
  return 0;
}

char dviprt_message_buffer[128];

liblocal int
dviprt_printmessage(char *str,int len)
{
  if (dviprt_messagestream && str) {
    if (len >= 0) fwrite(str,len,1,dviprt_messagestream);
    else fputs(str,dviprt_messagestream);
    fflush(dviprt_messagestream);
  }
  return 0;
}

private int
dviprt_printcfgerrorheader(dviprt_cfg_i *pinfo)
{
  if (pinfo) {
    char *fn = pinfo->fname;
    if (fn == NULL) fn = "-";
    dviprt_printmessage(fn,-1);
    dviprt_printmessage(": ",-1);
    if (pinfo->line_no>0) {
      sprintf(dviprt_message_buffer,"%d: ",pinfo->line_no);
      dviprt_printmessage(dviprt_message_buffer,-1);
    }
  }
  return 0;
}

liblocal int
dviprt_printerror(char *msg,int len)
{
  dviprt_printmessage("*ERROR* ",-1);
  dviprt_printmessage(msg,len);
  return 0;
}

liblocal int 
dviprt_printcfgerror(dviprt_cfg_i *pinfo,char *msg,int len)
{
  dviprt_printcfgerrorheader(pinfo);
  dviprt_printerror(msg,len);
  return 0;
}

liblocal int
dviprt_printwarning(char *msg,int len)
{
  dviprt_printmessage("*WARNING* ",-1);
  dviprt_printmessage(msg,len);
  return 0;
}

liblocal int 
dviprt_printcfgwarning(dviprt_cfg_i *pinfo,char *msg,int len)
{
  dviprt_printcfgerrorheader(pinfo);
  dviprt_printwarning(msg,len);
  return 0;
}
/***** End of util.c *****/


/***** From print.c *****/
/* $Id: dviprlib.c,v 1.3 2002/07/20 21:03:20 tillkamppeter Exp $ */


/*--- forward declarations ---*/
private int dviprt_getmaximalwidth(P1(dviprt_print *));
private int dviprt_flush_buffer(P2(dviprt_print *,uchar far *));
private int dviprt_output_transpose(P3(dviprt_print *,uchar far *,uint ));
private int dviprt_output_nontranspose(P3(dviprt_print *,uchar far *,uint ));
private int dviprt_output_nontranspose_reverse(P3(dviprt_print *,uchar far *,uint ));
private int dviprt_reverse_bits(P2(uchar far *,uint));
private int dviprt_transpose8x8(P4(uchar far *,uint, uchar far *,uint));
private int dviprt_output_expr(P4(dviprt_print *,int,uint,uint));
private int dviprt_default_outputproc(P3(uchar far *,long ,void *));
private long dviprt_getbuffersize(P1(dviprt_print *));
     
/*--- library functions ---*/
long
dviprt_initlibrary(dviprt_print *pprint,dviprt_cfg_t *pprt,uint width,uint height)
{
  dviprt_encoder *pencode;
  uint pins = pprt->integer[CFG_PINS]*8;
  
  pprint->printer = pprt;
  height += (pins-1);
  height /= pins;
  height *= pins;
  pprint->bitmap_width = width; /* width by bytes */
  pprint->bitmap_height = height;
  pprint->buffer_width = MIN(width,pprt->integer[CFG_MAXIMAL_UNIT]);
  pprint->page_count = 0;
  pprint->output_bytes = 0;
  pprint->tempbuffer_f = 0;
  pencode = dviprt_getencoder_((int)pprt->integer[CFG_ENCODE]);
  if (pencode == NULL) return CFG_ERROR_NOT_SUPPORTED;
  pprint->encode_getbuffersize_proc = pencode->getworksize;
  pprint->encode_encode_proc = pencode->encode;
  
  pprint->output_bytes = 0;
  pprint->pstream = NULL;
  pprint->output_proc = NULL;
  
  if (pprt->integer[CFG_UPPER_POS] & CFG_NON_TRANSPOSE_BIT) {
    pprint->output_maximal_unit =
      (pprt->integer[CFG_UPPER_POS] & CFG_REVERSE_BIT) ?
	dviprt_output_nontranspose_reverse : dviprt_output_nontranspose;
  }
  else
    pprint->output_maximal_unit = dviprt_output_transpose;
  return dviprt_getbuffersize(pprint);
}

int
  dviprt_setstream
#ifdef __PROTOTYPES__
  (dviprt_print *pprint,int (*func)(P3(uchar far *,long ,void*)),void *pstream)
#else
(pprint,func,pstream)
dviprt_print *pprint;
int (*func)();
void *pstream;
#endif
{
  if (pprint->page_count) {
    int code = dviprt_output_expr(pprint,CFG_FORM_FEED,0,0);
    if (code < 0) return code;
    pprint->page_count = 0;
  }
  pprint->output_bytes = 0;
  pprint->pstream = pstream;
  pprint->output_proc = (func == NULL) ? dviprt_default_outputproc : func;
  return 0;
}

int
dviprt_setbuffer(dviprt_print *pprint,uchar far *buf)
{
  if (pprint->tempbuffer_f) {
    BufferFree(pprint->encode_buffer);
  }
  pprint->tempbuffer_f = 0;
  if (buf == NULL) {
    long s = dviprt_getbuffersize(pprint);
    if (s) {
      buf = (uchar far *)BufferAlloc(s);
      if (buf == NULL) return CFG_ERROR_MEMORY;
      pprint->tempbuffer_f = 1;
    }
  }
  pprint->encode_buffer = buf;
  pprint->source_buffer =
    buf + pprint->encode_getbuffersize_proc(pprint,dviprt_getmaximalwidth(pprint));
  return 0;
}

int
dviprt_beginpage(dviprt_print *pprint)
{
  int code;
  pprint->device_x = pprint->device_y = 0;
  pprint->bitmap_x = pprint->bitmap_y = 0;
  if (pprint->page_count == 0) { /* bit_image_mode */
    code = dviprt_output_expr(pprint,CFG_BIT_IMAGE_MODE,0,0);
  }
  else { /* form_feed */
    code = dviprt_output_expr(pprint,CFG_FORM_FEED,0,0);
  }
  pprint->page_count++;
  if (code < 0) return code;
  return 0;
}

int
dviprt_outputscanlines(dviprt_print *pprint,uchar far *fb)
{
  dviprt_cfg_t *pprt;
  int code;
  uint bw;
  
  pprt = pprint->printer;
  bw = pprint->bitmap_width;
  
  if (pprt->prtcode_size[CFG_SKIP_SPACES] <= 0) {
    pprint->bitmap_x = bw;
    pprint->last_x = 0;
  }
  else {
    uint uw,rw;
    uint mu;
    uint bx,lx;
    uint pins = dviprt_getscanlines(pprint);
    mu = pprt->integer[CFG_MINIMAL_UNIT];
    bx = lx = 0;
    
    for (rw= bw; rw > 0 ;rw -= uw) {
      uint x,y;
      uchar far *in;
      
      uw = MIN(mu,rw);
      in = fb + bx;
      for (x = uw; x>0 ; x--) {
        uchar far *test;
        test = in;
        for (y = pins ; y > 0 ;y--) {
          if (*test) goto next_unit;
          test += bw;
        }
        in++;
      }
      
      if (bx > lx) {
        pprint->bitmap_x = bx;
        pprint->last_x = lx;
        code = dviprt_flush_buffer(pprint,fb); /* output buffered unit */
        if (code < 0) return code;
        lx = pprint->last_x + uw;
      }
      else lx += uw;
      
    next_unit:
      bx += uw;
    }
    pprint->bitmap_x = bx;
    pprint->last_x = lx;
  }
  code = (pprint->last_x < pprint->bitmap_x) ? dviprt_flush_buffer(pprint,fb) : 0;
  pprint->bitmap_y++;
  return code;
}

int
dviprt_endbitmap(dviprt_print *pprint)
{
  if (pprint->page_count) {
    int code = dviprt_output_expr(pprint,CFG_NORMAL_MODE,0,0);
    if (code < 0) return code;
  }
  return 0;
}

int
dviprt_unsetbuffer(dviprt_print *pprint)
{
  if (pprint->tempbuffer_f) {
    BufferFree(pprint->encode_buffer);
    pprint->tempbuffer_f = 0;
  }
  return 0;
}

int
dviprt_output(dviprt_print *pprint,uchar far *buf,long s)
{
  int c = pprint->output_proc(buf,s,pprint->pstream);
  pprint->output_bytes += s;
  return c;
}

/*--- internal routines ---*/
private int
dviprt_getmaximalwidth(dviprt_print *pprint)
{
  return MIN(pprint->printer->integer[CFG_MAXIMAL_UNIT],pprint->bitmap_width);
}

private long
dviprt_getbuffersize(dviprt_print *pprint)
{
  long w = dviprt_getmaximalwidth(pprint);
  long e = pprint->encode_getbuffersize_proc(pprint,w);
  switch (pprint->printer->integer[CFG_UPPER_POS]
	  & (CFG_NON_TRANSPOSE_BIT | CFG_REVERSE_BIT)) {
  case CFG_LEFT_IS_HIGH:
    return e;
  default:
    return w * dviprt_getscanlines(pprint) + e;
  }
}

private int
dviprt_flush_buffer(dviprt_print *pprint,uchar far *fb)
{
  dviprt_cfg_t *pprt;
  int code;
  
  pprt = pprint->printer;
  while (pprint->device_y < pprint->bitmap_y) { /* skip vertical spaces */
    pprint->device_y++;
    code = dviprt_output_expr(pprint,CFG_LINE_FEED,0,0);
    pprint->device_x = 0;
  }
  while (pprint->last_x < pprint->bitmap_x) {
    int w;
    while (pprint->device_x < pprint->last_x) { /* skip horizontal spaces */
      w = MIN(pprt->integer[CFG_MAXIMAL_UNIT],
	      pprint->last_x - pprint->device_x);
      code = dviprt_output_expr(pprint,CFG_SKIP_SPACES,w,0);
      pprint->device_x += w;
    }
    w = MIN(pprt->integer[CFG_MAXIMAL_UNIT],pprint->bitmap_x-pprint->last_x);
    code = pprint->output_maximal_unit(pprint,fb+pprint->last_x,w);
    if (code < 0) return code;
    pprint->last_x += w;
    if (!(pprt->integer[CFG_UPPER_POS] & CFG_NON_MOVING))
      pprint->device_x += w;
  }
  return 0;
}

private int
dviprt_output_nontranspose(dviprt_print *pprint,uchar far *fb,uint width)
{
  int code;
  uint dsize;
  uint y;
  uint pins;
  
  pins = dviprt_getscanlines(pprint);
  
  dsize = 0;
  pprint->psource = fb;
  for (y = pins ; y>0 ; y--) {
    int dsize_line;
    dsize_line = pprint->encode_encode_proc(pprint,(long)width,0);
    if (dsize_line < 0) return dsize_line;
    dsize += dsize_line;
    pprint->psource += pprint->bitmap_width;
  }
  
  code = dviprt_output_expr(pprint,CFG_SEND_BIT_IMAGE,width,dsize);
  if (code < 0) return code;
  
  pprint->psource = fb;
  for (y = pins ; y>0 ; y--) {
    int dsize_line;
    dsize_line = pprint->encode_encode_proc(pprint,(long)width,1);
    code = dviprt_output_expr(pprint,CFG_BIT_ROW_HEADER,width,dsize_line);
    if (code < 0) return code;
    code = dviprt_output(pprint,pprint->poutput,dsize_line);
    if (code < 0) return code;
    pprint->psource += pprint->bitmap_width;
  }
  
  code = dviprt_output_expr(pprint,CFG_AFTER_BIT_IMAGE,width,dsize);
  if (code < 0) return code;
  
  return 0;
}


private int
dviprt_output_nontranspose_reverse(dviprt_print *pprint,uchar far *fb,uint width)
{
  uchar far *psrc;
  uchar far *pbuf;
  int code;
  uint src_size;
  uint dsize;
  uint y;
  uint pins;
  
  pins = dviprt_getscanlines(pprint);
  src_size = width * pins;
  
  psrc = pprint->source_buffer;
  for (y = pins ; y > 0; y--) {
    uint i;
    pbuf = fb;
    for (i=width;i>0;i--) *psrc++ = *pbuf++;
    fb += pprint->bitmap_width;
  }
  
  /* here, reverse bits */
  psrc = pprint->source_buffer;
  dviprt_reverse_bits(psrc,src_size);
  
  
  dsize = 0;
  pprint->psource = pprint->source_buffer;
  for (y = pins ; y>0 ; y--) {
    int dsize_line;
    dsize_line = pprint->encode_encode_proc(pprint,(long)width,0);
    if (dsize_line < 0) return dsize_line;
    dsize += dsize_line;
    pprint->psource += width;
  }
  
  code = dviprt_output_expr(pprint,CFG_SEND_BIT_IMAGE,width,dsize);
  if (code < 0) return code;
  
  pprint->psource = pprint->source_buffer;
  for (y = pins ; y>0 ; y--) {
    int dsize_line;
    dsize_line = pprint->encode_encode_proc(pprint,(long)width,1);
    code = dviprt_output_expr(pprint,CFG_BIT_ROW_HEADER,width,dsize_line);
    if (code < 0) return code;
    code = dviprt_output(pprint,pprint->poutput,dsize_line);
    if (code < 0) return code;
    pprint->psource += width;
  }
  
  code = dviprt_output_expr(pprint,CFG_AFTER_BIT_IMAGE,width,dsize);
  if (code < 0) return code;
  
  return 0;
}

private int
dviprt_output_transpose(dviprt_print *pprint,uchar far *fb,uint width)
{
  uchar far *psrc;
  uchar far *pbuf;
  int code;
  uint src_size;
  uint dsize;
  uint pins,pins8;
  int y;
  
  pins8 = pprint->printer->integer[CFG_PINS];
  pins = pins8 * 8;
  src_size = width * pins;
  psrc = pprint->source_buffer;
  {
    uchar far *pdst;
    uint sskip;
    sskip = pprint->bitmap_width * 8;
    for (y = pins8-1; y >= 0 ; y--) {
      uint i;
      pbuf = fb;
      pdst = psrc;
      for (i=width;i>0;i--) {
        dviprt_transpose8x8(pbuf,pprint->bitmap_width,pdst,pins8);
        pbuf ++;
        pdst += pins;
      }
      fb += sskip;
      psrc++;
    }
  }
  
  psrc = pprint->source_buffer;
  
  /* here, reverse bits */
  if (pprint->printer->integer[CFG_UPPER_POS] & CFG_REVERSE_BIT)
    dviprt_reverse_bits(psrc,src_size);
  
  dsize = 0;
  pprint->psource = pprint->source_buffer;
  for (y = pins ; y>0 ; y--) {
    int dsize_line;
    dsize_line = pprint->encode_encode_proc(pprint,(long)width,0);
    if (dsize_line < 0) return dsize_line;
    dsize += dsize_line;
    pprint->psource += width;
  }
  
  code = dviprt_output_expr(pprint,CFG_SEND_BIT_IMAGE,width,dsize);
  if (code < 0) return code;
  
  pprint->psource = pprint->source_buffer;
  for (y = pins ; y>0 ; y--) {
    uint dsize_line;
    dsize_line = pprint->encode_encode_proc(pprint,(long)width,1);
    code = dviprt_output(pprint,pprint->poutput,dsize_line);
    if (code < 0) return code;
    pprint->psource += width;
  }
  
  code = dviprt_output_expr(pprint,CFG_AFTER_BIT_IMAGE,width,dsize);
  if (code < 0) return code;
  
  return 0;
}

private int
dviprt_transpose8x8(uchar far *inp,uint line_size,uchar far *outp,uint dist)
{
  register uint ae, bf, cg, dh;
  {
    uchar far *ptr4 = inp + (line_size << 2);
    ae = ((uint)*inp << 8) + *ptr4;
    inp += line_size, ptr4 += line_size;
    bf = ((uint)*inp << 8) + *ptr4;
    inp += line_size, ptr4 += line_size;
    cg = ((uint)*inp << 8) + *ptr4;
    inp += line_size, ptr4 += line_size;
    dh = ((uint)*inp << 8) + *ptr4;
  }
  /* Check for all 8 bytes being the same. */
  /* This is especially worth doing for the case where all are zero. */
  if ( ae == bf && ae == cg && ae == dh && (ae >> 8) == (ae & 0xff) ) {
    if ( ae == 0 ) goto store;
    *outp = -((ae >> 7) & 1);
    outp += dist;
    *outp = -((ae >> 6) & 1);
    outp += dist;
    *outp = -((ae >> 5) & 1);
    outp += dist;
    *outp = -((ae >> 4) & 1);
    outp += dist;
    *outp = -((ae >> 3) & 1);
    outp += dist;
    *outp = -((ae >> 2) & 1);
    outp += dist;
    *outp = -((ae >> 1) & 1);
    outp += dist;
    *outp = -(ae & 1);
  }
  else {
    register uint temp;
    
    /* Transpose a block of bits between registers. */
#define transpose(r,s,mask,shift)\
    r ^= (temp = ((s >> shift) ^ r) & mask);\
      s ^= temp << shift
	
	/* Transpose blocks of 4 x 4 */
#define transpose4(r) transpose(r,r,0x00f0,4)
	transpose4(ae);
    transpose4(bf);
    transpose4(cg);
    transpose4(dh);
    
    /* Transpose blocks of 2 x 2 */
    transpose(ae, cg, 0x3333, 2);
    transpose(bf, dh, 0x3333, 2);
    
    /* Transpose blocks of 1 x 1 */
    transpose(ae, bf, 0x5555, 1);
    transpose(cg, dh, 0x5555, 1);
    
  store:	*outp = ae >> 8;
    outp += dist;
    *outp = bf >> 8;
    outp += dist;
    *outp = cg >> 8;
    outp += dist;
    *outp = dh >> 8;
    outp += dist;
    *outp = (uchar)ae;
    outp += dist;
    *outp = (uchar)bf;
    outp += dist;
    *outp = (uchar)cg;
    outp += dist;
    *outp = (uchar)dh;
  }
  return 0;
}

private int
dviprt_reverse_bits(uchar far *buf,uint s)
{
  static uchar rev[256] = {
    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 
    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 
    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 
    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 
    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 
    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 
    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 
    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 
    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 
    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 
    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 
    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 
    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 
    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 
    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 
    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 
    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 
    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 
    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 
    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 
    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 
    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 
    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 
    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 
    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 
    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 
    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 
    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 
    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 
    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 
    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 
  };
  while (s-- > 0) {
    *buf = rev[*buf];
    buf++;
  }
  return 0;
}


private int
dviprt_output_expr(dviprt_print *pprint,int numb,uint width,uint dsize)
{
  uchar *pcode;
  dviprt_cfg_t *pprt;
  uint v;
  uint len;
  
  pprt = pprint->printer;
  if (pprt->prtcode[numb] == NULL) return 0;
  pcode = pprt->prtcode[numb];
  len = pprt->prtcode_size[numb];
  
  while (*pcode && len>0) {
    if (*pcode & CFG_FMT_BIT) {
      uint stack[CFG_STACK_DEPTH];
      int stack_p = -1;
      uchar fmt = *pcode++;
      uint l = *pcode++;
      len -=2;
      while (l>0) {
        if ((*pcode & CFG_EXPR_TYPE_BIT) == CFG_OP) {
          uint v2 = stack[stack_p--];
          v = stack[stack_p--];
          switch (*pcode) {
          case CFG_OP_ADD: v += v2; break;
          case CFG_OP_SUB: v -= v2; break;
          case CFG_OP_MUL: v *= v2; break;
          case CFG_OP_DIV:
            if (v2 == 0) { /* divided by zero. */
            div_by_zero:
              return CFG_ERROR_DIV0;
            }
            v /= v2;
            break;
          case CFG_OP_MOD:
            if (v2 == 0) goto div_by_zero;
            v %= v2;
            break;
          case CFG_OP_SHL: v <<= v2; break;
          case CFG_OP_SHR: v >>= v2; break;
          case CFG_OP_AND: v &= v2; break;
          case CFG_OP_OR : v |= v2; break;
          case CFG_OP_XOR: v ^= v2; break;
          default:
            ;
          }
          stack[++stack_p] = v;
        }
        else if ((*pcode & CFG_EXPR_TYPE_BIT) == CFG_VAL) {
          {
            switch (*pcode) {
            case CFG_VAL_DEFAULT: v = width*8; break;
            case CFG_VAL_CONSTANT: v = pprt->integer[CFG_CONSTANT]; break;
            case CFG_VAL_WIDTH: v = pprint->bitmap_width*8; break;
            case CFG_VAL_HEIGHT: v = pprint->bitmap_height; break;
            case CFG_VAL_PAGE:
            case CFG_VAL_PAGECOUNT: v = pprint->page_count; break;
            case CFG_VAL_DATASIZE: v = dsize; break;
            case CFG_VAL_X_DPI: v = (int)pprt->integer[CFG_DPI]; break;
            case CFG_VAL_Y_DPI:
              v = pprt->integer[CFG_Y_DPI] > 0 ?
		pprt->integer[CFG_Y_DPI] : pprt->integer[CFG_DPI];
              break;
            case CFG_VAL_PINS_BYTE: v = pprt->integer[CFG_PINS]; break;
            case CFG_VAL_X_POS: v = pprint->device_x*8; break;
            case CFG_VAL_Y_POS:
              v = pprint->device_y * dviprt_getscanlines(pprint);
              break;
            }
          }
          stack[++stack_p] = v;
        }
        else {
          stack[++stack_p] = *pcode;
        }
        l--; pcode++; len--;
      }
      v = stack[stack_p];
      if ((fmt & CFG_FMT_FORMAT_BIT) == CFG_FMT_STRINGS) {
        uint l = *pcode++;
        len--;
        while (v-- > 0)
          dviprt_output(pprint,(uchar far *)pcode,l);
        pcode += l;
        len -= l;
      }
      else if ((fmt & CFG_FMT_FORMAT_BIT) == CFG_FMT_ASSIGNMENT) {
        pprint->uservar[fmt&0x0f] = v;
      }
      else { uchar valbuf[10];
	     int cols = fmt & CFG_FMT_COLUMN_BIT;
	     int i;
	     
	     switch (fmt & CFG_FMT_FORMAT_BIT) {
	     case CFG_FMT_BIN_LTOH:
	       for (i=0;i<cols;i++) {
		 valbuf[i] = v&0xff;
		 v >>= 8;
	       }
	       break;
	     case CFG_FMT_BIN_HTOL:
	       for (i=cols-1;i>=0;i--) {
		 valbuf[i] = v&0xff;
		 v >>= 8;
	       }
	       break;
	     default:
	       { char *f;
		 char fmtbuf[10];
		 switch(fmt & CFG_FMT_FORMAT_BIT) {
		 case CFG_FMT_HEX_UPPER: f = "X"; break;
		 case CFG_FMT_HEX_LOWER: f = "x"; break;
		 case CFG_FMT_DECIMAL: f = "u"; break;
		 case CFG_FMT_OCTAL: f = "o"; break;
		 }
		 if (cols == 0)
		   strcpy(fmtbuf,"%");
		 else
		   sprintf(fmtbuf,"%%0%d",cols);
		 strcat(fmtbuf,f);
		 sprintf(valbuf,fmtbuf,stack[stack_p]);
		 cols = strlen(valbuf);
		 if (fmt & CFG_FMT_ISO_BIT)
		   valbuf[cols-1] |= 0x10;
	       }
	       break;
	     }
	     dviprt_output(pprint,(uchar far *)valbuf, cols);
	   }
    }
    else {
      uint l = *pcode++;
      len--;
      dviprt_output(pprint,(uchar far *)pcode,l);
      pcode += l;
      len -= l;
    }
  }
  return 0;
}

private int
dviprt_default_outputproc(uchar far *buf,long s,void *fp)
{
#ifdef __MSDOS_REAL__
  while (s-- > 0) {
    if (fputc(*buf++,fp) == EOF)
      return CFG_ERROR_OUTPUT;
  }
  return 0;
#else
  return fwrite(buf,s,1,fp) == 1 ? 0 : CFG_ERROR_OUTPUT;
#endif
}
/***** End of print.c *****/


/***** From encode.c *****/
/* $Id: dviprlib.c,v 1.3 2002/07/20 21:03:20 tillkamppeter Exp $ */


#define DVIPRT_SUPPORT_FAX 1
#define DVIPRT_SUPPORT_PCL 1

/*--- forward declarations ---*/
private long dviprt_null_getworksize(P2(dviprt_print *,long ));
private long dviprt_null_encode(P3(dviprt_print *,long ,int ));
private long dviprt_hex_getworksize(P2(dviprt_print *,long ));
private long dviprt_hex_encode(P3(dviprt_print *,long ,int ));
#if DVIPRT_SUPPORT_FAX
private long dviprt_fax_getworksize(P2(dviprt_print *,long ));
private long dviprt_fax_encode(P3(dviprt_print *,long ,int ));
#endif
#if DVIPRT_SUPPORT_PCL
private long dviprt_pcl1_getworksize(P2(dviprt_print *,long ));
private long dviprt_pcl1_encode(P3(dviprt_print *,long ,int ));
private long dviprt_pcl2_getworksize(P2(dviprt_print *,long ));
private long dviprt_pcl2_encode(P3(dviprt_print *,long ,int ));
#endif
     
private dviprt_encoder dviprt_encoder_list[] = {
  { CFG_ENCODE_NULL, dviprt_null_getworksize,dviprt_null_encode},
  { CFG_ENCODE_HEX, dviprt_hex_getworksize,dviprt_hex_encode},
#if DVIPRT_SUPPORT_FAX
  { CFG_ENCODE_FAX, dviprt_fax_getworksize,dviprt_fax_encode},
#endif
#if DVIPRT_SUPPORT_PCL
  { CFG_ENCODE_PCL1, dviprt_pcl1_getworksize,dviprt_pcl1_encode},
  { CFG_ENCODE_PCL2, dviprt_pcl2_getworksize,dviprt_pcl2_encode},
#endif
  { -1 },
};

/*--- internal routines ---*/
/* The users MUST NOT USE these functions */
liblocal dviprt_encoder *
dviprt_getencoder_(int no)
{
  int i;
  for (i=0;dviprt_encoder_list[i].no >= 0;i++)
    if (no == dviprt_encoder_list[i].no)
      return dviprt_encoder_list+i;
  return NULL;
}

private long 
dviprt_null_getworksize(dviprt_print *pprint,long s)
{
  return 0;
}
private long 
dviprt_null_encode(dviprt_print *pprint,long s,int f)
{
  pprint->poutput = pprint->psource;
  return s;
}

private long 
dviprt_hex_getworksize(dviprt_print *pprint,long s)
{
  return s*2;
}
private long 
dviprt_hex_encode(dviprt_print *pprint,long s,int f)
{
  if (f) {
    uchar far *w;
    uchar far *buf;
    static uchar hex[] = "0123456789ABCDEF";
    int i=s;
    w = pprint->poutput = pprint->encode_buffer;
    buf = pprint->psource;
    while (i-->0) {
      *w++ = hex[(*buf>>4)&0x0f];
      *w++ = hex[*buf&0x0f];
      buf++;
    }
  }
  return s*2;
}

#if DVIPRT_SUPPORT_PCL
private long
dviprt_pcl1_getworksize(dviprt_print *pprint,long s)
{
  return s*2;
}
private long 
dviprt_pcl1_encode(dviprt_print *pprint,long s,int f)
{
  uchar far *src;
  uchar far *end;
  uchar far *out;
  long total = 0;
  
  src = pprint->psource;
  end = src + s;
  out = pprint->poutput = pprint->encode_buffer;
  
  while ( src < end  ) {
    uchar test = *src++;
    uchar far *run = src;
    while ( src < end && *src == test ) src++;
    if (f) {
      while ( src - run > 255 ) {
        *out++ = 255;
        *out++ = test;
        total += 2;
        run += 256;
      }
      *out++ = src - run;
      *out++ = test;
      total += 2;
    }
    else {
      total += (((src-run)/255 + ((src-run)%255) ? 1 : 0)) * 2;
    }
  }
  return total;
}

private long 
dviprt_pcl2_getworksize(dviprt_print *pprint,long s)
{
  return s + s/127 + 1;
}
private long 
dviprt_pcl2_encode(dviprt_print *pprint,long s,int f)
{
  uchar far *exam;
  uchar far *cptr;
  uchar far *end;
  uchar far *src;
  long total = 0;
  
  src = pprint->psource;
  exam = src;
  cptr = pprint->poutput = pprint->encode_buffer;
  end = exam + s;
  
  for ( ; ; ) {
    uchar test = *exam++;
    int len;
    while ((test != *exam) && (exam < end))
      test = *exam++;
    if (exam < end) exam--;
    len = exam - src;
    if (f) {
      while (len > 0){
        int i;
        int count = len;
        if (count>127) count=127;
        *cptr++=count-1;
        for (i = 0 ; i < count ; i++) *cptr++ = *src++;
        len -= count;
        total += (count+1);
      }
    }
    else {
      total += len + ((len/127)+(len%127 ? 1 : 0));
    }
    if (exam >= end) break;
    exam++;
    while ((test == *exam) && (exam < end))
      exam++;
    len = exam - src;
    if (f) {
      while (len > 0) {
        int count = len;
        if (count > 127) count = 127;
        *cptr++ = (257-count);
        *cptr++ = test;
        len -= count;
        total += 2;
      }
    }
    else {
      total += ((len/127 + (len%127) ? 1 : 0)) * 2;
    }
    if (exam >= end) break;
    src = exam;
  }
  return total;
}
#endif /* DVIPRT_SUPPORT_PCL */

#if DVIPRT_SUPPORT_FAX
private long 
dviprt_fax_getworksize(dviprt_print *pprint,long s)
{
  long size = s * 8 + 7;
  return MAX(size*2/9+4,size/8) * dviprt_getscanlines(pprint) + 1;
}

#define MAX_FAX_WIDTH	2623
typedef struct {
  int	data;
  int	length;
} FaxEncode_t;
typedef struct {
  uchar i_bitbuf;
  uchar far *i_buf;
  int i_count;
  
  uchar o_bitbuf;
  uchar far *o_buf;
  int o_count;
  int o_bufcount;
} FaxEncodeInfo;
private int dviprt_fax_set_white(P2(int,FaxEncodeInfo *));
private int dviprt_fax_set_black(P2(int,FaxEncodeInfo *));
private int dviprt_fax_set_bitcount(P2(FaxEncode_t *,FaxEncodeInfo *));
     
private long 
dviprt_fax_encode(dviprt_print *pprint,long s,int f)
{
  static FaxEncode_t eol_code = {0x800,12};
  int allruns = 0;
  int width = s * 8;
  int top_bit_count = 8;
  FaxEncodeInfo info;
  uchar far *src_end;
  uchar recover;
  
  src_end = pprint->psource + s;
  recover = *src_end;
  *src_end = 0xaa;
  
  /* initializing */
  info.i_buf = pprint->psource;
  info.i_bitbuf = *info.i_buf++;
  info.i_count = 8;
  info.o_buf = pprint->poutput = pprint->encode_buffer;
  info.o_bitbuf = 0;
  info.o_count = 8;
  info.o_bufcount = 0;
  
  dviprt_fax_set_bitcount(&eol_code,&info);
  
  for(;;){
    static uchar ROW[9] =
      {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
    static uchar MASK[9] =
      {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
    int white_run_length;
    int black_run_length;
    
    /* count run-length */
    /* remaining bits in the current byte are white? */
    if (!(info.i_bitbuf &= MASK[info.i_count])){
      do{
	top_bit_count += 8; /* next byte is also white	*/
      } while(!(info.i_bitbuf = *info.i_buf++));
      info.i_count = 8;
    }
    /* current byte contains white and black bits 	*/
    while(!(info.i_bitbuf & ROW[info.i_count]))
      info.i_count--;		/* skip white bits 	*/
    white_run_length = top_bit_count - (black_run_length = info.i_count);
    
    /* remaining bits in the current byte are black?	*/
    if (info.i_bitbuf == MASK[info.i_count]){
      do{
	black_run_length += 8;
	/* next byte is also black	*/
      } while((info.i_bitbuf = *info.i_buf++) == 0xff);
      info.i_count = 8;
    }
    else info.i_count--;	/* skip the top black bit	*/
    
    /* current byte contains white and black bits 	*/
    while(info.i_bitbuf & ROW[info.i_count])
      info.i_count--;		/* skip black bits	 		*/
    black_run_length -= (top_bit_count = info.i_count);
    
    /* output */
    if((allruns += white_run_length) < width)
      dviprt_fax_set_white(white_run_length,&info);
    else{
      dviprt_fax_set_white(white_run_length + width - allruns,&info);
      break;
    }
    if((allruns += black_run_length) < width)
      dviprt_fax_set_black(black_run_length,&info);
    else{
      dviprt_fax_set_black(black_run_length + width - allruns,&info);
      break;
    }
  }
  
  info.o_bufcount++;
  if (info.o_count < 8)
    *info.o_buf++ = info.o_bitbuf;
  else
    *info.o_buf++ = 0;
  *src_end = recover;
  
  return info.o_bufcount;
}

private int 
dviprt_fax_set_bitcount(FaxEncode_t *pt,FaxEncodeInfo *info)
{
  int	data, length;
  
  data = pt->data;
  length = pt->length;
  while( (length -= info->o_count) >= 0 ){
    *info->o_buf++ = ((data << (8 - info->o_count))|info->o_bitbuf);
    info->o_bitbuf = 0;
    info->o_bufcount++;
    data >>= info->o_count;
    info->o_count = 8;
  }
  info->o_bitbuf |= (data << (8 - info->o_count));
  info->o_count = -length;
  return 0;
}

private int 
dviprt_fax_set_white(int count,FaxEncodeInfo *info)
{
  static FaxEncode_t white_count_list[]={
    { 0x00AC,      8,	}, /*    0 */
    { 0x0038,      6,	}, /*    1 */
    { 0x000E,      4,	}, /*    2 */
    { 0x0001,      4,	}, /*    3 */
    { 0x000D,      4,	}, /*    4 */
    { 0x0003,      4,	}, /*    5 */
    { 0x0007,      4,	}, /*    6 */
    { 0x000F,      4,	}, /*    7 */
    { 0x0019,      5,	}, /*    8 */
    { 0x0005,      5,	}, /*    9 */
    { 0x001C,      5,	}, /*   10 */
    { 0x0002,      5,	}, /*   11 */
    { 0x0004,      6,	}, /*   12 */
    { 0x0030,      6,	}, /*   13 */
    { 0x000B,      6,	}, /*   14 */
    { 0x002B,      6,	}, /*   15 */
    { 0x0015,      6,	}, /*   16 */
    { 0x0035,      6,	}, /*   17 */
    { 0x0072,      7,	}, /*   18 */
    { 0x0018,      7,	}, /*   19 */
    { 0x0008,      7,	}, /*   20 */
    { 0x0074,      7,	}, /*   21 */
    { 0x0060,      7,	}, /*   22 */
    { 0x0010,      7,	}, /*   23 */
    { 0x000A,      7,	}, /*   24 */
    { 0x006A,      7,	}, /*   25 */
    { 0x0064,      7,	}, /*   26 */
    { 0x0012,      7,	}, /*   27 */
    { 0x000C,      7,	}, /*   28 */
    { 0x0040,      8,	}, /*   29 */
    { 0x00C0,      8,	}, /*   30 */
    { 0x0058,      8,	}, /*   31 */
    { 0x00D8,      8,	}, /*   32 */
    { 0x0048,      8,	}, /*   33 */
    { 0x00C8,      8,	}, /*   34 */
    { 0x0028,      8,	}, /*   35 */
    { 0x00A8,      8,	}, /*   36 */
    { 0x0068,      8,	}, /*   37 */
    { 0x00E8,      8,	}, /*   38 */
    { 0x0014,      8,	}, /*   39 */
    { 0x0094,      8,	}, /*   40 */
    { 0x0054,      8,	}, /*   41 */
    { 0x00D4,      8,	}, /*   42 */
    { 0x0034,      8,	}, /*   43 */
    { 0x00B4,      8,	}, /*   44 */
    { 0x0020,      8,	}, /*   45 */
    { 0x00A0,      8,	}, /*   46 */
    { 0x0050,      8,	}, /*   47 */
    { 0x00D0,      8,	}, /*   48 */
    { 0x004A,      8,	}, /*   49 */
    { 0x00CA,      8,	}, /*   50 */
    { 0x002A,      8,	}, /*   51 */
    { 0x00AA,      8,	}, /*   52 */
    { 0x0024,      8,	}, /*   53 */
    { 0x00A4,      8,	}, /*   54 */
    { 0x001A,      8,	}, /*   55 */
    { 0x009A,      8,	}, /*   56 */
    { 0x005A,      8,	}, /*   57 */
    { 0x00DA,      8,	}, /*   58 */
    { 0x0052,      8,	}, /*   59 */
    { 0x00D2,      8,	}, /*   60 */
    { 0x004C,      8,	}, /*   61 */
    { 0x00CC,      8,	}, /*   62 */
    { 0x002C,      8,	}, /*   63 */
    
    { 0x001B,      5,	}, /*   64 */
    { 0x0009,      5,	}, /*  128 */
    { 0x003A,      6,	}, /*  192 */
    { 0x0076,      7,	}, /*  256 */
    { 0x006C,      8,	}, /*  320 */
    { 0x00EC,      8,	}, /*  384 */
    { 0x0026,      8,	}, /*  448 */
    { 0x00A6,      8,	}, /*  512 */
    { 0x0016,      8,	}, /*  576 */
    { 0x00E6,      8,	}, /*  640 */
    { 0x0066,      9,	}, /*  704 */
    { 0x0166,      9,	}, /*  768 */
    { 0x0096,      9,	}, /*  832 */
    { 0x0196,      9,	}, /*  896 */
    { 0x0056,      9,	}, /*  960 */
    { 0x0156,      9,	}, /* 1024 */
    { 0x00D6,      9,	}, /* 1088 */
    { 0x01D6,      9,	}, /* 1152 */
    { 0x0036,      9,	}, /* 1216 */
    { 0x0136,      9,	}, /* 1280 */
    { 0x00B6,      9,	}, /* 1344 */
    { 0x01B6,      9,	}, /* 1408 */
    { 0x0032,      9,	}, /* 1472 */
    { 0x0132,      9,	}, /* 1536 */
    { 0x00B2,      9,	}, /* 1600 */
    { 0x0006,      6,	}, /* 1664 */
    { 0x01B2,      9,	}, /* 1728 */
    
    { 0x0080,     11,	}, /* 1792 */
    { 0x0180,     11,	}, /* 1856 */
    { 0x0580,     11,	}, /* 1920 */
    { 0x0480,     12,	}, /* 1984 */
    { 0x0C80,     12,	}, /* 2048 */
    { 0x0280,     12,	}, /* 2112 */
    { 0x0A80,     12,	}, /* 2176 */
    { 0x0680,     12,	}, /* 2240 */
    { 0x0E80,     12,	}, /* 2304 */
    { 0x0380,     12,	}, /* 2368 */
    { 0x0B80,     12,	}, /* 2432 */
    { 0x0780,     12,	}, /* 2496 */
    { 0x0F80,     12,	}, /* 2560 */
  };
  while (count >= 64){
    if(count <= MAX_FAX_WIDTH){
      dviprt_fax_set_bitcount((white_count_list + 63) + (count/64),info);
      break;
    }
    dviprt_fax_set_white(MAX_FAX_WIDTH,info);
    dviprt_fax_set_black(0,info);
    count -= MAX_FAX_WIDTH;
  }
  dviprt_fax_set_bitcount(white_count_list + (count & 63) ,info);
  return 0;
}

private int 
dviprt_fax_set_black(int count,FaxEncodeInfo *info)
{
  static FaxEncode_t black_count_list[]={
    { 0x03B0,     10,	}, /*    0 */
    { 0x0002,      3,	}, /*    1 */
    { 0x0003,      2,	}, /*    2 */
    { 0x0001,      2,	}, /*    3 */
    { 0x0006,      3,	}, /*    4 */
    { 0x000C,      4,	}, /*    5 */
    { 0x0004,      4,	}, /*    6 */
    { 0x0018,      5,	}, /*    7 */
    { 0x0028,      6,	}, /*    8 */
    { 0x0008,      6,	}, /*    9 */
    { 0x0010,      7,	}, /*   10 */
    { 0x0050,      7,	}, /*   11 */
    { 0x0070,      7,	}, /*   12 */
    { 0x0020,      8,	}, /*   13 */
    { 0x00E0,      8,	}, /*   14 */
    { 0x0030,      9,	}, /*   15 */
    { 0x03A0,     10,	}, /*   16 */
    { 0x0060,     10,	}, /*   17 */
    { 0x0040,     10,	}, /*   18 */
    { 0x0730,     11,	}, /*   19 */
    { 0x00B0,     11,	}, /*   20 */
    { 0x01B0,     11,	}, /*   21 */
    { 0x0760,     11,	}, /*   22 */
    { 0x00A0,     11,	}, /*   23 */
    { 0x0740,     11,	}, /*   24 */
    { 0x00C0,     11,	}, /*   25 */
    { 0x0530,     12,	}, /*   26 */
    { 0x0D30,     12,	}, /*   27 */
    { 0x0330,     12,	}, /*   28 */
    { 0x0B30,     12,	}, /*   29 */
    { 0x0160,     12,	}, /*   30 */
    { 0x0960,     12,	}, /*   31 */
    { 0x0560,     12,	}, /*   32 */
    { 0x0D60,     12,	}, /*   33 */
    { 0x04B0,     12,	}, /*   34 */
    { 0x0CB0,     12,	}, /*   35 */
    { 0x02B0,     12,	}, /*   36 */
    { 0x0AB0,     12,	}, /*   37 */
    { 0x06B0,     12,	}, /*   38 */
    { 0x0EB0,     12,	}, /*   39 */
    { 0x0360,     12,	}, /*   40 */
    { 0x0B60,     12,	}, /*   41 */
    { 0x05B0,     12,	}, /*   42 */
    { 0x0DB0,     12,	}, /*   43 */
    { 0x02A0,     12,	}, /*   44 */
    { 0x0AA0,     12,	}, /*   45 */
    { 0x06A0,     12,	}, /*   46 */
    { 0x0EA0,     12,	}, /*   47 */
    { 0x0260,     12,	}, /*   48 */
    { 0x0A60,     12,	}, /*   49 */
    { 0x04A0,     12,	}, /*   50 */
    { 0x0CA0,     12,	}, /*   51 */
    { 0x0240,     12,	}, /*   52 */
    { 0x0EC0,     12,	}, /*   53 */
    { 0x01C0,     12,	}, /*   54 */
    { 0x0E40,     12,	}, /*   55 */
    { 0x0140,     12,	}, /*   56 */
    { 0x01A0,     12,	}, /*   57 */
    { 0x09A0,     12,	}, /*   58 */
    { 0x0D40,     12,	}, /*   59 */
    { 0x0340,     12,	}, /*   60 */
    { 0x05A0,     12,	}, /*   61 */
    { 0x0660,     12,	}, /*   62 */
    { 0x0E60,     12,	}, /*   63 */
    
    { 0x03C0,     10,	}, /*   64 */
    { 0x0130,     12,	}, /*  128 */
    { 0x0930,     12,	}, /*  192 */
    { 0x0DA0,     12,	}, /*  256 */
    { 0x0CC0,     12,	}, /*  320 */
    { 0x02C0,     12,	}, /*  384 */
    { 0x0AC0,     12,	}, /*  448 */
    { 0x06C0,     13,	}, /*  512 */
    { 0x16C0,     13,	}, /*  576 */
    { 0x0A40,     13,	}, /*  640 */
    { 0x1A40,     13,	}, /*  704 */
    { 0x0640,     13,	}, /*  768 */
    { 0x1640,     13,	}, /*  832 */
    { 0x09C0,     13,	}, /*  896 */
    { 0x19C0,     13,	}, /*  960 */
    { 0x05C0,     13,	}, /* 1024 */
    { 0x15C0,     13,	}, /* 1088 */
    { 0x0DC0,     13,	}, /* 1152 */
    { 0x1DC0,     13,	}, /* 1216 */
    { 0x0940,     13,	}, /* 1280 */
    { 0x1940,     13,	}, /* 1344 */
    { 0x0540,     13,	}, /* 1408 */
    { 0x1540,     13,	}, /* 1472 */
    { 0x0B40,     13,	}, /* 1536 */
    { 0x1B40,     13,	}, /* 1600 */
    { 0x04C0,     13,	}, /* 1664 */
    { 0x14C0,     13, }, /* 1728 */
    
    { 0x0080,     11,	}, /* 1792 */
    { 0x0180,     11,	}, /* 1856 */
    { 0x0580,     11,	}, /* 1920 */
    { 0x0480,     12,	}, /* 1984 */
    { 0x0C80,     12,	}, /* 2048 */
    { 0x0280,     12,	}, /* 2112 */
    { 0x0A80,     12,	}, /* 2176 */
    { 0x0680,     12,	}, /* 2240 */
    { 0x0E80,     12,	}, /* 2304 */
    { 0x0380,     12,	}, /* 2368 */
    { 0x0B80,     12,	}, /* 2432 */
    { 0x0780,     12,	}, /* 2496 */
    { 0x0F80,     12,	}, /* 2560 */
  };
  
  while (count >= 64){
    if(count <= MAX_FAX_WIDTH){
      dviprt_fax_set_bitcount((black_count_list + 63) + (count/64),info);
      break;
    }
    dviprt_fax_set_black(MAX_FAX_WIDTH,info);
    dviprt_fax_set_white(0,info);
    count -= MAX_FAX_WIDTH;
  }
  dviprt_fax_set_bitcount(black_count_list + (count & 63),info);
  return 0;
}
#endif /* DVIPRT_SUPPORT_FAX */
/***** End of encode.c *****/
