/*
 * Display All JIS characters
 * Test Program for Vector Font Library VFlib 2
 *
 *  Programmed by Hirotsugu KAKUGAWA, Hiroshima University
 *  E-Mail:  kakugawa@se.hiroshima-u.ac.jp
 *
 * Edition History
 *  30 Jan 1994  
 *   8 Mar 1994  Added -F and -o options
 *  21 May 1994  Bug fixed. (by Yosuke Koshino tykoshin@tomcat.iijnet.or.jp)
 *
 */


/* This file is part of VFlib
 *
 * Copyright (C) 1994,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/VF.h"
#include "str.h"


#define CHAR_PER_LINE  16
#define LINE_PER_PAGE   6

#define W_XDOTS     50
#define W_YDOTS     50

int  XDots,  YDots, XBytes;

void InitWin(), ClearWin(), PutBitmap();
int   CCode2Jis(), UserCmd();


int
main(argc, argv)
  int  argc;
  char **argv;
{
  int     Fd, Code, OutlineTest, Pos, Page, UseFSlib;
  int     jiscode, i, cmd;
  char    *Ent, *Vfcap, *Buff;
  long    *vfdata;

  Vfcap  = NULL;
  Ent    = "min";
  XDots  = W_XDOTS;
  YDots  = W_YDOTS;
  OutlineTest = 0;
  UseFSlib = 0;

  argv++;
  argc--;
  while (argc > 0){
    if (argv[0][0] == '-'){
      switch (argv[0][1]){
      case 'f':
	if (--argc == 0)
	  usage();
	Ent = *(++argv);
	break;
      case 'F':
	UseFSlib = 1;
	break;
      case 'x':
	if (--argc == 0)
	  usage();
	XDots = atoi(*(++argv)); 
	break;
      case 'y':
	if (--argc == 0)
	  usage();
	YDots = atoi(*(++argv)); 
	break;
      case 'o':
	OutlineTest = 1;
	break;
      case 'v':
	if (--argc == 0)
	  usage();
	Vfcap = *(++argv);
	break;
      case 'h':
      default:
	usage();
      }
    }
    argc--;
    argv++;
  }

  if (VF_Init(Vfcap) < 0){
    printf("Initializing VFlib: FAIL\n");
    exit(1);
  }
  printf("Initializing VFlib: OK\n");

  if ((Fd = VF_OpenFont(Ent)) < 0){
    fprintf(stderr, "open error; %s\n", Ent);
    exit(-1);
  }
  printf("Opening font: OK\n");

  XBytes = (XDots+7)/8;
  if ((Buff = malloc(XBytes*YDots)) == NULL){
    fprintf(stderr, "malloc err\n");
    exit(0);
  } 

  InitWin(XDots*CHAR_PER_LINE, YDots*LINE_PER_PAGE);
  Page = 0x000;
  for (;;){
    ClearWin();
    for (Code = 0; Code < CHAR_PER_LINE*LINE_PER_PAGE; Code++){
      bzero(Buff, XBytes*YDots);
      jiscode = CCode2Jis(Page+Code);
      if (OutlineTest == 0){
	VF_GetBitmap(jiscode, Fd, XDots, YDots, XBytes, 0, Buff);
      } else {  /* OR */
	if ((vfdata = VF_GetOutline(jiscode, Fd)) == NULL){
	  ;  /* printf("Failed to get outline : %04x\n", jiscode); */
	} else {
#ifndef USE_SONY_FONT
	  VF_DrawOutline(vfdata, Fd, XDots, YDots, XBytes, 0, Buff);
#else
	  if (UseFSlib == 0){
	    VF_DrawOutline(vfdata, Fd, XDots, YDots, XBytes, 0, Buff);
	  } else {
	    FS_scan_conv(&vfdata[2], XDots, YDots, XBytes, 0, Buff, 0, 0, 0);
	  }
#endif
	  VF_FreeOutline(vfdata, Fd);
	}

      }
      PutBitmap(Buff, XDots, YDots, XBytes, 
		Code%CHAR_PER_LINE, Code/CHAR_PER_LINE);
    }

    cmd = UserCmd();
Loop:
    switch (cmd){
      case -1:
      if (Page > 0){
	Page = Page - CHAR_PER_LINE*LINE_PER_PAGE;
      } else {
	cmd = UserCmd();
	goto Loop;
      }
      break;
    case 0:
      goto Exit;
    case 1:
      Page = Page + CHAR_PER_LINE*LINE_PER_PAGE;
      break;
    case 2:
      free(Buff);
      XBytes    = (XDots+7)/8;
      if ((Buff = malloc(XBytes*YDots)) == NULL){
	fprintf(stderr, "malloc err\n");
	exit(0);
      }
      break;
    } 
  }

Exit:
  VF_CloseFont(Fd);
  printf("Closing font: OK\n");
  VF_Deinit();

  return 0;
}

usage()
{
  printf("ktest  - display all JIS characters.\n");
  printf("Usage ktest [options]\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(" -o       : use VF_Outline()/VF_DrawOutline() instead of VF_GetBitmap().\n");
  printf(" -v       : set vfontcap file. (must give full path)\n");	
  printf("Press LEFT button for previous page\n");
  printf("Press RIGHT button for next page\n");
  printf("Press MIDDLE button to exit\n");
  exit(0);
}


int
CCode2Jis(ccode)
  int ccode;
{
  int hi, lo;
  
  hi = ccode/94 + 0x21;
  lo = ccode%94 + 0x21;
  return hi*0x100+lo;
}
  


#ifdef USE_XWIN

/*------------------------*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>

Display               *Disp;
Window                Win;
GC                    Gc;
XGCValues             GcVal;
XSetWindowAttributes  Att;
unsigned int          WinX, WinY, WinBorder, WinDepth;
char                  *DisplayName; 
char                  *WindowName;


void
InitWin(x, y)
  int x, y;
{
  WindowName = "VFlib: Character Table";
  DisplayName = NULL;

  WinX = x; WinY = y;
  Disp = XOpenDisplay(DisplayName);
  Win = XCreateSimpleWindow(Disp, RootWindow(Disp, 0), 
			    0, 0, x, y, 2,
			    BlackPixel(Disp, 0), WhitePixel(Disp, 0));
  Gc     = XCreateGC(Disp, Win, 0, 0);
  XStoreName(Disp, Win, WindowName);
  Att.override_redirect = True;
  Att.backing_store     = Always;
  /*XChangeWindowAttributes(Disp, Win, CWOverrideRedirect, &Att);*/
  XChangeWindowAttributes(Disp, Win, CWBackingStore, &Att);
  XSelectInput(Disp, Win, ButtonPressMask|StructureNotifyMask);
  XMapWindow(Disp, Win);
  XFlush(Disp);
}

void
ClearWin()
{
  XFillRectangle(Disp, Win, Gc, 0, 0, WinX, WinY);
}

void
PutBitmap(s, xdots, ydots, yyy, x, y)
  unsigned char *s;
  int           xdots, ydots, yyy, x, y; 
{
  int     ix, iy, i;
  char    d, *xbitmap;
  Pixmap  pix;
  static unsigned char  
    tb1[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01},
    tb2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
  unsigned long fg, bg;
  unsigned int depth;

  depth = DefaultDepth(Disp, DefaultScreen(Disp));
  fg = BlackPixel(Disp, DefaultScreen(Disp));
  bg = WhitePixel(Disp, DefaultScreen(Disp));

  if ((xbitmap = malloc(ydots*((xdots+7)/8))) == NULL){
    fprintf(stderr, "Malloc err\n");
    return;
  }
  bzero(xbitmap, ydots*((xdots+7)/8));

  for (iy = 0; iy < ydots; iy++)
    for (ix = 0; ix < (xdots+7)/8; ix++){
      d = 0;
      for (i = 0; i < 8; i++)
	if ((tb1[i] & s[ix+iy*yyy]) != 0)
	  d |= tb2[i];
      xbitmap[ix+iy*((xdots+7)/8)] = d;
    }
  pix = XCreatePixmapFromBitmapData(Disp, Win, xbitmap, xdots, ydots, 
				    fg, bg, depth);
  XCopyArea(Disp, pix, Win, Gc, 0, 0, xdots, ydots, x*xdots, y*ydots);
  XFreePixmap(Disp, pix);
  free(xbitmap);
}

int
UserCmd()
{
  int     x, y;
  XEvent  xevent;

  for (;;){
    XNextEvent(Disp, &xevent);
    switch(xevent.type){
    case ButtonPress:
      switch (xevent.xbutton.button){
      case 1:
	return -1;
      case 2:
	return 0;
      case 3:
	return 1;
      }
    case ConfigureNotify:
      x = xevent.xconfigure.width;
      y = xevent.xconfigure.height;
      if ((WinX != x) || (y != WinY)){
	WinX = x;
	WinY = y;
	XDots = WinX / CHAR_PER_LINE;
	YDots = WinY / LINE_PER_PAGE;
	return 2;
      }
      break;
    default:
      break;
    }
  }
}

#endif /* USE_XWIN */
