//<copyright>
//
// Copyright (c) 1996
// Institute for Information Processing and Computer Supported New Media (IICM),
// Graz University of Technology, Austria.
//
//</copyright>

//<file>
//
// Name:    japanconvertwizard.C
//
// Purpose: Convert from and to Shift-JIS, EUC, New-JIS, Old-JIS, and NEC_JIS-JIS
//
// Created: 10 Sep 1996 Juergen Schipflinger
//
// $Id: japanconvertwizard.C,v 1.4 1997/01/13 14:09:00 jschipf Exp $
//
// Description:
//
//</file>
//
/*
 * $Log: japanconvertwizard.C,v $
 * Revision 1.4  1997/01/13 14:09:00  jschipf
 * clear istream after codedetection
 *
 * Revision 1.3  1996/12/11 16:27:15  jschipf
 * some casts for msdev
 *
 * Revision 1.2  1996/10/03 15:57:52  jfasch
 * dont know
 *
 * Revision 1.1  1996/09/11 07:11:56  jfasch
 * Initial revision
 *
*/

#include "japanconvertwizard.h"
#include <stdio.h>
#include <iostream.h>

static char rcsid[] = "$Id: japanconvertwizard.C,v 1.4 1997/01/13 14:09:00 jschipf Exp $";
inline void printRCSInfo() { printf("RCSInfo: %s",rcsid); }


#ifdef THINK_C
#include <console.h>
#include <stdlib.h>
#endif
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifndef THINK_C
#include <errno.h>
#endif

#define INPUT       (unsigned char)1
#define OUTPUT      (unsigned char)2
#define REPAIR      (unsigned char)3
#define NUL         (unsigned char)0
#define NL          (unsigned char)10
#define CR          (unsigned char)13
#define ESC         (unsigned char)27
#define SS2         (unsigned char)142
#define PERIOD      (unsigned char)'.'
#define SJIS1(A)    ((A >= 129 && A <= 159) || (A >= 224 && A <= 239))
#define SJIS2(A)    (A >= 64 && A <= 252)
#define HANKATA(A)  (A >= 161 && A <= 223)
#define ISEUC(A)    (A >= 161 && A <= 254)
#define ISMARU(A)   (A >= 202 && A <= 206)
#define ISNIGORI(A) ((A >= 182 && A <= 196) || (A >= 202 && A <= 206) || (A == 179))
#ifndef SEEK_CUR
#define SEEK_CUR    1
#endif
/* The following 8 lines of code are used to establish the default output codes
 * when using the "-o[CODE]" or "-r[CODE]" options. They are self-explanatory,
 * and easy to change.
 */
#define DEFAULT_O   SJIS     /* default output code for "-o[CODE]" option */
#define DEFAULT_OS  ".sjs"   /* default file extension for "-o[CODE]" option */
#define DEFAULT_OKI ""       /* default kanji-in code for "-o[CODE]" option */
#define DEFAULT_OKO ""       /* default kanji-out code for "-o[CODE]" option */
#define DEFAULT_R   NEW      /* default output code for "-r[CODE]" option */
#define DEFAULT_RS  ".new"   /* default file extension for "-r[CODE]" option */
#define DEFAULT_RKI "$B"     /* default kanji-in code for "-r[CODE]" option */
#define DEFAULT_RKO "(J"     /* default kanji-out code for "-r[CODE]" option */

// void han2zen(FILE *in,int *p1,int *p2,int incode);
// void sjis2jis(int *p1,int *p2);
// void jis2sjis(int *p1,int *p2);
// void shift2seven(FILE *in,FILE *out,int incode,char ki[],char ko[]);
// void shift2euc(FILE *in,FILE *out,int incode,int tofullsize);
// void euc2seven(FILE *in,FILE *out,int incode,char ki[],char ko[]);
// void euc2euc(FILE *in,FILE *out,int incode,int tofullsize);
// void shift2shift(FILE *in,FILE *out,int incode,int tofullsize);
// void euc2shift(FILE *in,FILE *out,int incode,int tofullsize);
// void seven2shift(FILE *in,FILE *out);
// void seven2euc(FILE *in,FILE *out);
// void seven2seven(FILE *in,FILE *out,char ki[],char ko[]);
// void dohelp(char toolname[]);
// void dojistable(void);
// void doeuctable(void);
// void dosjistable(void);
// void jisrepair(FILE *in,FILE *out,int verbose,int outcode,char ki[],char ko[]);
// void removeescape(FILE *in,FILE *out,int verbose,int forcedelesc);
// void printcode(int code);
// int toup(int data);
// int SkipESCSeq(FILE *in,int temp,int *intwobyte);
// int DetectCodeType(FILE *in);
// int getcode(char extension[],int data,char ki[],char ko[],int doing);
#ifdef THINK_C
int ccommand(char ***p);
#endif

//----------------- JapanConvertWizard::JapanConvertWizard -----------------------
JapanConvertWizard::JapanConvertWizard(istream* in,bool destroy)
{
  instream_=in;
  destroyInstream_=destroy;
  outstream_=0;
  incode_=JapanConvertWizard::NOT_SET;
  outcode_=JapanConvertWizard::NOT_SET;
  forceHTFWK_=false;
}

//----------------- JapanConvertWizard::~JapanConvertWizard ----------------------
JapanConvertWizard::~JapanConvertWizard()
{
  if (destroyInstream_)
    delete instream_;
}

//----------------- JapanConvertWizard::DetectCodeType --------------------------
JapanConvertWizard::Coding JapanConvertWizard::detectCodeType()
{
  if (!instream_) return JapanConvertWizard::ASCII;
  int c = 0;
  JapanConvertWizard::Coding whatcode = JapanConvertWizard::ASCII;

  while ((whatcode == JapanConvertWizard::EUC_OR_SJIS ||
    whatcode == JapanConvertWizard::ASCII) && c != EOF) {
    if ((c = instream_->get()) != EOF) {
      if (c == ESC) {
        c = instream_->get();
        if (c == '$') {
          c = instream_->get();
          if (c == 'B')
            whatcode = JapanConvertWizard::NEW_JIS;
          else if (c == '@')
            whatcode = JapanConvertWizard::OLD_JIS;
        }
        else if (c == 'K')
          whatcode = JapanConvertWizard::NEC_JIS;
      }
      else if ((c >= 129 && c <= 141) || (c >= 143 && c <= 159))
        whatcode = JapanConvertWizard::SHIFT_JIS;
      else if (c == SS2) {
        c = instream_->get();
        if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160) || (c >= 224 && c <= 252))
          whatcode = JapanConvertWizard::SHIFT_JIS;
        else if (c >= 161 && c <= 223)
          whatcode = JapanConvertWizard::EUC_OR_SJIS;
      }
      else if (c >= 161 && c <= 223) {
        c = instream_->get();
        if (c >= 240 && c <= 254)
          whatcode = JapanConvertWizard::EUC;
        else if (c >= 161 && c <= 223)
          whatcode = JapanConvertWizard::EUC_OR_SJIS;
        else if (c >= 224 && c <= 239) {
          whatcode = JapanConvertWizard::EUC_OR_SJIS;
          while (c >= 64 && c != EOF && whatcode == JapanConvertWizard::EUC_OR_SJIS) {
            if (c >= 129) {
              if (c <= 141 || (c >= 143 && c <= 159))
                whatcode = JapanConvertWizard::SHIFT_JIS;
              else if (c >= 253 && c <= 254)
                whatcode = JapanConvertWizard::EUC;
            }
            c = instream_->get();
          }
        }
        else if (c <= 159)
          whatcode = JapanConvertWizard::SHIFT_JIS;
      }
      else if (c >= 240 && c <= 254)
        whatcode = JapanConvertWizard::EUC;
      else if (c >= 224 && c <= 239) {
        c = instream_->get();
        if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160))
          whatcode = JapanConvertWizard::SHIFT_JIS;
        else if (c >= 253 && c <= 254)
          whatcode = JapanConvertWizard::EUC;
        else if (c >= 161 && c <= 252)
          whatcode = JapanConvertWizard::EUC_OR_SJIS;
      }
    }
  }
  return whatcode;
}

//----------------- JapanConvertWizard::convert ---------------------------------
JapanConvertWizard::Coding JapanConvertWizard::convert(ostream* ostr)
{
  outstream_=ostr;
  if (!instream_ || !outstream_) return JapanConvertWizard::NOT_SET;
  setESC(); // set escape chars for convert
  // if outcode_ is NOT_SET outcode_ is set SHIFT_JIS
  if (incode_==JapanConvertWizard::NOT_SET || incode_==JapanConvertWizard::AUTO_DETECT)
  {
    incode_=detectCodeType();
    instream_->clear();
    instream_->seekg(0);
  }
  switch (incode_) {
    case JapanConvertWizard::NOT_SET :
      return JapanConvertWizard::NOT_SET;
    case JapanConvertWizard::EUC_OR_SJIS :
      return JapanConvertWizard::NOT_SET;
      // Ambiguous (Shift-JIS or EUC) input code!
    case JapanConvertWizard::ASCII :
      return JapanConvertWizard::NOT_SET;
      // Since detected input code is ASCII, it may be damaged New- or Old-JIS
      // Try repair
    case JapanConvertWizard::NEW_JIS :
    case JapanConvertWizard::OLD_JIS :
    case JapanConvertWizard::NEC_JIS :
      switch (outcode_) {
        case JapanConvertWizard::NEW_JIS :
        case JapanConvertWizard::OLD_JIS :
        case JapanConvertWizard::NEC_JIS :
          seven2seven();
          break;
        case JapanConvertWizard::EUC :
          seven2euc();
          break;
        case JapanConvertWizard::SHIFT_JIS :
          seven2shift();
          break;
        default:
        {
          return JapanConvertWizard::NOT_SET;
        }
      }
      break;
    case JapanConvertWizard::EUC :
      switch (outcode_) {
        case JapanConvertWizard::NEW_JIS :
        case JapanConvertWizard::OLD_JIS :
        case JapanConvertWizard::NEC_JIS :
          euc2seven();
          break;
        case JapanConvertWizard::EUC :
          euc2euc();
          break;
        case JapanConvertWizard::SHIFT_JIS :
          euc2shift();
          break;
        default:
        {
          return JapanConvertWizard::NOT_SET;
        }
      }
      break;
    case JapanConvertWizard::SHIFT_JIS :
      switch (outcode_) {
        case JapanConvertWizard::NEW_JIS :
        case JapanConvertWizard::OLD_JIS :
        case JapanConvertWizard::NEC_JIS :
          shift2seven();
          break;
        case JapanConvertWizard::EUC :
          shift2euc();
          break;
        case JapanConvertWizard::SHIFT_JIS :
          shift2shift();
          break;
        default:
        {
          return JapanConvertWizard::NOT_SET;
        }
      }
      break;
    default:
    {
      return JapanConvertWizard::NOT_SET;
    }
  }
  return JapanConvertWizard::outcode_;
}

//----------------- JapanConvertWizard::removeESCChars -------------------------
JapanConvertWizard::Coding JapanConvertWizard::removeESCChars(ostream*)
{
  return JapanConvertWizard::ASCII;
}

//----------------- JapanConvertWizard::repairESCChars ------------------------
JapanConvertWizard::Coding JapanConvertWizard::repairESCChars(ostream*)
{
  if (incode_==JapanConvertWizard::NOT_SET || incode_==JapanConvertWizard::AUTO_DETECT)
  {
    incode_=detectCodeType();
  }
  return JapanConvertWizard::ASCII;
}

//----------------- JapanConvertWizard::getCodeName --------------------------
RString JapanConvertWizard::getCodeName(Coding code)const
{
  switch (code) {
    case JapanConvertWizard::OLD_JIS :
      return "Old-JIS";
      break;
    case JapanConvertWizard::NEW_JIS :
      return "New-JIS";
      break;
    case JapanConvertWizard::NEC_JIS :
      return "NEC-JIS";
      break;
    case JapanConvertWizard::EUC :
      return "EUC";
      break;
    case JapanConvertWizard::SHIFT_JIS :
      return "Shift-JIS";
      break;
    case JapanConvertWizard::EUC_OR_SJIS :
      return "ambiguous (Shift-JIS or EUC)";
      break;
    case JapanConvertWizard::ASCII :
      return "ASCII (no Japanese)";
      break;
    case JapanConvertWizard::NOT_SET :
    case JapanConvertWizard::AUTO_DETECT :
      return "unknown";
      break;
    default :
      return "unknown";
  }
}

//----------------- JapanConvertWizard::setESC -------------------------------
void JapanConvertWizard::setESC(bool repair)
{
  if (outcode_ == JapanConvertWizard::EUC) {
  }
  else if (outcode_ == JapanConvertWizard::SHIFT_JIS) {
  }
  else if (outcode_ == JapanConvertWizard::NEW_JIS) {
    strcpy(ki_,"$B");
    strcpy(ko_,"(J");
  }
  else if (outcode_ == JapanConvertWizard::OLD_JIS) {
    strcpy(ki_,"$@");
    strcpy(ko_,"(J");
  }
  else if (outcode_ == JapanConvertWizard::NEC_JIS) {
    strcpy(ki_,"K");
    strcpy(ko_,"H");
  }
  else {
    if (!repair) {
      strcpy(ki_,DEFAULT_OKI);
      strcpy(ko_,DEFAULT_OKO);
      outcode_ = JapanConvertWizard::SHIFT_JIS;
    }
    else {
      strcpy(ki_,DEFAULT_RKI);
      strcpy(ko_,DEFAULT_RKO);
    }
  }
}

//------------------- JapanConvertWizard::skipESCSeq -----------------------------
bool JapanConvertWizard::skipESCSeq(int temp,bool& intwobyte)
{
  bool tempdata = intwobyte;

  if (temp == '$' || temp == '(')
    instream_->get();
  if (temp == 'K' || temp == '$')
    intwobyte = true;
  else
    intwobyte = false;
  return (tempdata == intwobyte);
}

//----------------- JapanConvertWizard::jis2sjis -----------------------------
void JapanConvertWizard::jis2sjis(int& p1, int&p2)
{
  unsigned char c1 = p1;
  unsigned char c2 = p2;
  int rowOffset = c1 < 95 ? 112 : 176;
  int cellOffset = c1 % 2 ? (c2 > 95 ? 32 : 31) : 126;

  p1 = ((c1 + 1) >> 1) + rowOffset;
  p2 += cellOffset;
}

//---------------- JapanConvertWizard::sjis2jis -----------------------------
void JapanConvertWizard::sjis2jis(int &p1, int &p2)
{
  unsigned char c1 = p1;
  unsigned char c2 = p2;
  int adjust = c2 < 159;
  int rowOffset = c1 < 160 ? 112 : 176;
  int cellOffset = adjust ? (c2 > 127 ? 32 : 31) : 126;

  p1 = ((c1 - rowOffset) << 1) - adjust;
  p2 -= cellOffset;
}


//----------------- JapanConvertWizard::seven2seven () -----------------------
void JapanConvertWizard::seven2seven()
{
  int temp;
  int p1;
  int p2;
  bool change;
  bool intwobyte = false;

  while ((p1 = instream_->get()) != EOF) {
    if (p1 == ESC) {
      temp = instream_->get();
      change = skipESCSeq(temp,intwobyte);
      if ((intwobyte) && (change)){
        outstream_->put(ESC);*outstream_ << ki_;
      //        fprintf(out,"%c%s",ESC,ki);
      }
      else if (change){
        outstream_->put(ESC);*outstream_ << ko_;
      //        fprintf(out,"%c%s",ESC,ko);
      }
    }
    else if (p1 == NL || p1 == CR) {
      if (intwobyte) {
        intwobyte = false;
        outstream_->put(ESC);*outstream_ << ko_;
        //        fprintf(out,"%c%s",ESC,ko);
      }
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
    else {
      if (intwobyte) {
        p2 = instream_->get();
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
      else
      {
        outstream_->put((unsigned char)p1);
      //        fprintf(out,"%c",p1);
      }
    }
  }
  if (intwobyte)
  {
    outstream_->put(ESC);*outstream_ << ko_;
    //    fprintf(out,"%c%s",ESC,ko);
  }
}

//----------------- JapanConvertWizard::seven2euc ----------------------------
void JapanConvertWizard::seven2euc()
{
  int temp;
  int p1;
  int p2;
  bool intwobyte = false;

  while ((p1 = instream_->get()) != EOF) {
    if (p1 == ESC) {
      temp = instream_->get();
      skipESCSeq(temp,intwobyte);
    }
    else if (p1 == NL || p1 == CR) {
      if (intwobyte)
        intwobyte = false;
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
    else {
      if (intwobyte) {
        p2 = instream_->get();
        p1 += 128;
        p2 += 128;
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
      else
      {
        outstream_->put((unsigned char)p1);
        //        fprintf(out,"%c",p1);
      }
    }
  }
}

//------------------ JapanConvertWizard::seven2shift ------------------------------
void JapanConvertWizard::seven2shift()
{
  int temp;
  int p1;
  int p2;
  bool intwobyte = false;

  while ((p1 = instream_->get()) != EOF) {
    if (p1 == ESC) {
      temp = instream_->get();
      skipESCSeq(temp,intwobyte);
    }
    else if (p1 == NL || p1 == CR) {
      if (intwobyte)
        intwobyte = false;
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
    else {
      if (intwobyte) {
        p2 = instream_->get();
        jis2sjis(p1,p2);
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
      else
      {
        outstream_->put((unsigned char)p1);
        //        fprintf(out,"%c",p1);
      }
    }
  }
}

//-------------- JapanConvertWizard::euc2seven --------------------------
void JapanConvertWizard::euc2seven()
{
  int p1,p2;
  bool intwobyte = false;

  while ((p1 = instream_->get()) != EOF) {
    if (p1 == NL || p1 == CR) {
      if (intwobyte) {
        intwobyte = false;
        outstream_->put(ESC);*outstream_ << ko_;
        //        fprintf(out,"%c%s",ESC,ko);
      }
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
    else {
      if (ISEUC(p1)) {
        p2 = instream_->get();
        if (ISEUC(p2)) {
          p1 -= 128;
          p2 -= 128;
          if (!intwobyte) {
            intwobyte = true;
            outstream_->put(ESC);*outstream_ << ki_;
            //            fprintf(out,"%c%s",ESC,ki);
          }
        }
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
      else if (p1 == SS2) {
        p2 = instream_->get();
        if (HANKATA(p2)) {
          p1 = p2;
          han2zen(p1,p2);
          sjis2jis(p1,p2);
          if (!intwobyte) {
            intwobyte = true;
            outstream_->put(ESC);*outstream_ << ki_;
            //            fprintf(out,"%c%s",ESC,ki);
          }
        }
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
      else {
        if (intwobyte) {
          intwobyte = false;
          outstream_->put(ESC);*outstream_ << ko_;
          //          fprintf(out,"%c%s",ESC,ko);
        }
        outstream_->put((unsigned char)p1);
        //        fprintf(out,"%c",p1);
      }
    }
  }
  if (intwobyte)
  {
    outstream_->put(ESC);*outstream_ << ko_;
    //    fprintf(out,"%c%s",ESC,ko);
  }
}

//----------------- JapanConvertWizard::euc2euc -----------------------------------
void JapanConvertWizard::euc2euc()
{
  int p1,p2;

  while ((p1 = instream_->get()) != EOF) {
    if (ISEUC(p1)) {
      p2 = instream_->get();
      if (ISEUC(p2))
      {
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
    }
    else if (p1 == SS2) {
      p2 = instream_->get();
      if (HANKATA(p2) && forceHTFWK_) {
        p1 = p2;
        han2zen(p1,p2);
        sjis2jis(p1,p2);
        p1 += 128;
        p2 += 128;
      }
      outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
      //      fprintf(out,"%c%c",p1,p2);
    }
    else
    {
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
  }
}

//----------------- JapanConvertWizard::euc2shift ------------------------------
void JapanConvertWizard::euc2shift()
{
  int p1,p2;

  while ((p1 = instream_->get()) != EOF) {
    if (ISEUC(p1)) {
      p2 = instream_->get();
      if (ISEUC(p2)) {
        p1 -= 128;
        p2 -= 128;
        jis2sjis(p1,p2);
      }
      outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
      //      fprintf(out,"%c%c",p1,p2);
    }
    else if (p1 == SS2) {
      p2 = instream_->get();
      if (HANKATA(p2)) {
        p1 = p2;
        if (forceHTFWK_) {
          han2zen(p1,p2);
          outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
          //          fprintf(out,"%c%c",p1,p2);
        }
        else {
          outstream_->put((unsigned char)p1);
          //          fprintf(out,"%c",p1);
        }
      }
      else
      {
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
    }
    else
    {
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
  }
}

//------------------ JapanConvertWizard::shift2seven ------------------------------
void JapanConvertWizard::shift2seven()
{
  int p1,p2;
  bool intwobyte = false;

  while ((p1 = instream_->get()) != EOF) {
    if (p1 == NL || p1 == CR) {
      if (intwobyte) {
        intwobyte = false;
        outstream_->put(ESC);*outstream_ << ko_;
        //        fprintf(out,"%c%s",ESC,ko);
      }
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
    else if (SJIS1(p1)) {
      p2 = instream_->get();
      if (SJIS2(p2)) {
        sjis2jis(p1,p2);
        if (!intwobyte) {
          intwobyte = true;
          outstream_->put(ESC);*outstream_ << ki_;
          //          fprintf(out,"%c%s",ESC,ki);
        }
      }
      outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
      //      fprintf(out,"%c%c",p1,p2);
    }
    else if (HANKATA(p1)) {
      han2zen(p1,p2);
      sjis2jis(p1,p2);
      if (!intwobyte) {
        intwobyte = true;
        outstream_->put(ESC);*outstream_ << ki_;
        //        fprintf(out,"%c%s",ESC,ki);
      }
      outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
      //      fprintf(out,"%c%c",p1,p2);
    }
    else {
      if (intwobyte) {
        intwobyte = false;
        outstream_->put(ESC);*outstream_ << ko_;
        //        fprintf(out,"%c%s",ESC,ko);
      }
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
  }
  if (intwobyte)
  {
    outstream_->put(ESC);*outstream_ << ko_;
    //    fprintf(out,"%c%s",ESC,ko);
  }
}

//------------------ JapanConvertWizard::shift2euc -----------------------------
void JapanConvertWizard::shift2euc()
{
  int p1,p2;

  while ((p1 = instream_->get()) != EOF) {
    if (SJIS1(p1)) {
      p2 = instream_->get();
      if (SJIS2(p2)) {
        sjis2jis(p1,p2);
        p1 += 128;
        p2 += 128;
      }
      outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
      //      fprintf(out,"%c%c",p1,p2);
    }
    else if (HANKATA(p1)) {
      if (forceHTFWK_) {
        han2zen(p1,p2);
        sjis2jis(p1,p2);
        p1 += 128;
        p2 += 128;
      }
      else {
        p2 = p1;
        p1 = SS2;
      }
      outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
      //      fprintf(out,"%c%c",p1,p2);
    }
    else
    {
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
  }
}

//------------------- JapanConvertWizard::shift2shift --------------------------
void JapanConvertWizard::shift2shift()
{
  int p1,p2;

  while ((p1 = instream_->get()) != EOF) {
    if (SJIS1(p1)) {
      p2 = instream_->get();
      if (SJIS2(p2))
      {
        outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
        //        fprintf(out,"%c%c",p1,p2);
      }
    }
    else if (HANKATA(p1) && forceHTFWK_) {
      han2zen(p1,p2);
      outstream_->put((unsigned char)p1);outstream_->put((unsigned char)p2);
      //      fprintf(out,"%c%c",p1,p2);
    }
    else
    {
      outstream_->put((unsigned char)p1);
      //      fprintf(out,"%c",p1);
    }
  }
}

//---------------- JapanConvertWizard::han2zen ----------------------------------
void JapanConvertWizard::han2zen(int &p1,int &p2)
{
  int tmp = p1,junk;
  bool maru = false;
  bool nigori = false;
  int mtable[][2] = {
    {129,66},{129,117},{129,118},{129,65},{129,69},{131,146},{131,64},
    {131,66},{131,68},{131,70},{131,72},{131,131},{131,133},{131,135},
    {131,98},{129,91},{131,65},{131,67},{131,69},{131,71},{131,73},
    {131,74},{131,76},{131,78},{131,80},{131,82},{131,84},{131,86},
    {131,88},{131,90},{131,92},{131,94},{131,96},{131,99},{131,101},
    {131,103},{131,105},{131,106},{131,107},{131,108},{131,109},
    {131,110},{131,113},{131,116},{131,119},{131,122},{131,125},
    {131,126},{131,128},{131,129},{131,130},{131,132},{131,134},
    {131,136},{131,137},{131,138},{131,139},{131,140},{131,141},
    {131,143},{131,147},{129,74},{129,75}
  };

  if (incode_ == JapanConvertWizard::SHIFT_JIS) {
    p2 = instream_->get();
    if (p2 == 222) {
      if (ISNIGORI(p1))
        nigori = true;
      else
        instream_->putback(p2);
      //ungetc(p2,in);
    }
    else if (p2 == 223) {
      if (ISMARU(p1))
        maru = true;
      else
        instream_->putback(p2);
      //ungetc(p2,in);
    }
    else
      instream_->putback(p2);
    //ungetc(p2,in);
  }
  else if (incode_ == JapanConvertWizard::EUC) {
    junk = instream_->get();
    if (junk == SS2) {
      p2 = instream_->get();
      if (p2 == 222) {
        if (ISNIGORI(p1))
          nigori = true;
        else {
          instream_->putback(p2);
          //ungetc(p2,in);
          instream_->putback(junk);
          //ungetc(junk,in);
        }
      }
      else if (p2 == 223) {
        if (ISMARU(p1))
          maru = true;
        else {
          instream_->putback(p2);
          //ungetc(p2,in);
          instream_->putback(junk);
          //ungetc(junk,in);
        }
      }
      else {
        instream_->putback(p2);
        //ungetc(p2,in);
        instream_->putback(junk);
        //ungetc(junk,in);
      }
    }
    else
      instream_->putback(junk);
    //ungetc(junk,in);
  }
  if (p1 >= 161 && p1 <= 223) {
    p1 = mtable[tmp - 161][0];
    p2 = mtable[tmp - 161][1];
  }
  if (nigori) {
    if ((p2 >= 74 && p2 <= 103) || (p2 >= 110 && p2 <= 122))
      (p2)++;
    else if (p1 == 131 && p2 == 69)
      p2 = 148;
  }
  else if (maru && p2 >= 110 && p2 <= 122)
    p2 += 2;
}


// void main(int argc,char **argv)
// {
//   FILE *in,*out;
// #ifndef THINK_C
//   int rc;
// #endif
//   int tempincode,incode,doing = false,forcedelesc = false;
//   int makeoutfile = true,outcode = NOTSET,verbose = false,delesc = false;
//   int repairjis = false,tofullsize = false,setincode = false,docheck = false;
//   char infilename[100],outfilename[100],extension[10],ki[10],ko[10],toolname[100];

// #ifdef THINK_C
//   argc = ccommand(&argv);
// #endif

//   strcpy(toolname,*argv);
//   while (--argc > 0 && (*++argv)[0] == '-')
//     switch (toup(*++argv[0])) {
//       case 'C' :
//         docheck = true;
//         break;
//       case 'F' :
//         tofullsize = true;
//         break;
//       case 'H' :
//         dohelp(toolname);
//         break;
//       case 'I' :
//         setincode = true;
//         doing = INPUT;
//         incode = getcode(extension,toup(*++argv[0]),ki,ko,doing);
//         break;
//       case 'O' :
//         doing = OUTPUT;
//         outcode = getcode(extension,toup(*++argv[0]),ki,ko,doing);
//         break;
//       case 'R' :
//         repairjis = true;
//         doing = REPAIR;
//         outcode = getcode(extension,toup(*++argv[0]),ki,ko,doing);
//         break;
//       case 'S' :
//         delesc = true;
//         strcpy(extension,".rem");
//         if (toup(*++argv[0]) == 'F')
//           forcedelesc = true;
//         break;
//       case 'T' :
//         switch (toup(*++argv[0])) {
//           case 'E' :
//             doeuctable();
//             break;
//           case 'J' :
//           case 'N' :
//           case 'O' :
//             dojistable();
//             break;
//           case 'S' :
//             dosjistable();
//             break;
//           default :
//             dojistable();
//             dosjistable();
//             doeuctable();
//             break;
//         }
//         exit(0);
//         break;
//       case 'V' :
//         verbose = true;
//         break;
//       default :
//         fprintf(stderr,"Illegal option \"-%c\"! Try using the \"-h\" option for help.\n",*argv[0]);
//         fprintf(stderr,"Usage: %s [-options] [infile] [outfile]\nExiting...\n",toolname);
//         exit(1);
//         break;
//     }
//   if (repairjis && delesc) {
//     fprintf(stderr,"Error! Both \"-r\" and \"-s\" options cannot be selected! Exiting...\n");
//     exit(1);
//   }
//   if (outcode == NOTSET && !repairjis && !delesc) {
//     strcpy(ki,DEFAULT_OKI);
//     strcpy(ko,DEFAULT_OKO);
//     strcpy(extension,DEFAULT_OS);
//     outcode = DEFAULT_O;
//   }
//   if (argc == 0) {
// #ifndef THINK_C
//     rc = lseek(0,0,SEEK_CUR);
//     if (rc == -1 && errno == ESPIPE && !setincode && !delesc && !docheck && !repairjis) {
//       fprintf(stderr,"Cannot automatically detect input code from a pipe!\n");
//       fprintf(stderr,"Try \"-c\" to determine input code, then apply it to \"iCODE\" option.\n");
//       fprintf(stderr,"Exiting...\n");
//       exit(1);
//     }
// #endif
//     in = stdin;
//     out = stdout;
//   }
//   else if (argc > 0) {
//     if (argc == 1) {
//       strcpy(infilename,*argv);
//       if (strchr(*argv,PERIOD) != NULL)
//         *strrchr(*argv,PERIOD) = '\0';
//       strcpy(outfilename,*argv);
//       strcat(outfilename,extension);
//       if (!strcmp(infilename,outfilename)) {
//         if (strchr(outfilename,PERIOD) != NULL)
//           *strrchr(outfilename,PERIOD) = '\0';
//         strcat(outfilename,"-");
//         strcat(outfilename,extension);
//       }
//       if (verbose && !docheck)
//         fprintf(stderr,"Output file will be named %s\n",outfilename);
//     }
//     else if (argc > 1) {
//       strcpy(infilename,*argv++);
//       if (*argv[0] == '-') {
//         out = stdout;
//         makeoutfile = false;
//       }
//       else {
//         strcpy(outfilename,*argv);
//         if (!strcmp(infilename,outfilename)) {
//           if (strchr(outfilename,PERIOD) != NULL)
//             *strrchr(outfilename,PERIOD) = '\0';
//           strcat(outfilename,"-");
//           strcat(outfilename,extension);
//         }
//       }
//     }
//     if ((in = fopen(infilename,"r")) == NULL) {
//       fprintf(stderr,"Cannot open %s! Exiting...\n",infilename);
//       exit(1);
//     }
//     if (!docheck && makeoutfile)
//       if ((out = fopen(outfilename,"w")) == NULL) {
//         fprintf(stderr,"Cannot open %s! Exiting...\n",outfilename);
//         exit(1);
//       }
//   }
//   if (repairjis) {
//     jisrepair(in,out,verbose,outcode,ki,ko);
//     exit(0);
//   }
//   if (delesc) {
//     removeescape(in,out,verbose,forcedelesc);
//     exit(0);
//   }
//   tempincode = incode;
//   if (setincode && verbose) {
//     fprintf(stderr,"User-selected input code: ");
//     printcode(incode);
//   }
//   if (verbose && !docheck) {
//     fprintf(stderr,"User-selected output code: ");
//     printcode(outcode);
//   }
//   if (setincode && verbose)
//     ;
//   else if (!setincode || docheck || verbose) {
//     incode = DetectCodeType(in);
//     if (docheck || verbose) {
//       if (setincode && docheck)
//         fprintf(stderr,"NOTE: The selected \"-iCODE\" option was ignored\n");
//       fprintf(stderr,"Detected input code: ");
//       printcode(incode);
//       if (docheck)
//         exit(0);
//     }
//     rewind(in);
//   }
//   if (setincode)
//     incode = tempincode;
//   switch (incode) {
//     case NOTSET :
//       fprintf(stderr,"Unknown input code! Exiting...\n");
//       exit(1);
//       break;
//     case EUC_OR_SJIS :
//       fprintf(stderr,"Ambiguous (Shift-JIS or EUC) input code!\n");
//       fprintf(stderr,"Try using the \"-iCODE\" option to specify either Shift-JIS or EUC.\n");
//       fprintf(stderr,"Exiting...\n");
//       exit(1);
//       break;
//     case ASCII :
//       fprintf(stderr,"Since detected input code is ASCII, it may be damaged New- or Old-JIS\n");
//       fprintf(stderr,"Trying to repair...\n");
//       jisrepair(in,out,verbose,outcode,ki,ko);
//       break;
//     case NEW_JIS :
//     case OLD_JIS :
//     case NEC_JIS :
//       switch (outcode) {
//         case NEW_JIS :
//         case OLD_JIS :
//         case NEC_JIS :
//           seven2seven(in,out,ki,ko);
//           break;
//         case EUC :
//           seven2euc(in,out);
//           break;
//         case SHIFT_JIS :
//           seven2shift(in,out);
//           break;
//       }
//       break;
//     case EUC :
//       switch (outcode) {
//         case NEW_JIS :
//         case OLD_JIS :
//         case NEC_JIS :
//           euc2seven(in,out,incode,ki,ko);
//           break;
//         case EUC :
//           euc2euc(in,out,incode,tofullsize);
//           break;
//         case SHIFT_JIS :
//           euc2shift(in,out,incode,tofullsize);
//           break;
//       }
//       break;
//     case SHIFT_JIS :
//       switch (outcode) {
//         case NEW_JIS :
//         case OLD_JIS :
//         case NEC_JIS :
//           shift2seven(in,out,incode,ki,ko);
//           break;
//         case EUC :
//           shift2euc(in,out,incode,tofullsize);
//           break;
//         case SHIFT_JIS :
//           shift2shift(in,out,incode,tofullsize);
//           break;
//       }
//       break;
//   }
//   exit(0);
// }

// int toup(int data)
// {
//   if (islower(data))
//     return (toupper(data));
//   else
//     return data;
// }

// void printcode(int code)
// {
//   switch (code) {
//     case OLD_JIS :
//       fprintf(stderr,"Old-JIS\n");
//       break;
//     case NEW_JIS :
//       fprintf(stderr,"New-JIS\n");
//       break;
//     case NEC_JIS :
//       fprintf(stderr,"NEC-JIS\n");
//       break;
//     case EUC :
//       fprintf(stderr,"EUC\n");
//       break;
//     case SHIFT_JIS :
//       fprintf(stderr,"Shift-JIS\n");
//       break;
//     case EUC_OR_SJIS :
//       fprintf(stderr,"ambiguous (Shift-JIS or EUC)\n");
//       break;
//     case ASCII :
//       fprintf(stderr,"ASCII (no Japanese)\n");
//       break;
//     case NOTSET :
//       fprintf(stderr,"unknown\n");
//       break;
//     default :
//       break;
//   }
// }


// void removeescape(FILE *in,FILE *out,int verbose,int forcedelesc)
// {
//   int p1,p2,p3;
//   unsigned long count = 0,other = 0;

//   while ((p1 = instream_->get()) != EOF) {
//     if (p1 == ESC) {
//       p2 = instream_->get();
//       if (p2 == '(') {
//         p3 = instream_->get();
//         switch (p3) {
//           case 'J' :
//           case 'B' :
//           case 'H' :
//             fprintf(out,"%c%c",p2,p3);
//             count++;
//             break;
//           default :
//             if (forcedelesc)
//               fprintf(out,"%c%c",p2,p3);
//             else
//               fprintf(out,"%c%c%c",p1,p2,p3);
//             other++;
//             break;
//         }
//       }
//       else if (p2 == '$') {
//         p3 = instream_->get();
//         switch (p3) {
//           case 'B' :
//           case '@' :
//             fprintf(out,"%c%c",p2,p3);
//             count++;
//             break;
//           default :
//             if (forcedelesc)
//               fprintf(out,"%c%c",p2,p3);
//             else
//               fprintf(out,"%c%c%c",p1,p2,p3);
//             other++;
//             break;
//         }
//       }
//       else {
//         if (forcedelesc)
//           fprintf(out,"%c",p2);
//         else
//           fprintf(out,"%c%c",p1,p2);
//         other++;
//       }
//     }
//     else
//       fprintf(out,"%c",p1);
//   }
//   if (verbose) {
//     fprintf(stderr,"Number of valid escape characters removed: %lu\n",count);
//     if (forcedelesc)
//       fprintf(stderr,"Number of other escape characters forced removed: %lu\n",other);
//     else
//       fprintf(stderr,"Number of other escape characters detected: %lu\n",other);
//   }
// }

// void jisrepair(FILE *in,FILE *out,int verbose,int outcode,char ki[],char ko[])
// {
//   int p1,p2,p3,intwobyte = false;
//   unsigned long count = 0;

//   while ((p1 = instream_->get()) != EOF) {
//     if (intwobyte) {
//       if (p1 == ESC) {
//         p2 = instream_->get();
//         if (p2 == '(') {
//           p3 = instream_->get();
//           switch (p3) {
//             case 'J' :
//             case 'B' :
//             case 'H' :
//               intwobyte = false;
//               switch (outcode) {
//                 case NEC_JIS :
//                 case NEW_JIS :
//                 case OLD_JIS :
//                   fprintf(out,"%c%s",ESC,ko);
//                   break;
//                 default :
//                   break;
//               }
//               break;
//             default :
//               fprintf(out,"%c%c%c",p1,p2,p3);
//               break;
//           }
//         }
//         else if (p2 == 'H') {
//           intwobyte = false;
//           switch (outcode) {
//             case NEC_JIS :
//             case NEW_JIS :
//             case OLD_JIS :
//               fprintf(out,"%c%s",ESC,ko);
//               break;
//             default :
//               break;
//           }
//         }
//         else
//           fprintf(out,"%c%c",p1,p2);
//       }
//       else if (p1 == '(') {
//         p2 = instream_->get();
//         switch (p2) {
//           case 'J' :
//           case 'B' :
//           case 'H' :
//             intwobyte = false;
//             switch (outcode) {
//               case NEC_JIS :
//               case NEW_JIS :
//               case OLD_JIS :
//                 fprintf(out,"%c%s",ESC,ko);
//                 break;
//               default :
//                 break;
//             }
//             count++;
//             break;
//           default :
//             switch (outcode) {
//               case NEC_JIS :
//               case NEW_JIS :
//               case OLD_JIS :
//                 fprintf(out,"%c%c",p1,p2);
//                 break;
//               case EUC :
//                 p1 += 128;
//                 p2 += 128;
//                 fprintf(out,"%c%c",p1,p2);
//                 break;
//               case SHIFT_JIS :
//                 jis2sjis(&p1,&p2);
//                 fprintf(out,"%c%c",p1,p2);
//                 break;
//             }
//             break;
//         }
//       }
//       else if (p1 == NL) {
//         switch (outcode) {
//           case NEC_JIS :
//           case NEW_JIS :
//           case OLD_JIS :
//             fprintf(out,"%c%s%c",ESC,ko,p1);
//             break;
//           default :
//             fprintf(out,"%c",p1);
//             break;
//         }
//         count++;
//         intwobyte = false;
//       }
//       else {
//         p2 = instream_->get();
//         switch (outcode) {
//           case NEC_JIS :
//           case NEW_JIS :
//           case OLD_JIS :
//             fprintf(out,"%c%c",p1,p2);
//             break;
//           case EUC :
//             p1 += 128;
//             p2 += 128;
//             fprintf(out,"%c%c",p1,p2);
//             break;
//           case SHIFT_JIS :
//             jis2sjis(&p1,&p2);
//             fprintf(out,"%c%c",p1,p2);
//             break;
//         }
//       }
//     }
//     else {
//       if (p1 == ESC) {
//         p2 = instream_->get();
//         if (p2 == '$') {
//           p3 = instream_->get();
//           switch (p3) {
//             case 'B' :
//             case '@' :
//               intwobyte = true;
//               switch (outcode) {
//                 case NEC_JIS :
//                 case NEW_JIS :
//                 case OLD_JIS :
//                   fprintf(out,"%c%s",ESC,ki);
//                   break;
//                 default :
//                   break;
//               }
//               break;
//             default :
//               fprintf(out,"%c%c%c",p1,p2,p3);
//               break;
//           }
//         }
//         else if (p2 == 'K') {
//           intwobyte = true;
//           switch (outcode) {
//             case NEC_JIS :
//             case NEW_JIS :
//             case OLD_JIS :
//               fprintf(out,"%c%s",ESC,ki);
//               break;
//             default :
//               break;
//           }
//         }
//         else
//           fprintf(out,"%c%c",p1,p2);
//       }
//       else if (p1 == '$') {
//         p2 = instream_->get();
//         switch (p2) {
//           case 'B' :
//           case '@' :
//             intwobyte = true;
//             switch (outcode) {
//               case NEC_JIS :
//               case NEW_JIS :
//               case OLD_JIS :
//                 fprintf(out,"%c%s",ESC,ki);
//                 break;
//               default :
//                 break;
//             }
//             count++;
//             break;
//           default :
//             switch (outcode) {
//               case NEC_JIS :
//               case NEW_JIS :
//               case OLD_JIS :
//                 fprintf(out,"%c%c",p1,p2);
//                 break;
//               case EUC :
//                 fprintf(out,"%c%c",p1,p2);
//                 break;
//               case SHIFT_JIS :
//                 fprintf(out,"%c%c",p1,p2);
//                 break;
//             }
//             break;
//         }
//       }
//       else
//         fprintf(out,"%c",p1);
//     }
//   }
//   if (intwobyte) {
//     switch (outcode) {
//       case NEC_JIS :
//       case NEW_JIS :
//       case OLD_JIS :
//         fprintf(out,"%c%s",ESC,ko);
//         count++;
//         break;
//       default :
//         break;
//     }
//   }
//   if (verbose)
//     fprintf(stderr,"Number of escape characters restored: %lu\n",count);
// }


