/*
 * kban.c  --- 'banner'-like program for kanji chars only
 *
 *  Programmed by Hirotsugu KAKUGAWA, Hiroshima University
 *  E-Mail:  kakugawa@se.hiroshima-u.ac.jp
 *
 * Edition History
 *  28 Dec 1995
 *  29 Dec 1995  Reading stdin feature.
 *
 */

/* This file is part of VFlib
 *
 * Copyright (C) 1995  Hirotsugu KAKUGAWA.   All rights reserved.
 *
 * VFlib 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 GNU General Public License for full details.
 *
 * Everyone is granted permission to copy, modify and redistribute
 * VFlib, but only under the conditions described in the GNU
 * General Public License.  A copy of this license is supposed to have been
 * given to you along with VFlib 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. 
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "../src/config.h"
#include "../src/defs.h"
#include "../src/VF.h"
#include "str.h"

#define W_XDOTS     40
#define W_YDOTS     20

void usage(void);
int  BanAChar(int jiscode, int fd, int xdots, int ydots, 
	      int rast, unsigned char *buff);
int  BanStdin(int fd, int xdots, int ydots, 
	      int rast, unsigned char *buff);
void PutBitmap(unsigned char *buff, int xdots, int ydots, int xbytes);


char *BanChar = "*";
int   BanCLen = 1;
int   BanCSft = 1;
int   YokoMode = 0;

/* EUC to JIS */
#define KanjiConv(ch1, ch2) (((ch1)&0x7f)*0x100 + ((ch2)&0x7f))


int
main(argc, argv)
  int  argc;
  char **argv;
{
  int     ReadStdin;
  int     Fd, XDots,  YDots, XBytes, jiscode, tmp;
  char    *Ent, *Vfcap;
  unsigned char  *Buff;

  ReadStdin = 0;
  Vfcap  = NULL;
  Ent    = "min";
  XDots  = W_XDOTS;
  YDots  = W_YDOTS;
  jiscode = 0x3b52;

  argv++;
  argc--;
  while (argc > 0){
    if (argv[0][0] == '-'){
      switch (argv[0][1]){
      case 'f':
	if (--argc == 0)
	  usage();
	Ent = *(++argv);
	break;
      case 'x':
	if (--argc == 0)
	  usage();
	XDots = atoi(*(++argv)); 
	break;
      case 'y':
	if (--argc == 0)
	  usage();
	YDots = atoi(*(++argv)); 
	break;
      case 'v':
	if (--argc == 0)
	  usage();
	Vfcap = *(++argv);
	break;
      case 'c':
	if (--argc == 0)
	  usage();
	BanChar = *(++argv);
	BanCLen = strlen(BanChar);
	break;
      case 's':
	if (--argc == 0)
	  usage();
	BanCSft = atoi(*(++argv));
	break;
      case 'Y':
	YokoMode = 1;
	break;
      case 'z':
	ReadStdin = 1;
	break;
      case 'h':
      default:
	usage();
      }
    } else {
      jiscode = strtol(*argv, (char**)NULL, 16);
    }
    argc--;
    argv++;
  }

  if (VF_Init(Vfcap) < 0){
    printf("Initializing VFlib: FAIL\n");
    exit(1);
  }
  if ((Fd = VF_OpenFont(Ent)) < 0){
    fprintf(stderr, "open error; %s\n", Ent);
    exit(-1);
  }

  if (YokoMode == 1){
    tmp = XDots;
    XDots = YDots;
    YDots = tmp;
  }

  XBytes = (XDots+7)/8;
  if ((Buff = malloc(XBytes*YDots)) == NULL){
    fprintf(stderr, "malloc err\n");
    exit(0);
  } 
  if (ReadStdin == 0)
    (void) BanAChar(jiscode, Fd, XDots, YDots, XBytes, Buff);
  else 
    (void) BanStdin(Fd, XDots, YDots, XBytes, Buff);
  
  VF_CloseFont(Fd);
  VF_Deinit();
  return 0;
}

void usage(void)
{
  printf("kban  - display a kanji char \n");
  printf("Usage ktest [options] [jis-code]\n");
  printf("options: \n");
  printf(" -f FONT_ENTRY  : specify font entry name. %s\n",
	 "(`min' is default)");
  printf(" -x DOTS : set character width.\n");
  printf(" -y DOTS : set character height.\n");
  printf(" -v      : set vfontcap file. (must give full path)\n");
  printf(" -Y      : yoko gaki mode\n");
  printf(" -z      : read stdin for kanji chars in EUC code\n");
  printf("Example :\n");
  printf(" %% kban -x 75 -y 30 3026\n");
  printf(" %% kban -x 60 -y 30 -z < kban.dat\n");
  printf(" %% kban -x 60 -y 30 -Y -f goth -z < kban.dat\n");
  exit(0);
}

int
BanAChar(int jiscode, int fd, int xdots, int ydots, 
	 int rast, unsigned char *buff)
{
  bzero(buff, rast*ydots);
  VF_GetBitmap(jiscode, fd, xdots, ydots, rast, 0, buff);
  PutBitmap(buff, xdots, ydots, rast);
  return 0;
}

int
BanStdin(int fd, int xdots, int ydots, 
	 int rast, unsigned char *buff)
{
  int jiscode, ch1, ch2;

  for (;;){
    if ((ch1 = getchar()) == EOF)
      break;
    if (ch1 < 0x80)
      continue;
    if ((ch2 = getchar()) == EOF)
      break;
    jiscode = KanjiConv(ch1, ch2);
    bzero(buff, rast*ydots);
    VF_GetBitmap(jiscode, fd, xdots, ydots, rast, 0, buff);
    PutBitmap(buff, xdots, ydots, rast);
  }
  return 0;
}

void
PutBitmap(unsigned char *buff, int xdots, int ydots, int xbytes)
{
  int x, y, shift;
  unsigned char  *bp;
  static unsigned char bits[] = {
    0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

  if (YokoMode == 0){
    shift = BanCSft;
    for (y = 0; y < ydots; y++){
      bp = &buff[y*xbytes];
      for (x = 0; x < xdots; x++){
	if ((bits[x%8] & bp[x/8]) == 0)
	  putchar(' ');
	else
	  putchar(BanChar[(x+shift)%BanCLen]);
      }
      putchar('\n');
      shift += BanCSft;
    }
  } else {
    shift = BanCSft;
    for (x = 0; x < xdots; x++){
      for (y = ydots; y >= 0; y--){
	bp = &buff[y*xbytes];
	if ((bits[x%8] & bp[x/8]) == 0)
	  putchar(' ');
	else
	  putchar(BanChar[(x+shift)%BanCLen]);
      }
      putchar('\n');
      shift += BanCSft;
    }
  }
}
