/**************************************************************************
*                 X  J  D  I  C    V1.1                                   *
*         Japanese-English Dictionary program (X11 version)               *
*                                                   Author: Jim Breen     *
*  V1.2 by Roger Ang, Oct. '95				          	  *
*  - ported to Amiga						          *
*  - added memory saving routines				          *
*  - optimized the use of cbreaks and optimized output			  *
*    (cause raw output can be slow)					  *   
*  - re-indented and cleaned up					          *
***************************************************************************/

#ifdef __AMIGA__
#include "AK_globals.h"
#include "raw.c"
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

/* Roger's buffering stuff */
#include "stack_buf.c"

/* Following addition by ELI */
#include <signal.h>

/*    Paul Burchard supplied a patch to provide BSD compatibility for xjdic
(it uses the appropriate BSD ioctls in place of the SVR4 stuff).  In
order to enable this, people should compile with the option
-D__STRICT_BSD___ .         */

#ifndef __AMIGA__
#ifdef __STRICT_BSD__
#include <sgtty.h>
#else
#include <sys/termio.h>
#endif
#endif

#define FALSE 0
#define TRUE 1
#define SEEK_END 2

#define MAXLINES 20	/* lines per display */

#define RADLINE 10	/* radicals/line in the "r" display */
#define NRKANA 250*2   /*  size of the romaji to kana tables*/
#define NOFILT 10
#define VMAX 350
#define DEFAULT_DICDIR "."
/* could be: "/usr/local/lib/xjdic"   */
#define NOHITS 1000       /* size of hittab  */

#ifdef __AMIGA__
struct FileLock *f_lock;
struct FileInfoBlock buf;
#else
struct stat *buf;

static enum
{
IOCTL_ORIG,
IOCTL_RAW
} myi_status = IOCTL_ORIG;

#ifdef __STRICT_BSD__
static struct sgttyb    orig,new;
#else
static struct termio    orig,new;
#endif
#endif /* not #ifdef __AMIGA__ */

int ShiftJIS = FALSE;
FILE *fpk,*fpki,*fpd,*fpi,*fpr;
unsigned char *dictbuff,*kanjbuff;
unsigned long *jdxbuff,*kjdxbuff;
unsigned char instr[256];
unsigned char kanatab[NRKANA*2][7];
int Omode = 0,Smode = 0,Dmode = 0;
int maxlines = MAXLINES,Radline=RADLINE;
unsigned long kindlen,indlen,kdiclen,diclen,hittab[NOHITS];
int verblen,DispHit,ksp,hitind,FirstKanj = 0;
unsigned char kmodes[2][10] = {"ON","OFF"};
unsigned long chline,chpos,it,kindptr,indptr,lone;
unsigned char strfilt[10],tempout[80];
unsigned char IRname[50] = {"radicals.tm"};
unsigned char IDname[30] = {"edict"};
unsigned char IJDXname[30] = {"edict.xjdx"};
unsigned char IKDname[30] = {"kanjidic"};
unsigned char IKJDXname[30] = {"kanjidic.xjdx"};
/* above are for short file name, 
   below are for full file name (including path) */
unsigned char Rname[50] = {"radicals.tm"};
unsigned char Dname[60] = {"edict"};
unsigned char JDXname[60] = {"edict.xjdx"};
unsigned char KDname[60] = {"kanjidic"};
unsigned char KJDXname[60] = {"kanjidic.xjdx"};
unsigned char ROMname[60] = {"romkana.cnv"};
unsigned char IROMname[60] = {"romkana.cnv"};
unsigned char Vname[60] = {"vconj"};
unsigned char IVname[60] = {"vconj"};
unsigned char ENVname[50] = {""};
int jiver = 14;	/*The last time the index structure changed was Version1.4*/
unsigned char sver[] = {"1.2"};
unsigned char fbuff[512];
unsigned char ksch[50],ktarg[50];
unsigned char Help[22][81] = {
"\n\nXJDIC USAGE SUMMARY  (See xjdic.man for full information)\n\n",
"At the XJDIC SEARCH KEY: respond:\n\n",
"  a string of ascii, kana and/or kanji to look up in the main dictionary\n",
"    (prefix with @ or # to invoke conversion to hiragana or katakana)\n",
"  \\ to put it in Kanji Dictionary mode (see below)\n",
"  ? to get this display\n",
"  / to toggle the display between the two kanji_within_compound modes\n",
"  ; to activate/dectivate any filters\n",
"  : to toggle the verb deinflection function on and off\n",
"  bye   to exit\n\n",
"In Kanji Dictionary mode, the prompt is KANJI LOOKUP TYPE:.  Respond\n\n",
"  k  followed by a single kanji or a kana reading (default)\n",
"  j  followed by the 4-digit hexadecimal JIS code for a kanji\n",
"  j  followed by - and the 4-digit KUTEN code for a kanji\n",
"  j  followed by s and the 4-digit hexadecimal Shift-JIS code for a kanji\n",
"  m  followed by an (English) kanji meaning\n",
"  c  followed by an index code such as Nnnn (Nelson), Bnn (Bushu), etc\n",
"  r  initiates a display of all radicals and their numbers\n\n",
"$$$"
};

unsigned char RVon[] = {0x1b,'[','7','m',0};
unsigned char RVoff[] = {0x1b,'[','m',0};

#ifdef __AMIGA__
unsigned char ClrEOL[] = {0x9b,0x4b,0};  /* clear to end of line */
#endif

int nofilts=FALSE,filton[NOFILT],filtact[NOFILT],filttype[NOFILT],filtcoden[NOFILT];
unsigned char filtnames[NOFILT][50],filtcodes[NOFILT][10][10];
unsigned char testline[1025];
unsigned char vdicf[VMAX][7],vinfl[VMAX][21],vcomms[41][50];
int strf,Jverb = TRUE,vcommno[VMAX];
unsigned char vline[250],vstr[13];

short save_mem = 0;
short exit_err = 1;

/* globals for file buffering */
SB_bufferset *dic_buffers = NULL;
SB_bufferset *kanj_buffers = NULL;
SB_bufferset *jdx_buffers = NULL;
SB_bufferset *kjdx_buffers = NULL;


/*====== Prototypes========================================================*/
void Verbtoggle(void);
void FiltSet(void);
void xjdicrc(void);
void DoRADICALS(void);
int Vlookup(void);
void AppKanji(unsigned char c1,unsigned char c2);
void Verbinit(void);
int Kstrcmp3(void);
void KOut(unsigned char *sout);
void LoadKana(void);
void DoRomaji(unsigned char kc);
int kanaconv(int rpos, int rlen);
void togglemode(void);
void DoKANJI(void);
void DoJIS(void);
int addhit(long spot);
void GetEUC(unsigned char *eucline);
void cbreakon(void);
void cbreakoff(void);

#ifndef __AMIGA__
void ioctlorig();
void ioctlraw();
#endif

void Lookup(void);
unsigned long jindex(unsigned long xit);
unsigned char dbchar(unsigned long xit);
void DicSet(void);
int Kstrcmp2(int i);
void sjis2jis(int *p1,int *p2);/* Ken Lunde's routine  */
void jis2sjis(unsigned char *p1,unsigned char *p2);/* Ken Lunde's routine  */
int stringcomp(unsigned char *s1, unsigned char *s2);
void FixSJIS(unsigned char *jline);

#ifdef __AMIGA__
/* my cleanup routine called on exiting */
int my_exit(int i);

int my_exit(int i)
{
  SB_bufferset *buffers = NULL;

  cbreakoff();

  /* pause, in case of error message, exiting resets the console */
  if (exit_err)  Delay(150);

  /* clean up buffers */
  freeall_SBuffers();                                        
  while (SB_global_bufferset) {                              
    buffers = SB_global_bufferset;
    SB_global_bufferset = 
      SB_bufferset_remove(SB_global_bufferset, buffers);
    SB_bufferset_delete(buffers);
  } 

  AK_cleanup(NULL);
  return(i);
}
#endif

/*====== end of prototypes==================================================*/

/*====stringcomp==stricmp & strcasecmp pulled together=========*/
int stringcomp(unsigned char *s1, unsigned char *s2)
{	
  int i;	 unsigned char c1,c2;
  
  for(i = 0; i < strlen(s1);i++)  {
    c1 = s1[i];
    if (c1 < 0x60) c1 = (c1|0x20);
    c2 = s2[i];
    if (c2 < 0x60) c2 = (c2|0x20);
    if (c1 != c2) return(1);
  }
  return (0);
}

#ifndef __AMIGA__
/* ==== ioctl routines supplied by Cameron Blackwood=======================*/
/* ==== BSD compatibility hacked in by Paul Burchard ==============*/
void    ioctlraw()
{
  if (myi_status == IOCTL_ORIG)    {
#ifdef __STRICT_BSD__
    ioctl(0, TIOCGETP, &orig); ioctl(0, TIOCGETP, &new);
    new.sg_flags |= CBREAK; new.sg_flags &= ~ECHO;
    ioctl(0, TIOCSETP, &new);
#else
    ioctl(0, TCGETA, &orig); ioctl(0, TCGETA, &new);
    new.c_lflag &= ~ICANON; new.c_lflag &= ~ISIG; new.c_lflag &= ~ECHO;
    new.c_lflag &= ~IXON;
    new.c_cc[4] = 1; new.c_cc[5] = 0;   ioctl(0, TCSETA, &new);
#endif
    myi_status=IOCTL_RAW;
  }
  else return;
}

void    ioctlorig()
{
#ifdef __STRICT_BSD__
  ioctl(0, TIOCSETP, &orig);
#else
  ioctl(0, TCSETA, &orig);
#endif
  myi_status = IOCTL_ORIG;
}
#endif /* #ifndef __AMIGA__ */

void cbreakoff()
{
#ifdef __AMIGA__
  cooked();
#else
  ioctlorig();
  /*system("stty -cbreak echo");*/
#endif
}

void cbreakon()
{
#ifdef __AMIGA__
  raw();
#else
  ioctlraw();
  /*system("stty cbreak -echo");*/
#endif
}


/*=====DoRomaji==collect search key from keyboard. Convert to kana.======*/
void DoRomaji(unsigned char kc)
{
  int is;
  unsigned char c;
  
  /* collect the search string   */
  Smode = 1;
  if(kc == '#') Smode = 2;
  is = 0;
  ksp = 0;
  c = 0;
  ktarg[0] = 0;

#ifdef __AMIGA__
  printf("\r%s\r%sROMAJI ENTRY:%s ",ClrEOL,RVon,RVoff);
#else
  printf("\r                                         ");
  printf("\r%sROMAJI ENTRY:%s ",RVon,RVoff);
#endif
  /* loop until Enter is pressed   */
  while ((c != 0x0a) && (c != 0x0d)) {
    c = getchar();
    
    if ((c == 0x8)||(c == 0x7f)) {
      /* backspace  */
      if (is != ksp)  {
	/* kana mode - back over a romaji  */
	ksch[is-1] = '\0';
	is--;
        printf("\b \b");
	continue;
      }
      else {
	if (strlen(ktarg) != 0)  {
	  /* kana mode - back over a kana  */
	  ktarg[strlen(ktarg)-2] = '\0';
#ifdef __AMIGA__
          printf("\b\b  \b\b");
#else
	  sprintf(tempout,"\b\b  \r%sROMAJI ENTRY:%s %s%s",RVon,RVoff,ktarg,ksch+ksp);
	  KOut(tempout);
#endif
	  continue;
	}
      }
    }
    if (c > 32) {  /* ordinary character - store and display   */
      ksch[is] = c | 0x20;
      ksch[is+1] = '\0';
      is++;
      putchar(c);
    }
    if (ksp != is) {
      /* the input string so far is now parsed for romaji -> kana conversions.
	 function "kanaconv" is used for the various sub-strings */

      /* if there is an "nn", "nm" or "mm", convert the first to "q" 
	 to force it to be converted to a kana "n"   */
      if ((ksch[ksp] == 'n')&&(ksch[ksp+1] == 'n')) ksch[ksp] = 'q';
      if ((ksch[ksp] == 'm')&&(ksch[ksp+1] == 'm')) ksch[ksp] = 'q';
      if ((ksch[ksp] == 'n')&&(ksch[ksp+1] == 'm')) ksch[ksp] = 'q';
      /* if there is "nX" or "mX", where "X" is not a vowel or a "y", 
	 force the "n". */
      if (((ksch[ksp] == 'n')||(ksch[ksp] == 'm'))&&(ksch[ksp+1] != 0))	{
	c = ksch[ksp+1];
	if ((c!='y')&&(c!='a')&&(c!='e')&&(c!='i')&&(c!='o')&&
	    (c!='u')&&(c!='\'')) {
	  ksch[ksp] = 'q';
	}
      }
      if(kanaconv(ksp,1)) { /*  match on a,e,i,o,u,q or -  ?  */
	continue;
      }
      if (ksch[ksp] == ksch[ksp+1]) { 
	/* double consonant - force small "tsu" */
	ksch[ksp] = '*';
	kanaconv(ksp,1);
	continue;
      }
      if(kanaconv(ksp,2)) { /* match on two letter syllable   */
	continue;
      }
      if(kanaconv(ksp,3)) { /*match on 3 letter syllable    */
	continue;
      }
      if(kanaconv(ksp,4)) { /*match on 4 letter syllable    */
	continue;
      }
    }		/* end of rom->kana */
  }			/* end of while loop */
  if (ksch[ksp] =='n') { /*flush out a trailing "n"*/
    ksch[ksp] = 'q';
    kanaconv(ksp,1);
  }

  strcpy(instr,ktarg);
}

/*========kanaconv==convert romaji to kana==============================*/
int kanaconv(int rpos, int rlen)
{
  /* rpos and rlen are the start and length of the romaji characters in
     array ksch.  Smode specifies hira or kata. If found, the kana is
     appended to ktarg and TRUE returned.                          */

  int koff,ki;
  unsigned char targ[50];
  
  koff = (Smode-1)*NRKANA;
  for(ki = 0; ki < rlen; ki++)	{
    targ[ki] = ksch[rpos+ki];
  }
  targ[rlen] = 0;
  for (ki = koff; ki < koff+NRKANA; ki+=2) {
    if (strlen(targ) != strlen(kanatab[ki])) continue;
    if (stringcomp(targ,kanatab[ki]) != 0) continue;
    strcat(ktarg,kanatab[ki+1]);
    ksp = ksp+rlen;
    sprintf(tempout,"\b \r%sROMAJI ENTRY:%s %s%s",RVon,RVoff,ktarg,ksch+ksp);
    KOut(tempout);
    return (TRUE);
  }
  return(FALSE);
}

/* ==== LoadKana=== Load the romaji to kana conversion file============*/
void LoadKana()
{
  int i,ih,mode;
  FILE *fp,*fopen();
  unsigned char LKin[80],*ptr;
  
  for (i = 0; i < NRKANA*2; i++) strcpy(kanatab[i]," ");
  fp=fopen(ROMname,"r");
  if (fp==NULL)  {
    printf("Cannot open %s\n",ROMname);
    exit(1);
  }

  mode = 0;
  while (!feof(fp)) {
    fgets(LKin,79,fp);
    if (feof(fp))break;
    /*LKin[strlen(LKin)-1] = '\0';*/
    if(LKin[0] == '#')continue;
    if((LKin[0] == '$')&&((LKin[1]|0x20) == 'h')) {
      mode = 0;
      ih = 0;
      continue;
    }
    if((LKin[0] == '$')&&((LKin[1]|0x20) == 'k'))  {
      mode = 1;
      ih = 0;
      continue;
    }
    ptr = (unsigned char *)strtok(LKin," \t");
    strcpy(kanatab[mode*NRKANA+ih*2+1],ptr);
    ptr = (unsigned char *)strtok(NULL," \t\r\n");
    strcpy(kanatab[mode*NRKANA+ih*2],ptr);
    ih++;
    if(ih == NRKANA) {
      printf("Too many romaji table entries!");
      exit(1);
    }
  }
  fclose(fp);
}
/*======jis2sjis  (from Ken Lunde) =====================================*/
void jis2sjis(unsigned char *p1,unsigned char *p2) /* courtesy of Ken Lunde */
{
  register unsigned char c1 = *p1;
  register unsigned char c2 = *p2;
  register int rowOffset = c1 < 95 ? 112 : 176;
  register int cellOffset = c1 % 2 ? 31 + (c2 > 95) : 126;
  
  *p1 = ((c1 + 1) >> 1) + rowOffset;
  *p2 = c2 + cellOffset;
}
/*=====KOut===output kana/kanji according to selected mode===========*/
void KOut(unsigned char *sout)
{
  int i;
  unsigned char c1,c2;  
  unsigned int tmpch;

  for (i = 0; i < strlen(sout); i++) {
    c1 = sout[i]; c2 = sout[i+1];
    if (c1 < 127) {
      putchar(c1);
      continue;
    }

    /* my Amiga kanji output - Roger */
#ifdef __AMIGA__
    AK_curr_encoding = EUC;
    tmpch = (c1 << 8) | c2;
    AK_putchar(tmpch);
    i++;
    continue;
#endif

    switch(Omode) {
    case 0 :  /* JIS (default)  */
      printf("%c$B%c%c%c(B",0x1b,c1&0x7f,c2&0x7f,0x1b);
      i++;
      break;
	  
    case 1 : /* EUC (internal format) */
      printf("%c%c",c1,c2);
      i++;
      break;
	  
    case 2 : /* Shift-JIS */
      c1 -= 128; c2 -= 128;
      jis2sjis(&c1,&c2);
      printf("%c%c",c1,c2);
      i++;
      break;
    }
  }
}

/*====DicSet check & load Dictionary and index files=======*/
void DicSet()
{
  unsigned long ver_check;
  int nodread;

#ifdef __AMIGA__
  f_lock = (struct FileLock *) Lock(Dname, SHARED_LOCK);
  if (f_lock == NULL)  {
    perror(NULL);
    printf("Cannot lock: %s \n",Dname);
    exit(1);
  }
  if (Examine((BPTR) f_lock, &buf) == NULL) {
    perror(NULL);
    UnLock((BPTR) f_lock);
    printf("Cannot examine: %s \n",Dname);
    exit(1);
  }
  UnLock((BPTR) f_lock);
  diclen = buf.fib_Size;
#else
  /* not Amiga */
  buf = (void *)malloc(sizeof(struct stat));
  if(stat(Dname, buf) != 0) {
    /*perror();*/
    printf("Cannot stat: %s \n",Dname);
    exit(1);
  }
  diclen = buf->st_size;
#endif

  fpd=fopen(Dname,"rb");
  if (fpd==NULL ) {
    printf("\nCannot open dictionary file: %s\n",Dname);
    exit(1);   
  }

  if (save_mem)
    dictbuff = NULL;
  else {
    dictbuff = (unsigned char *)calloc(diclen+100, sizeof(unsigned char));
  }

  if (dictbuff) {
    nodread = diclen/1024;
    fread((unsigned char *)dictbuff+1, 1024, nodread, fpd);
    nodread = diclen % 1024;
    fread((unsigned char *)(dictbuff+(diclen/1024)*1024)+1, nodread,1, fpd);
    dictbuff[0] = 0xa;
  }

  diclen++;
  fclose(fpd);

  if (dictbuff == NULL) {
    /* setup buffering of variable */
    if (!SBuffer_var((void**) (&dictbuff))) {
      fprintf(stderr,"Could not memory buffer dictionary\n");
      exit(1);
    }
    else
      dic_buffers = var_SBuffered((void**) (&dictbuff));
  }

#ifdef __AMIGA__
  f_lock = (struct FileLock *) Lock(JDXname, SHARED_LOCK);
  if (f_lock == NULL)  {
    perror(NULL);
    printf("Cannot lock: %s \n",JDXname);
    exit(1);
  }
  if (Examine((BPTR) f_lock, &buf) == NULL) {
    perror(NULL);
    UnLock((BPTR) f_lock);
    printf("Cannot examine: %s \n",JDXname);
    exit(1);
  }
  UnLock((BPTR) f_lock);
  indlen = buf.fib_Size;
#else  /* not Amiga */
  if(stat(JDXname, buf) != 0)  {
    printf("Cannot stat: %s \n",JDXname);
    exit(1);
  }
  indlen = buf->st_size;
#endif

  fpi = fopen(JDXname,"rb");
  if(fpi == NULL) {
    printf("\nCannot open index file: %s\n",JDXname);
    exit(1);   
  }

  indptr = indlen/sizeof(long)-1;

  if (save_mem)
    jdxbuff = NULL;
  else {
    jdxbuff = (unsigned long *)calloc(indlen+1024, sizeof(unsigned char));
  }

  if (jdxbuff)  {
    nodread = indlen/1024+1;
    fread((char*) jdxbuff,1024,nodread,fpi);
    if (jdxbuff[0] != (diclen+jiver))  {
      printf ("The dictionary and index files do not match! \n");
      fclose(fpi);
      exit(1);
    }
  }
  else {
    ver_check = 0;
    fread((char*)(&ver_check), sizeof(unsigned long), 1, fpi); 

    if (ver_check != (diclen+jiver))  {
      printf ("The dictionary and index files do not match! \n");
      fclose(fpi);
      exit(1);
    }
  }
  fclose(fpi);

  if (jdxbuff == NULL) {
    /* setup buffering of variable */
    if (!SBuffer_var((void**) (&jdxbuff))) {
      fprintf(stderr,"Could not memory buffer dictionary\n");
      exit(1);
    }
    else
      jdx_buffers = var_SBuffered((void**) (&jdxbuff));
  }


#ifdef __AMIGA__
  f_lock = (struct FileLock *) Lock(KDname, SHARED_LOCK);
  if (f_lock == NULL)  {
    perror(NULL);
    printf("Cannot lock: %s \n",KDname);
    exit(1);
  }
  if (Examine((BPTR) f_lock, &buf) == NULL) {
    perror(NULL);
    UnLock((BPTR) f_lock);
    printf("Cannot examine: %s \n",KDname);
    exit(1);
  }
  UnLock((BPTR) f_lock);
  kdiclen = buf.fib_Size;
#else  /* not Amiga */
  if(stat(KDname, buf) != 0)  {
    /*perror();*/
    printf("Cannot stat: %s \n",KDname);
    exit(1);
  }
  kdiclen = buf->st_size;
#endif

  /* repeat for kanji dictionary */
  fpk=fopen(KDname,"rb");
  if (fpk==NULL) {
    printf("\nCannot open Kanji dictionary file: %s\n",KDname);
    exit(1);   
  }

  if (save_mem)
    kanjbuff = NULL;
  else {
    kanjbuff = (unsigned char *)calloc(kdiclen+100, sizeof(unsigned char));
  }

  if (kanjbuff)  {
    nodread = kdiclen/1024;
    fread((unsigned char *)kanjbuff+1, 1024, nodread, fpk);
    nodread = kdiclen % 1024;
    fread((unsigned char *)(kanjbuff+(kdiclen/1024)*1024)+1, nodread,1, fpk);
    kanjbuff[0] = 0xa;
  }

  kdiclen++;
  fclose(fpk);

  if (kanjbuff == NULL) {
    /* setup buffering of variable */
    if (!SBuffer_var((void**) (&kanjbuff))) {
      fprintf(stderr,"Could not memory buffer dictionary\n");
      exit(1);
    }
    else
      kanj_buffers = var_SBuffered((void**) (&kanjbuff));
  }

#ifdef __AMIGA__
  f_lock = (struct FileLock *) Lock(KJDXname, SHARED_LOCK);
  if (f_lock == NULL)  {
    perror(NULL);
    printf("Cannot lock: %s \n",KJDXname);
    exit(1);
  }
  if (Examine((BPTR) f_lock, &buf) == NULL) {
    perror(NULL);
    UnLock((BPTR) f_lock);
    printf("Cannot examine: %s \n",KJDXname);
    exit(1);
  }
  UnLock((BPTR) f_lock);
  kindlen = buf.fib_Size;
#else  /* not Amiga */
  if(stat(KJDXname, buf) != 0)  {
    /*perror();*/
    printf("Cannot stat: %s \n",KJDXname);
    exit(1);
  }
  kindlen = buf->st_size;
#endif

  fpki = fopen(KJDXname,"rb");
  if(fpki == NULL) {
    printf("\nCannot open kanji index file: %s\n",KJDXname);
    exit(1);   
  }

  kindptr = kindlen/sizeof(long)-1;

  if (save_mem)
    kjdxbuff = NULL;
  else {
    kjdxbuff = (unsigned long *)calloc(kindlen+1024, sizeof(unsigned char));
  }

  if (kjdxbuff) {
    nodread = kindlen/1024+1;
    fread((char*)kjdxbuff,1024,nodread,fpki);

    if (kjdxbuff[0] != (kdiclen+jiver))  {
      printf ("The kanji dictionary and index files do not match!\n");
      fclose(fpki);
      exit(1);
    }
  }
  else {
    ver_check = 0;
    fread((char*)(&ver_check), sizeof(unsigned long), 1, fpki);

    if (ver_check != (kdiclen+jiver))  {
      printf ("The dictionary and index files do not match! \n");
      fclose(fpki);
      exit(1);
    }
    kjdxbuff = NULL;
  }
  fclose(fpki);

  if (kjdxbuff == NULL) {
    /* setup buffering of variable */
    if (!SBuffer_var((void**) (&kjdxbuff))) {
      fprintf(stderr,"Could not memory buffer dictionary\n");
      exit(1);
    }
    else
      kjdx_buffers = var_SBuffered((void**) (&kjdxbuff));
  }

#ifndef __AMIGA__
  free(buf);
#endif
}


/*=====dbchar====returns specified character from a dictionary===============*/
unsigned char dbchar(unsigned long xit)
{
  unsigned char c;

  if (Dmode == 0) {
    if (!dic_buffers)
      return(dictbuff[xit]);
    else {
      c = get_SBuffered_char(Dname, dic_buffers, xit, diclen);
      if (c == 0)  {
	fprintf(stderr,"Memory buffer problem - %s index: %ld\n", Dname, xit);
	exit(1);
      }
      return c;
    }
  }
  else {
    if (!kanj_buffers)
      return(kanjbuff[xit]);
    else {
      c = get_SBuffered_char(KDname, kanj_buffers, xit, kdiclen);
      if (c == 0)  {
	fprintf(stderr,"Memory buffer problem - %s index: %ld\n", KDname, xit);
	exit(1);
      }
      return c;
    }
  }
}


/*======jindex  returns specified entry from .xjdx file========*/

unsigned long jindex(unsigned long xit)
{
  unsigned long tmp_ind;

  if (Dmode == 0) {
    if (!jdx_buffers)
      return(jdxbuff[xit]);
    else {
      tmp_ind = get_SBuffered_ind(JDXname, jdx_buffers, xit, indlen);
      if (tmp_ind == 0)  {
	fprintf(stderr,"Memory buffer problem - %s index: %ld\n", JDXname, xit);
	exit(1);
      }
      return tmp_ind;
    }
  }
  else {
    if (!kjdx_buffers)
      return(kjdxbuff[xit]);
    else {
      tmp_ind = get_SBuffered_ind(KJDXname, kjdx_buffers, xit, kindlen);
      if (tmp_ind == 0)  {
	fprintf(stderr,"Memory buffer problem - %s index: %ld\n", KJDXname, xit);
	exit(1);
      }
      return tmp_ind;
    }
  }
}

/*=========string comparison function used in binary search ==========*/
int Kstrcmp2(int slen)
{
  unsigned c1,c2;
  int i,rc1,rc2;
  /* effectively does a strnicmp on two "strings" , one in fbuff               
     and the other pointed to by jindex(it)
     except it will make katakana and hiragana match (EUC A4 & A5) */
  
  for (i = 0; i<slen ; i++) {
    c1 = fbuff[i];
    c2 = dbchar(jindex(it)+i);
    if ((c1 == '\0')||(c2 == '\0')) return(0);
    if ((i % 2) ==0) {
      if (c1 == 0xA5)  {
	c1 = 0xA4;
      }
      if (c2 == 0xA5)   {
	c2 = 0xA4;
      }
    }
    if ((c1 >= 'A') && (c1 <= 'Z')) c1 |= 0x20; /*fix ucase*/
    if ((c2 >= 'A') && (c2 <= 'Z')) c2 |= 0x20;
    if (c1 != c2 ) {
      rc1 = c1;
      rc2 = c2;
      return(rc1-rc2);
    }
  }
  return(0);
}
/*=========string comparison function used in binary search ==========*/
int Kstrcmp3()
{
  unsigned c1,c2;
  int slen,i,rc1,rc2;
  /* effectively does a strnicmp on two "strings" , one in vstr                
     and the other pointed to by jindex(it)
     except it will make katakana and hiragana match (EUC A4 & A5) */
  
  slen = strlen(vstr);
  for (i = 0; i<slen ; i++) {
    c1 = vstr[i];
    c2 = dbchar(jindex(it)+i);
    if ((c1 == '\0')||(c2 == '\0')) return(0);
    if ((i % 2) ==0) {
      if (c1 == 0xA5) {
	c1 = 0xA4;
      }
      if (c2 == 0xA5) {
	c2 = 0xA4;
      }
    }
    if ((c1 >= 'A') && (c1 <= 'Z')) c1 |= 0x20; /*fix ucase*/
    if ((c2 >= 'A') && (c2 <= 'Z')) c2 |= 0x20;
    if (c1 != c2 ) {
      rc1 = c1;
      rc2 = c2;
      return(rc1-rc2);
    }
  }
  return(0);
}
/*======function to test if this entry has already been displayed=====*/
int addhit(long spot)
{
  int i;
  for (i=0;i<=hitind;i++) {
    if(hittab[i] == spot) return(0);
  }
  if(hitind < NOHITS) hitind++;
  hittab[hitind] = spot;
  return(1);
}

/*====GetEUC - gets next text line, and converts to EUC ============*/

void GetEUC(unsigned char *eucline)
{
  int i,j,SI;
  
  eucline[0] = '\0';
  chline = 0;
  chpos = 0;
  SI = FALSE;
  ShiftJIS = FALSE;
  j = 0;
  for (i = 0; i < strlen(instr); i++) {
    if ((instr[i]==0x1b)&&(instr[i+1]=='$')&&(instr[i+2]=='B'))	{
      SI = TRUE;
      i+=2;
      continue;
    }
    if ((instr[i]==0x1b)&&(instr[i+1]=='$')&&(instr[i+2]=='@'))	{
      SI = TRUE;
      i+=2;
      continue;
    }
    if ((instr[i]==0x1b)&&(instr[i+1]=='(')&&(instr[i+2]=='J'))	{
      SI = FALSE;
      i+=2;
      continue;
    }
    if ((instr[i]==0x1b)&&(instr[i+1]=='(')&&(instr[i+2]=='B'))	{
      SI = FALSE;
      i+=2;
      continue;
    }
    if (instr[i] == '\0')break;
    if (SI) {
      eucline[j] = instr[i] | 0x80;
    }
    else {
      eucline[j] = instr[i];
    }
    j++;
    eucline[j] = '\0';
  }
  /*  fix up SHIFT-JIS, if present  */
  FixSJIS(eucline);
}

/*====FixSJIS=== convert any SJIS to EUC in a string==================*/
void FixSJIS(unsigned char *jline)
{
  int i,p1,p2,ShiftJIS;
  
  ShiftJIS = FALSE;
  for (i = 0; i < strlen(jline); i++) {
    p1 = jline[i];
    if (p1 < 127)continue;
    p2 = jline[i+1];
    if ((p1 >= 129) && (p1 <= 159)) ShiftJIS = TRUE;
    if (((p1 >= 224) && (p1 <= 239)) && ((p2 >= 64) && 	(p2 <= 158))) 
      ShiftJIS = TRUE;
    if (ShiftJIS) {
      sjis2jis   (&p1,&p2);
      p1 += 128;
      p2 += 128;
      jline[i] = p1;
      jline[i+1] = p2;
    }
    i++;
  }
}

/*===sjis2jis    - convert ShiftJIS to JIS ===========================*/

void sjis2jis   (int *p1,int *p2)   /* Ken Lunde's routine  */
{
  register unsigned char c1 = *p1;
  register unsigned char c2 = *p2;
  register int adjust = c2 < 159;
  register int rowOffset = c1 < 160 ? 112 : 176;
  register int cellOffset = adjust ? (31 + (c2 > 127)) : 126;
  
  *p1 = ((c1 - rowOffset) << 1) - adjust;
  *p2 -= cellOffset;
}

/*==== Verbinit===Load & initialize verb inflection details==========*/
void Verbinit()
{
  unsigned char tempstr[512],*vptr;
  int vmode,i;
  FILE *fi;
  
  for (i = 0;i< VMAX;i++) {
    vdicf[i][0] = 0;
    vinfl[i][0] = 0;
    vcommno[i] = 40;
  }
  for (i = 0;i<40;i++) {
    vcomms[i][0] = 0;
  }
  vmode = 1;
  strcpy(vcomms[40],"Unknown type");
  verblen = 0;
  fi = fopen(Vname,"r");
  if (fi == NULL)  {
    printf("Cannot open verb file - function disabled\n");
    Jverb = FALSE;
    exit(1);
  }
  while(TRUE) {
    fgets(tempstr,511,fi);
    if(feof(fi))break;
    if (tempstr[0] == '#')  continue;
    if (tempstr[0] == '$')  {
      vmode = 2;
      continue;
    }
      
    switch (vmode) {
    case 1 :
      vptr = (unsigned char *)strtok(tempstr," \t\n\r");
      i = atoi(vptr);
      if ((i < 0) || (i > 39)) break;
      vptr = (unsigned char *)strtok(NULL,"\t\n\r");
      strcpy(vcomms[i],vptr);
      break;	
    case 2 :	
      vptr = (unsigned char *)strtok(tempstr," \t\n\r");
      strcpy(vinfl[verblen],vptr);
      vptr = (unsigned char *)strtok(NULL," \t\n\r");
      strcpy(vdicf[verblen],vptr);
      vptr = (unsigned char *)strtok(NULL," \t\n\r");
      i = atoi(vptr);
      if ((i >= 0)&&(i <= 40))  vcommno[verblen] = i;
      verblen++;
      if (verblen==VMAX)  {
	printf("Verb data overflow. Ignoring following entries\n");
	verblen--;
	fclose(fi);
	return;
      }
      break;
    }
  }
  verblen--;
  fclose(fi);
}

/*=== append a kana/kanji to the verb display line================*/
void AppKanji(unsigned char c1,unsigned char c2)
{
  unsigned char ops[3];
  
  ops[0] = c1;
  ops[1] = c2;
  ops[2] = 0;
  strcat(vline,ops);
}

/*=======Vlookup== look up plain form verb in dictionary=============*/
int Vlookup()
{
  long lo,hi,schix;
  int res,hit;
  unsigned char khi,klo,cc,ops[4];
  
  khi = 0;
  klo = 0;
  lo = 1;
  hi = indptr;
  vline[0] = 0;
  while(TRUE)  {
    it = (lo+hi)/2;
    res = Kstrcmp3();
    if (res == 0)  break;
    if (res < 0)  {
      hi = it-1;
    }
    else {
      lo = it+1;
    }
    if (lo > hi)break;
  }
  if (res != 0) return (FALSE);
  /*  we have a match, so scan backwards up the table to find the first   */
  while (TRUE) {
    if(Kstrcmp3() == 0)	{
      it--;
      if (it == 0) {
	it = 1;
	break;
      }
      continue;
    }
    else {
      it++;
      break;
    }
  }
  
  while (Kstrcmp3() == 0)  {
    schix = jindex(it);
    if(dbchar(schix-1) != 10) {
      it++;
      continue;
    }
    /* back off to the start of this line   */
    while ((dbchar(schix) != 0xa) && (schix >= 0)) schix--;
    schix++;
    /* now work forwards, displaying the line  */
    hit = FALSE;
    /* If the first word has already been displayed, skip it.
       Otherwise, put braces around the first word (kanji)  */
    while (TRUE) {
      cc = dbchar(schix);
      if (cc < 32) break;
      /* put a () around the yomikata in an ascii or Kanji search */
      if (cc=='[')  {
	AppKanji(0xa1,0xcA);  /* EUC (  */
	schix++;
	continue;
      }
      if (cc==']') {
	AppKanji(0xA1,0xCB);  /* EUC )  */
	schix++;
	continue;
      }
      if (cc < 128) { /* non-Japanese, display it (fix up the "/") */
	ops[0]= cc;
	ops[1] = '\0';
	if (ops[0] == '/')  {
	  if (hit)  {
	    ops[0] = ',';
	    ops[1] = ' ';
	    ops[2] = '\0';
	  }
	  else  {
	    hit = TRUE;
	    ops[0] = '\0';
	  }
	}
	strcat(vline,ops);
      }
      else {
	if (khi == 0) {
	  khi = cc;
	}
	else {
	  klo = cc;
	  AppKanji(khi,klo);
	  khi = 0;
	  klo = 0;
	}
      }
      schix++;
    }
    if(strlen(vline) > 0) break;
  }
  if(strlen(vline) <=1) return(FALSE);
  return(TRUE);
}


/*=========== Lookup - carry out dictionary search ================*/

void Lookup()
{
  /*
    
    Carries out a search for matches with the string "fbuff" in the specified
    dictionary. It matches the full string, then progressively shortens it.
    
    */
  unsigned long endtest,schix,schiy,schiz,itsav,itok,hi2,lo2,lo,hi;
  int j,dind,res,hit,skip,brace;
  int slk,ldisp,slench,slen,slenx,i;
  unsigned int LUCont,khi,klo,cc;
  unsigned long bshit[20];
  unsigned char k1,k2,kanj1,kanj2;
  int FiltOK;
  unsigned char vlast[11],temp[11],ops[80];
  int vi,vok;
  
  vlast[0] = 0;
  
  if ((Dmode == 0) && Jverb && (fbuff[0] > 0xa8) && (fbuff[2] < 0xa5) && 
      (fbuff[4] < 0xa5))  {
    /* possible inflected verb or adjective */
      
    vstr[0] = fbuff[0];
    vstr[1] = fbuff[1];
    vstr[2] = 0;
    for (i=0;i<11;i++)   temp[i] = fbuff[i];
      
    for (vi = 0;vi <= verblen;vi++) {
      vok = TRUE;
      vstr[2] = 0;
      for (i = 0;i < strlen(vinfl[vi]);i++)  {
	if (fbuff[2+i] != vinfl[vi][i])  {
	  vok = FALSE;
	  break;
	}
      }
      if (!vok) continue;
      strcat(vstr,vdicf[vi]);
	  
      if(strcmp(vstr,temp) == 0) continue;
      if (strcmp(vstr,vlast) == 0)continue;
      if (Vlookup())  {
	strcpy(vlast,vstr);
	khi = 0;
	printf(" Possible inflected verb or adjective: (%s)\n",
	       vcomms[vcommno[vi]]);				
	for(it = 0; it <strlen(vline)-2; it++) {
	  cc = vline[it];
	  if (cc < 128) { /* non-Japanese, display it  */
	    ops[0]= cc;
	    ops[1] = '\0';
	    printf("%s",ops);
	  }
	  else {  /* kana or kanji  */
	    if (khi == 0)
	      {
		khi = cc;
	      }
	    else {
	      klo = cc;
	      ops[0] = khi; ops[1] = klo; ops[2] = 0;
	      KOut(ops);
	      khi = 0;
	      klo = 0;
	    }
	  }
	}
	printf("\n");
	printf("Continue with this search (y/n)");
	cc = getchar();
	if ((cc == 'n')||(cc == 'N')) return;
	if ((cc != 'y')&&(cc != 'Y')) {
	  ungetc(cc,stdin);
	  return;
	}
	printf("\n");
      }		
    }
  }
  /*  do a binary search through the index table looking for a match  */
  DispHit = FALSE;
  ldisp = 0;
  khi = 0;
  klo = 0;
  lo = 1;
  hi = indptr;
  endtest = indptr;
  if (Dmode != 0)  {
    hi = kindptr;
    endtest = kindptr;
  }
  LUCont = TRUE;
  slench = 2;
  if (fbuff[0] < 127) slench = 1;
  slenx = strlen(fbuff)/slench;
  if (slenx > 20) slenx = 20;
  Smode = 0;
  if ((fbuff[0] == 0xa4)||(fbuff[0] == 0xa5)) Smode = 1;
  for ( slen = 0; slen <slenx; slen++) {
    while(TRUE) {
      it = (lo+hi)/2;
      res = Kstrcmp2(slen*slench+slench);
      if (res == 0)  {
	itsav = it;
	itok = it;
	lo2 = lo;
	hi2 = it;
	while (TRUE) {
	  if(lo2+1 >= hi2) break;
	  it = (lo2+hi2)/2;
	  res = Kstrcmp2(slen*slench+slench);
	  if (res == 0) {
	    hi2 = it;
	    itok = it;
	    continue;
	  }
	  else {
	    lo2 = it+1;
	  }
	}
	bshit[slen] = itok;
	res = 0;
	it = itsav;
	break;
      }
      if (res < 0)  {
	hi = it-1;
      }
      else {
	lo = it+1;
      }
      if (lo > hi) {
	LUCont = FALSE;
	break;
      }
    }
    if (!LUCont) {
      break;
    }
  }
  if (slen == 0) {
    printf("No Match Found\n");
    return;
  }
  
  hitind = 0;
  hittab[0] = -1;
  /*  loop for each possible string length  */
  for (dind = slen-1; dind >= 0 ; dind--) {
    /*  scan backwards up the table to find the first   */
    it = bshit[dind];
    while (TRUE) {
      if(Kstrcmp2(dind*slench+slench) == 0) {
	it--;
	if (it == 0) {
	  it = 1;
	  break;
	}
	continue;
      }
      else {
	it++;
	break;
      }
    }
    hit = FALSE;

#ifdef __AMIGA__
    /* AMIGA set max display lines to current window dimensions */
    maxlines = AK_conUnit->cu_YMax-1;
#endif

    /* this is the display loop - usually one line per entry  */
    while (Kstrcmp2(dind*slench+slench) == 0) {
      /* display as long as there are matches*/
      schix = jindex(it);
      schiy = schix;
      /* back off to the start of this line   */
      while ((dbchar(schix) != 0x0a) && (schix > 0))  schix--;
      schix++;
      /* make copy of line for filter testing   */
      slk=0;
      for(schiz=0;dbchar(schix+schiz)>=0x20;schiz++) {
	testline[schiz] = dbchar(schix+schiz);
	if (testline[schiz]=='/')  slk++;
      }
      testline[schiz+1] = '\0';
      kanj1 = testline[0];
      kanj2 = testline[1];
      FiltOK = TRUE;
      if((Dmode == 0)&& nofilts) {
	if(nofilts>0)  {
	  for (i=0;i<NOFILT;i++)  {
	    if(!filtact[i]||!filton[i])continue;
	    if(filttype[i] == 0)  {
	      FiltOK = FALSE;
	      for(j=0;j<filtcoden[i];j++)  {
		if(strstr(testline,filtcodes[i][j]) != NULL)  {
		  FiltOK = TRUE;
		  break;
		}
	      }
	      if(FiltOK)break;
	    }
	    if((filttype[i] == 1)||((filttype[i] == 2)&&(slk <= 2)))  {
	      FiltOK = TRUE;
	      for(j=0;j<filtcoden[i];j++)  {
		if(strstr(testline,filtcodes[i][j]) != NULL)  {
		  FiltOK = FALSE;
		  break;
		}
	      }
	      if(!FiltOK) break;
	    }
	  }
	}
      }
      if(strf && (Dmode ==1)) {
	FiltOK = FALSE;
	if (strstr(testline,strfilt) != NULL) FiltOK = TRUE;
      }
      /* now work forwards, displaying the line  */
      if (FiltOK&&(addhit(schix) != 0) && 
	  (!FirstKanj || (FirstKanj && (dbchar(schiy-1) < 127)))) {
	/* First, display the matched word/kana string  */
	DispHit = TRUE;
	if (Dmode == 0)  {
	  printf("%d: ",dind+1);
	  while (TRUE)	{
	    cc = dbchar(schiy);
	    if (cc < 128) { 
	      /* non-Japanese, display it*/
	      if (!isalpha(cc)) break;
	      ops[0] = cc; ops[1] = 0;
	      printf("%s",ops);
	    }
	    else {   /* kana or kanji  */
	      if (khi == 0)  {
		khi = cc;
	      }
	      else {
		klo = cc;
		ops[0] = khi; ops[1] = klo; ops[2] = 0;
		KOut(ops);
		khi = 0;
		klo = 0;
	      }
	    }
	    schiy++;
	    
	  } /* end of match display  */
	}
	printf(" ");
	hit = FALSE;
	skip = FALSE;
	brace = FALSE;
	/* If the first word has already been displayed, skip it.
	   Otherwise, put braces around the first word (kanji)  */
	if ((schix == jindex(it))&&(Dmode == 0))  {
	  skip = TRUE;
	}
	else  {
	  ops[0] = 0xa1; ops[1] = 0xda; ops[2] = 0; /* JIS [  */
	  KOut(ops);
	  brace = TRUE;
	}
	while ((cc = dbchar(schix)) != 0xa)  {
	  if (cc==' ')  skip = FALSE;
	  if ((brace)&&(cc==' '))  {
	    brace = FALSE;
	    ops[0] = 0xa1; ops[1] = 0xdb; ops[2] = 0; /* JIS ]  */
	    KOut(ops);
	    if (Dmode == 1) {
	      /* display JIS, Kuten & SJIS codes */
	      k1 = kanj1 & 0x7f;
	      k2 = kanj2 & 0x7f;
	      jis2sjis(&k1,&k2);
	      printf (" %x%x [%d:%x%x]",kanj1&0x7f,kanj2&0x7f,((kanj1&0x7f)-0x20)*100+(kanj2&0x7f)-0x20,k1,k2);
	      schix+=5;   /* skip over JIS code (already disp.) */
	    }
	  }
	  /* turn off yomikata skipping when a ']' is reached  */
	  if ((skip)&&(cc==']')) {
	    skip = FALSE;
	    schix++;
	    continue;
	  }
	  /* skip yomikata display during a kana search  */
	  if ((Smode > 0)&&(cc=='[')) skip = TRUE;
	  /* put a () around the yomikata in an ascii search */
	  if ((Smode==0)&&(cc=='[')) {
	    ops[0] = 0xa1; ops[1] = 0xca; ops[2] = 0; /* JIS (  */
	    KOut(ops);
	    schix++;
	    continue;
	  }
	  if ((Smode==0)&&(cc==']')) {
	    ops[0] = 0xa1; ops[1] = 0xcb; ops[2] = 0; /* JIS )  */
	    KOut(ops);
	    schix++;
	    continue;
	  }
	  if (skip) {
	    schix++;
	    continue;
	  }
	  if (cc < 128) {
	    /* non-Japanese, display it (fix up the MOKE "/") */
	    ops[0]= cc;
	    ops[1] = '\0';
	    if ((Dmode != 0) && (cc == '}')) {
	      ops[0] = ';';
	      if ((dbchar(schix+2) == 0x0a) && (ops[0] == ';')) ops[0] = '\0';
	    }
	    if ((Dmode != 0) && (cc == '{')) {
	      schix++;
	      continue;
	    }
	    if (ops[0] == '/') {
	      if (hit) {
		ops[0] = ';';
		ops[1] = ' ';
		ops[2] = '\0';
	      }
	      else {
		hit = TRUE;
		ops[0] = '\0';
	      }
	    }
	    if ((dbchar(schix+1) == 0x0a) && (ops[0] == ';')) ops[0] = '\0';
	    printf("%s",ops);
	  }
	  else {  /* kana or kanji  */
	    if (khi == 0) {
	      khi = cc;
	    }
	    else {
	      klo = cc;
	      ops[0] = khi ; ops[1] = klo ; ops[2] = 0;
	      KOut(ops);
	      khi = 0;
	      klo = 0;
	    }
	  }
	  schix++;
	}  /* end of line display loop  */
	printf("\n\r");
      }  /* of "once-per-line" test */
      else ldisp--;
      it++;
      if (it >= endtest) break;

#ifdef __AMIGA__
      /* increment correctly for long lines that wrap around */
      ldisp += AK_strlen(testline)/(AK_conUnit->cu_XMax - 1);
#endif

      if (ldisp++ == maxlines-1) {
	printf("Continue displaying matches? (y/n)");
	ops[0] = getchar();
	fflush(stdin);
	if ((ops[0] == 'y')||(ops[0] == 'Y')) {
	  printf("\n\r");
	  ldisp = 0;
	  continue;
	}
	else {
	  if ((ops[0] != 'n') && (ops[0] != 'N') && 
	      (ops[0] != 0x0a) && (ops[0] != 0x0d)) 
	    ungetc(ops[0],stdin);
	  return;
	}
      }
    }  /*  end of the "while it matches" loop  */
    if (!DispHit) printf("No display for this key (filtered or non-initial kanji)\n");
    if ((Dmode != 0) || (dind == 0)) return;
    printf("End of %d character matches. Continue for shorter matches? (y/n)",dind+1);
    ldisp = 0;
    ops[0] = getchar();
    fflush(stdin);
    if ((ops[0] == 'y')||(ops[0] == 'Y'))  {
      printf("\n\r");
      continue;
    }
    if ((ops[0] != 'n')&&(ops[0] != 'N')) {
      if ((ops[0] != 0x0a) && (ops[0] != 0x0d)) ungetc(ops[0],stdin);
    }
    break;
  }  /* end of the dind loop  */
}  /* end of lookup */

/*=====DoRADICALS===display Theresa's Radical File================*/

void DoRADICALS()
{
  
  int errf,i,j;
  unsigned char ops,rstr[20];
  
  fpr = fopen(Rname,"r");
  if (fpr == NULL) {
    printf("Sorry!, cannot open radicals.tm \n");
    return;
  }
  printf("\n RADICAL DISPLAY \n");
  fseek(stdin,0L,SEEK_END); /*kill any leftovers*/
  j = 0;
  while (TRUE) {
    errf = (fgets(rstr,19,fpr) == NULL);
    if (feof(fpr)||errf) {
      printf("\n");
      fseek(stdin,0L,SEEK_END); /*kill any leftovers*/
      return;
    }
    while(rstr[strlen(rstr)-1] < 0x20) rstr[strlen(rstr)-1] = 0;
    if ((rstr[strlen(rstr)-2]  == ' ')&&(rstr[strlen(rstr)-1]  == '0')) {
      i = 0;
      j+=2;
      if (j >= maxlines-1) {
	printf("\nContinue displaying radicals? (y/n)");
	ops = getchar();
	fflush(stdin);
	if ((ops == 'y')||(ops == 'Y')) {
	  j = 0;
          printf("\n");
	}
	else {
	  if ((ops != 'n') && (ops != 'N') && (ops != 0x0a) && (ops != 0x0d)) 
	    ungetc(ops,stdin);
	  return;
	}
      }
      if(rstr[0] > 127) {
	sprintf(tempout,"\n %c%c Stroke Radicals \n ",rstr[0],rstr[1]);
	KOut(tempout);
      }
      else {
	rstr[2] = 0;
	printf("\n %s Stroke Radicals \n ",rstr);
      }
      continue;
    }
    sprintf(tempout,"\t%s",rstr);
    KOut(tempout);
    i++;
    if (i == Radline) {
      i = 0;
      printf("\n ");
      j++;
      if (j >= maxlines-1) {
	printf("Continue displaying radicals? (y/n)");
	ops = getchar();
	fflush(stdin);
	if ((ops == 'y')||(ops == 'Y')) {
	  j = 0;
          printf("\n");
	}
	else {
	  if ((ops != 'n') && (ops != 'N') && (ops != 0x0a) && (ops != 0x0d)) 
	    ungetc(ops,stdin);
	  return;
	}
      }
    }
  }
}

/*=========DoJIS === JIS kanji lookup==========================================*/

void DoJIS()
{
  int i,ktf,sjf,i1,i2;
  unsigned char cj;
  
  ktf = FALSE;
  sjf = FALSE;
  cj = getchar();
  if (cj == '-') {
    ktf = TRUE;

#ifdef __AMIGA__
    printf("\r%s\r%sKUTEN:%s",ClrEOL,RVon,RVoff);
#else
    printf("\r                                      \r");
    printf("%sKUTEN:%s",RVon,RVoff);
#endif
  }
  else if ((cj == 's')||(cj == 'S')) {
    sjf = TRUE;

#ifdef __AMIGA__
    printf("\r%s\r%sSJIS:%s",ClrEOL,RVon,RVoff);
#else
    printf("\r                                      \r");
    printf("%sSJIS:%s",RVon,RVoff);
#endif
  }
  else {
    ungetc(cj,stdin);
    printf("%c",cj);
  }
  cbreakoff(); 
  scanf("%s",instr);
  cbreakon();
  fflush(stdin);
  if (ktf) {
    for (i = 0;i <4; i++) {
      if ((instr[i] >= '0') && (instr[i] <= '9'))instr[i] = instr[i] - '0';
    }
    instr[0] = (instr[0]*10+instr[1]+0x20) | 0x80;
    instr[1] = (instr[2]*10+instr[3]+0x20) | 0x80;
    instr[2] = 0;
  }
  else {
    for (i = 0;i <4; i++) {
      if ((instr[i]>='0') && (instr[i]<='9'))  instr[i] = instr[i] - '0';
      if ((instr[i]>='a') && (instr[i]<='f'))  instr[i] = instr[i]-'a'+0x0a;
      if ((instr[i]>='A') && (instr[i]<='F'))  instr[i] = instr[i]-'A'+0x0a;
    }
    if(sjf) {
      i1 = (instr[0] << 4) + instr[1];
      i2 = (instr[2] << 4) + instr[3];
      sjis2jis(&i1,&i2);
      instr[0] = i1 | 0x80;
      instr[1] = i2 | 0x80;
      instr[2] = 0;
    }
    else {
      instr[0] = ((instr[0] << 4) + instr[1]) | 0x80;
      instr[1] = ((instr[2] << 4) + instr[3]) | 0x80;
      instr[2] = 0;
    }
  }
  Dmode =1;
  strcpy(fbuff,instr);
  fseek(stdin,0L,SEEK_END); /*kill any leftovers*/
  Lookup();
  instr[0] = 0;
}

/*=====  DoKANJI === Kanji single lookup ======================*/

void DoKANJI()
{
  int escf,bit8,i;
  unsigned char c;
  
  escf = FALSE;
  bit8 = FALSE;
  c='x'; /*keep lint happy*/
  for (i = 0; (c != 0xd) && (c != 0xa); i++) {
    instr[i+1] = 0;
    c = getchar();
    if (!bit8 && !escf && ((c == '@') || (c == '#'))) {
      DoRomaji(c);
      break;
    }
    if (c == 0x1b) escf = TRUE;
    if (c > 0x7f) bit8 = TRUE;
    if ((c == 0x7f) || (c == 8)) {
      if(bit8) i--;
      if( i > 0) instr[--i] = 0;
      i--;
      strcpy(fbuff,instr);
      FixSJIS(fbuff);
#ifdef __AMIGA__
     printf("\r%s\r%sKANJI/KANA:%s",ClrEOL,RVon,RVoff);
#else
      printf("\r                                       \r");
      printf("%sKANJI/KANA:%s ",RVon,RVoff);
#endif
      KOut(fbuff);
      continue;
    }
    instr[i] = c;
    if (!escf) {
      if (!bit8) {
#ifdef __AMIGA__
        printf("\r%s\r%sKANJI/KANA:%s %s",ClrEOL,RVon,RVoff,instr);
#else
	printf("\r                                       \r");
	printf("%sKANJI/KANA:%s %s",RVon,RVoff,instr);
#endif
      }
      else {
	strcpy(fbuff,instr);
	if ((strlen(fbuff) % 2) > 0) fbuff[strlen(fbuff)-1] = 0;
#ifdef __AMIGA__
        printf("\r%s\r%sKANJI/KANA:%s",ClrEOL,RVon,RVoff);
#else
	printf("\r                                       \r");
	printf("%sKANJI/KANA:%s ",RVon,RVoff);
#endif
	FixSJIS(fbuff);
	KOut(fbuff);
      }
    }
    if ((instr[i] == 'B')&&(instr[i-1] == '(')&&(instr[i-2] == 0x1b)) break;
  }
  fseek(stdin,0L,SEEK_END); /*kill any leftovers*/
  printf("\n\r");
  fflush(stdin);
  GetEUC(fbuff);
  Dmode =1;
  Lookup();
  instr[0] = 0;
}
/*===togglemode===alternate between kanji compound modes===============*/
void togglemode()
{
  FirstKanj = (FirstKanj+1) % 2;
  printf("Display All Kanji Mode: %s\n",kmodes[FirstKanj]);
}

/*====Verbtoggle=== alternate between deinflection on/off===============*/
void Verbtoggle()
{
  if (Jverb) {
    Jverb = FALSE;
    printf("Verb deinflection is now OFF\n");
  }
  else {
    Jverb = TRUE; 
    printf("Verb deinflection is now ON\n");
  }
  
}
/*=====xjdicrc - access and analyze "xjdicrc" file (if any)==============*/
void xjdicrc()
{
  unsigned char xjdicdir[128],rcstr[80],*rcwd;
  int ft,fn;
  FILE *fm,*fopen();
  
  xjdicdir[0] = '\0';
  if (strlen(ENVname) > 2) {
    strcpy(xjdicdir,ENVname);
    strcat(xjdicdir,"/");
  }
  else {
#ifdef __AMIGA__
    strcpy(xjdicdir,"S:");
#else
    strcpy(xjdicdir,getenv("HOME"));
    strcat(xjdicdir,"/");
#endif
  }
  
  strcat(xjdicdir,".xjdicrc");
  fm = fopen(xjdicdir,"r");
  if (fm == NULL) {
    strcpy(xjdicdir,".xjdicrc");
    fm = fopen(xjdicdir,"r");
  }
  if (fm != NULL) {
    while(fgets(rcstr,79,fm) != NULL) {
      rcwd = (unsigned char *)strtok(rcstr," \t");
      if (stringcomp((unsigned char *)"omode",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	rcwd[0] = rcwd[0] | 0x20;
	if(rcwd[0] == 'j') Omode = 0;
	if(rcwd[0] == 'e') Omode = 1;
	if(rcwd[0] == 's') Omode = 2;
	continue;
      }
      if (stringcomp((unsigned char *)"dicfile",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	strcpy(Dname,rcwd);
	strcpy(JDXname,rcwd);
	strcat(JDXname,".xjdx");
	continue;
      }
      if (stringcomp((unsigned char *)"kdicfile",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	strcpy(KDname,rcwd);
	strcpy(KJDXname,rcwd);
	strcat(KJDXname,".xjdx");
	continue;
      }
      if (stringcomp((unsigned char *)"radfile",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	strcpy(Rname,rcwd);
	continue;
      }
      if (stringcomp((unsigned char *)"verbfile",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	strcpy(Vname,rcwd);
	continue;
      }
      if (stringcomp((unsigned char *)"lines",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	maxlines = atoi(rcwd);
	if(maxlines < 5) maxlines = 5;
	continue;
      }
      if (stringcomp((unsigned char *)"radlines",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	Radline = atoi(rcwd);
	if(Radline < 5) Radline = 5;
	continue;
      }
      if (stringcomp((unsigned char *)"romfile",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	strcpy(ROMname,rcwd);
	continue;
      }
      if (stringcomp((unsigned char *)"jverb",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	if(stringcomp(rcwd,(unsigned char *)"on") == 0) Jverb = TRUE;
	if(stringcomp(rcwd,(unsigned char *)"off") == 0) Jverb = FALSE;
	continue;
      }
      if (stringcomp((unsigned char *)"filt",rcwd) == 0) {
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	sscanf(rcwd,"%d",&fn);
	if ((fn < 0)||(fn > NOFILT)) continue;
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	sscanf(rcwd,"%d",&ft);
	if (ft > 2) continue;
	filttype[fn] = ft;
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	filton[fn] = FALSE;
	if(stringcomp((unsigned char *)"on",rcwd) == 0) {
	  filton[fn] = TRUE;
	  nofilts  = TRUE;
	}
	rcwd = (unsigned char *)strtok(NULL,"\"");
	strcpy(filtnames[fn],rcwd);
	ft=0;
	rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	while(rcwd != NULL) {
	  strcpy(filtcodes[fn][ft],rcwd);
	  ft++;
	  rcwd = (unsigned char *)strtok(NULL," \t\f\r\n");
	}
	if(ft==0)continue;
	filtcoden[fn] = ft;
	filtact[fn] = TRUE;
	continue;
      }
    }
  }
  fclose(fm);
}

/*=== FiltSet=== turn filters on & off==============================*/
void FiltSet()
{
  unsigned char c,fff[10];
  int anyfilt,j,k;
  
  anyfilt = FALSE;
  printf("%sFilter Setting%s\n",RVon,RVoff);
  for(j = 0;j < NOFILT;j++) {
    if(!filtact[j])continue;
    anyfilt = TRUE;
    strcpy(fff,"OFF");
    if(filton[j])strcpy(fff,"ON ");
    printf("No: %d Type: %d Status: %s Name: %s\n",
	   j,filttype[j],fff,filtnames[j]);
  }
  if (!anyfilt) {
    printf("No filters are loaded!\n");
    return;
  }
  printf("Modify which Filter?\n");
  c = getchar();
  if ((c ==  0x1b)||(c == 0xa)||(c == 0xd)) return;
  k = c-'0';
  if ((k <0)||(k >NOFILT)) {
    printf("INVALID!\n");
    return;
  }
  if (!filtact[k]) {
    printf("Filter %c is not active!\n",c);
    return;
  }
  printf("Filter %c OFF (0) or ON (1)\n",c);
  c = getchar();
  if ((c != '0') && (c != '1'))return;
  if(c == '0') {
    filton[k] = FALSE;
    printf("Filter %d Turned OFF\n",k);
  }
  if(c == '1') {
    filton[k] = TRUE;
    printf("Filter %d Turned ON\n",k);
  }
  nofilts = FALSE;
  for(j = 0;j < NOFILT;j++)if(filton[j])nofilts=TRUE;
  return;
}

/*                  M A I N                                      */
int main(argc,argv)
int argc;
unsigned char **argv;
{
  int i,ip,cmdmode,bit8,escf;
  unsigned char *dicenv,strtmp[50];
  unsigned char c;
  unsigned char xap[50];
  SB_bufferset *buffers = NULL;

  printf("XJDIC (Japanese Dictionary) Copyright J.W.Breen 1993.\n");
  printf("Verson %s by Roger Ang, Oct. '95\n", sver);

  for (i=0;i<NOFILT;i++) {
    filtact[i] = FALSE;
    filton[i] = FALSE;
  }
  dicenv = (unsigned char *)getenv("XJDIC");
  if (!dicenv) dicenv = (unsigned char *)DEFAULT_DICDIR;
  if (strlen(dicenv) <= 2) dicenv = (unsigned char *)getenv("PWD");
  strcpy (ENVname,dicenv);

  if (strlen(ENVname) > 0) {
    sprintf(Rname, "%s/%s", dicenv, IRname);
    sprintf(Dname, "%s/%s", dicenv, IDname);
    sprintf(Vname, "%s/%s", dicenv, IVname);
    sprintf(KDname, "%s/%s", dicenv, IKDname);
    sprintf(JDXname, "%s/%s", dicenv, IJDXname);
    sprintf(ROMname, "%s/%s", dicenv, IROMname);
    sprintf(KJDXname, "%s/%s", dicenv, IKJDXname);
  }

  xjdicrc();
  /* process command-line options*/
  if (argc > 1) {
    for (i = 1; i < argc; i++) {
      strcpy(xap,argv[i]);
      if ((xap[0] == '-') && (xap[1] == 'm'))
	save_mem = 1;
      if ((xap[0] == '-') && (xap[1] == 'j')) {
	if(xap[2] != 0)	{
	  strcpy(strtmp,xap+2);
	}
	else {
	  i++;
	  strcpy(xap,argv[i]);
	  strcpy (strtmp,xap);
	}
	if (strtmp[0] == 'j') {
	  Omode = 0;
	  printf("Output mode set to JIS\n");
	}
	if (strtmp[0] == 's') {
	  Omode = 2;
	  printf("Output mode set to Shift-JIS\n");
	}
	if (strtmp[0] == 'e') {
	  Omode = 1;
	  printf("Output mode set to EUC\n");
	}
	continue;
      }
      if ((xap[0] == '-') && (xap[1] == 'l')) {
	if(xap[2] != 0)	{
	  strcpy(strtmp,xap+2);
	}
	else {
	  i++;
	  strcpy(xap,argv[i]);
	  strcpy (strtmp,xap);
	}
	maxlines = atoi(strtmp);
	if(maxlines < 5) maxlines = 5;
	printf("Setting lines per display to %d\n",maxlines);
	continue;
      }
      if ((xap[0] == '-') && (xap[1] == 'd')) {
	if(xap[2] != 0)	{
	  strcpy(strtmp,xap+2);
	}
	else {
	  i++;
	  strcpy(xap,argv[i]);
	  strcpy (strtmp,xap);
	}
	strcpy (Dname,strtmp);
	strcpy (JDXname,strtmp);
	strcat (JDXname,".xjdx");
	printf("Command-line request to use dictionary files: %s and %s\n",
	       Dname,JDXname);
	continue;
      }
      if ((xap[0] == '-') && (xap[1] == 'k')) {
	if(xap[2] != 0) {
	  strcpy(strtmp,xap+2);
	}
	else {
	  i++;
	  strcpy(xap,argv[i]);
	  strcpy (strtmp,xap);
	}
	strcpy (KDname,strtmp);
	strcpy (KJDXname,strtmp);
	strcat (KJDXname,".xjdx");
	printf("Command-line request to use kanji dictionary files: %s and %s\n",Dname,JDXname);
	continue;
      }
      if ((xap[0] == '-') && (xap[1] == 'v')) {
	Jverb = FALSE;
	printf("Verb deinflection turned OFF\n");
      }
      if ((xap[0] == '-') && (xap[1] == 'h')) {
	printf("\nUsage: %s <options>\n\nwhere options are:\n\n", argv[0]);
	printf("   -d dictionary file_path\n");
	printf("   -h this information\n");
	printf("   -j x (where x is Output code: e = EUC, s = Shift-JIS, j  = JIS)\n");
	printf("   -k kanji-dictionary file_path\n");
	printf("   -l nn (where nn is lines per display)\n");
	printf("   -m buffer files in memory.\n");
	printf("   -v disable verb function\n");
	printf("\nSee xjdic.man for full information\n");
	exit_err = 0;
	exit(0);
      }
    }
  }

#ifdef __AMIGA__
  /* initialize my kanji stuff */
  printf("Loading fonts.  Please wait...\n");
  if (AK_init(NULL, 16, save_mem) == -1)
    exit(1);

#if LATTICE
  if (onexit(&my_exit))
    printf("Problem setting exit trap...\n");
#else
  if (atexit(&my_exit))
    printf("Problem setting exit trap...\n");
#endif
#endif

  printf ("Loading Dictionary and Index files.  Please wait.....\n");
  Verbinit();
  DicSet();
  LoadKana();
  togglemode();

  printf("\n(Enter ? for a summary of operating instructions)\n");
  cbreakon();
  
  while (TRUE) {
    printf("\n\r%sXJDIC SEARCH KEY:%s ",RVon,RVoff);
    c = 0;
    cmdmode = FALSE;
    strf = FALSE;
    escf = FALSE;
    bit8 = FALSE;
    for (i = 0; (c != 0xd) && (c != 0xa); i++) {
      instr[i+1] = 0;
      c = getchar();
      if (c == 0x1b) escf = TRUE;
      if (c > 0x7f) bit8 = TRUE;  /* assume a string of EUC kanji */
      
      /* ELI (stop on ^Z) */
      if (c == 26)  {
#ifdef __AMIGA__
	cbreakoff();
	exit_err = 0;
        exit(0);
#else
	cbreakoff();
	kill (getpid(), SIGTSTP);
	cbreakon();
#endif
	break;
      }
      if (!bit8 && !escf && ((c == '@') || (c == '#'))) {
	DoRomaji(c);
	break;
      }
      if ((c == '?') && (!escf) && (!bit8)) {
	cbreakoff(); 
	for (ip = 0; strcmp(Help[ip],"$$$")!=0;ip++)  printf("%s",Help[ip]);
	cbreakon(); 
	break;
      }
      if (!escf && !bit8 && ((c == '/') || (c == ':') || 
	   (c == ';') || (c == '\\'))) {
	cmdmode = TRUE; 
	break;
      }
      if ((c == 0x7f) || (c == 8)) {
        /* backspace or delete */
#ifdef __AMIGA__
/*	printf("\r%s\r%sXJDIC SEARCH KEY:%s ",ClrEOL,RVon,RVoff); ***/
        if (!bit8) {
          if (i > 0)  printf("\b \b");
	}
        else {
	  if (i > 1)  printf("\b\b  \b\b");
	}
#endif
	if (bit8) i--;
	if ( i > 0) instr[--i] = 0;
	i--;  /* to counter act 'for' increment */

#ifndef __AMIGA__
	strcpy(fbuff,instr);
	FixSJIS(fbuff);
	printf("\r                                       \r");
	printf("%sXJDIC SEARCH KEY:%s ",RVon,RVoff);
	KOut(fbuff);
#endif
	continue;
      }
      instr[i] = c;
      /*if (!escf)  printf("%c",c);*/
      if (!escf) {
	if (!bit8) {  /* print a normal character */
#ifdef __AMIGA__
          putchar(c);
#else
	  printf("\r					 \r");
	  printf("%sXJDIC SEARCH KEY:%s %s",RVon,RVoff,instr);
#endif
	}
	else {
	  strcpy(fbuff,instr);
	  if ((strlen(fbuff) % 2) > 0) fbuff[strlen(fbuff)-1] = 0;

#ifdef __AMIGA__
	  printf("\r%s\r%sXJDIC SEARCH KEY:%s ",ClrEOL,RVon,RVoff);
#else
	  printf("\r					 \r");
	  printf("%sXJDIC SEARCH KEY:%s ",RVon,RVoff);
#endif
	  FixSJIS(fbuff);
	  KOut(fbuff);
	}
      }
      if ((instr[i] == 'B')&&(instr[i-1] == '(')&&(instr[i-2] == 0x1b)) break;
    }
    fseek(stdin,0L,SEEK_END); /* kill any leftovers*/
    if ((instr[2] == 'e')&&(instr[1] == 'y')&&(instr[0] == 'b')) {
      cbreakoff();
      exit_err = 0;
      exit(0);
    }
    if(cmdmode) {
      if (c == '/') {
#ifdef __AMIGA__
	printf("\r%s\r",ClrEOL);
#else
	printf("\r                                      \r");
#endif
	togglemode();
	continue;
      }
      if (c == ';') {
#ifdef __AMIGA__
	printf("\r%s\r",ClrEOL);
#else
	printf("\r                                      \r");
#endif
	FiltSet();
	continue;
      }
      if (c == ':') {
#ifdef __AMIGA__
	printf("\r%s\r",ClrEOL);
#else
	printf("\r                                      \r");
#endif
	Verbtoggle();
	continue;
      }
#ifdef __AMIGA__
      printf("\r%s\r%sKANJI LOOKUP TYPE:%s ",ClrEOL,RVon,RVoff);
#else
      printf("\r                                      \r");
      printf("%sKANJI LOOKUP TYPE:%s ",RVon,RVoff);
#endif
      c = getchar();

      switch (c) {
      case 'c' :
      case 'C' :	
#ifdef __AMIGA__
        printf("\r%s\r",ClrEOL);
#else
	printf("\r                                      \r");
#endif
	printf("%sINDEX CODE:%s",RVon,RVoff);
	cbreakoff();
	scanf("%s",instr);
	cbreakon(); 
	fflush(stdin);
	Dmode =1;
	strcpy(fbuff,instr);
	strcat(fbuff," ");
	fseek(stdin,0L,SEEK_END); /*kill any leftovers*/
	if ((instr[0] | 0x20) == 'b') {
#ifdef __AMIGA__
	  printf("\r%s\r",ClrEOL);
#else
	  printf("\r                                      \r");
#endif
	  printf("%sSTROKE COUNT (0 selects all):%s",RVon,RVoff);
	  cbreakoff(); 
	  gets(instr);
	  i = atoi(instr);
	  sprintf(strfilt,"S%d",i);
	  cbreakon();
	  fflush(stdin);
	  fseek(stdin,0L,SEEK_END); /*kill any leftovers*/
	  strf = TRUE;
	  if (atoi(strfilt+1) == 0) strf = FALSE;
	}
	Lookup();
	instr[0] = 0;
	break;
      case 'm' :
      case 'M' :
#ifdef __AMIGA__
        printf("\r%s\r",ClrEOL);
#else
	printf("\r                                      \r");
#endif
	printf("%sMEANING:%s",RVon,RVoff);
	cbreakoff();
	scanf("%s",instr);
	cbreakon(); 
	fflush(stdin);
	Dmode =1;
	strcpy(fbuff,instr);
	fseek(stdin,0L,SEEK_END); /*kill any leftovers*/
	Lookup();
	instr[0] = 0;
	break;
      case 'j' :
      case 'J' :
#ifdef __AMIGA__
        printf("\r%s\r",ClrEOL);
#else
	printf("\r                                      \r");
#endif
	printf("%sJIS CODE:%s",RVon,RVoff);
	DoJIS();
	break;
      case 'r' :
      case 'R' :
	DoRADICALS();
	break;
      case 'k' :
      case 'K' :
	DoKANJI();
	break;
      default:
	ungetc(c,stdin);
	DoKANJI();
	break;
      }
    }
    if(strlen(instr) < 2) continue;
    GetEUC(fbuff);
    if (escf) KOut(fbuff);
    sprintf(tempout,"\nSearching for: %s%s%s\n",RVon,fbuff,RVoff);
    KOut(tempout);
    Dmode = 0;
    Lookup();
  }

  /* clean up buffers */
  freeall_SBuffers();                                        
  while (SB_global_bufferset) {                              
    buffers = SB_global_bufferset;
    SB_global_bufferset = 
      SB_bufferset_remove(SB_global_bufferset, buffers);
    SB_bufferset_delete(buffers);  
  }
}
