1-SSP)*2+1]);
                                c2=0; 
                                NEXT;
                            }
                            UNGETC(c2,f); c2 = 0;
                        }
                        (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
                        NEXT;
                    } else
                        SEND;
                } else if(c1 == '(' && broken_f && input_mode == X0208
                        && !mime_mode ) {
                    /* Try to recover missing escape */
                    if((c1 = GETC(f)) == EOF) {
                        (*oconv)(0, '(');
                        LAST;
                    } else {
                        if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
                            input_mode = ASCII; shift_mode = FALSE;
                            NEXT;
                        } else {
                            (*oconv)(0, '(');
                            /* do not modify various input_mode */
                            /* It can be vt100 sequence */
                            SEND;
                        }
                    }
                } else if(input_mode == X0208) {
                    /* in case of Kanji shifted */
                    c2 = c1;
                    NEXT;
                    /* goto next_byte */
                } else if(c1 == '=' && mime_f && !mime_mode ) {
                    if((c1 = getc(f)) == EOF) {
                        (*oconv)(0, '=');
                        LAST;
                    } else if(c1 == '?') {
                        /* =? is mime conversiooon start sequence */
                        if(mime_begin(f) == EOF) /* check in detail */
                            LAST;
                        else
                            NEXT;
                    } else {
                        (*oconv)(0, '=');
                        ungetc(c1,f);
                        NEXT;
                    }
                } else if(c1 == '$' && broken_f && !mime_mode) {
                    /* try to recover missing escape */
                    if((c1 = GETC(f)) == EOF) {
                        (*oconv)(0, '$');
                        LAST;
                    } else if(c1 == '@'|| c1 == 'B') {
                        /* in case of Kanji in ESC sequence */
                        input_mode = X0208;
                        shift_mode = FALSE;
                        NEXT;
                    } else {
                        /* sorry */
                        (*oconv)(0, '$');
                        (*oconv)(0, c1);
                        NEXT;
                    }
                } else
                    SEND;
            } else if(c1 == SI) {
                shift_mode = FALSE; 
                NEXT;
            } else if(c1 == SO) {
                shift_mode = TRUE; 
                NEXT;
            } else if(c1 == ESC) {
                if((c1 = GETC(f)) == EOF) {
                    (*oconv)(0, ESC);
                    LAST;
                } else if(c1 == '$') {
                    if((c1 = GETC(f)) == EOF) {
                        (*oconv)(0, ESC);
                        (*oconv)(0, '$');
                        LAST;
                    } else if(c1 == '@'|| c1 == 'B') {
                        /* This is kanji introduction */
                        input_mode = X0208;
                        shift_mode = FALSE;
                        NEXT;
                    } else if(c1 == '(') {
			if((c1 = GETC(f)) == EOF) {
			    (*oconv)(0, ESC);
			    (*oconv)(0, '$');
			    (*oconv)(0, '(');
			    LAST;
			} else if(c1 == '@'|| c1 == 'B') {
			    /* This is kanji introduction */
			    input_mode = X0208;
			    shift_mode = FALSE;
			    NEXT;
			} else {
			    (*oconv)(0, ESC);
			    (*oconv)(0, '$');
			    (*oconv)(0, '(');
			    (*oconv)(0, c1);
			    NEXT;
			}
                    } else if(broken_f&0x2) {
                        input_mode = X0208;
                        shift_mode = FALSE;
                        NEXT;
                    } else {
                        (*oconv)(0, ESC);
                        (*oconv)(0, '$');
                        (*oconv)(0, c1);
                        NEXT;
                    }
                } else if(c1 == '(') {
                    if((c1 = GETC(f)) == EOF) {
                        (*oconv)(0, ESC);
                        (*oconv)(0, '(');
                        LAST;
                    } else {
                        if(c1 == 'I') {
                            /* This is X0201 kana introduction */
                            input_mode = X0201; shift_mode = X0201;
                            NEXT;
                        } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
                            /* This is X0208 kanji introduction */
                            input_mode = ASCII; shift_mode = FALSE;
                            NEXT;
                        } else if(broken_f&0x2) {
                            input_mode = ASCII; shift_mode = FALSE;
                            NEXT;
                        } else {
                            (*oconv)(0, ESC);
                            (*oconv)(0, '(');
                            /* maintain various input_mode here */
                            SEND;
                        }
                    }
                } else {
                    /* lonely ESC  */
                    (*oconv)(0, ESC);
                    SEND;
                }
            } else if(c1 == NL && broken_f&4) {
                input_mode = ASCII; 
                SEND;
            } else
                SEND;
        }
        /* send: */
        if(input_mode == X0208) 
            (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */
        else
            (*iconv)(c2, c1);  /* can be EUC/SJIS */
        c2 = 0;
        continue;
        /* goto next_word */
    }

    /* epilogue */
    (*iconv)(EOF, 0);
}




static void
h_conv(f, c2, c1)
    FILE  *f;
    int    c1, c2;
{
    int    wc;


    /** it must NOT be in the kanji shifte sequence      */
    /** it must NOT be written in JIS7                   */
    /** and it must be after 2 byte 8bit code            */

    hold_count = 0;
    push_hold_buf(c2, c1);
    c2 = 0;

    while ((c1 = GETC(f)) != EOF) {
        if(c2) {
            /* second byte */
            if(!estab_f) {
                /* not established */
                if(c1 > SSP) {
                    /* it is still ambiguious yet */
                    SEND;
                } else if(c1 < AT) {
                    /* ignore bogus first byte */
                    c2 = 0;
                    SEND;
                } else {
                    /* now established */
                    /* it seems to be MS Kanji */
                    estab_f = TRUE;
                    iconv = s_iconv;
                    SEND;
                }
            } else
                SEND;
        } else {
            /* First byte */
            if(c1 > DEL) {
                /* 8th bit is on */
                if(c1 < SSP) {
                    /* it seems to be MS Kanji */
                    estab_f = TRUE;
                    iconv = s_iconv;
                } else if(c1 < 0xe0) {
                    /* it seems to be EUC */
                    estab_f = TRUE;
                    iconv = oconv;
                } else {
                    /* still ambiguious */
                }
                c2 = c1;
                NEXT;
            } else
            /* 7 bit code , then send without any process */
                SEND;
        }
        /* send: */
        if((push_hold_buf(c2, c1) == EOF) || estab_f)
            break;
        c2 = 0;
        continue;
    }

    /** now,
     ** 1) EOF is detected, or
     ** 2) Code is established, or
     ** 3) Buffer is FULL (but last word is pushed)
     **
     ** in 1) and 3) cases, we continue to use
     ** Kanji codes by oconv and leave estab_f unchanged.
     **/

    for (wc = 0; wc < hold_count; wc += 2) {
        c2 = hold_buf[wc];
        c1 = hold_buf[wc+1];
        (*iconv)(c2, c1);
    }
    return;
}



static int
push_hold_buf(c2, c1)
    int c2, c1;
{
    if(hold_count >= HOLD_SIZE*2)
        return (EOF);
    hold_buf[hold_count++] = c2;
    hold_buf[hold_count++] = c1;
    return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
}


static void
s_iconv(c2, c1)
    int    c2,
                    c1;
{
    if((c2 == EOF) || (c2 == 0)) {
        /* NOP */
    } else {
        c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
        if(c1 < 0x9f)
            c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
        else {
            c1 = c1 - 0x7e;
            c2++;
        }
    }
    (*oconv)(c2, c1);
}


static void
e_oconv(c2, c1)
    int    c2, c1;
{
    c2 = pre_convert(c1,c2); c1 = c1_return;
    if(fold_f) {
        switch(line_fold(c2,c1)) {
            case '\n': 
                if(add_cr == TRUE) {
                    putchar('\r');
                    c1 = '\n';
                }
                putchar('\n');
                break;
            case 0:    return;
            case '\r': 
                c1 = '\n'; c2 = 0;
                break;
            case '\t': 
            case ' ': 
                c1 = ' '; c2 = 0;
                break;
        }
    }
    if(c2==DOUBLE_SPACE) {
        putchar(' '); putchar(' ');
        return;
    }
    if(c2 == EOF)
        return;
    else if(c2 == 0 && (c1&0x80)) {
        putchar(SSO); putchar(c1);
    } else if(c2 == 0) {
        if(c1 == '\n' && add_cr == TRUE) 
            putchar('\r');
        if(c1 != '\r') 
            putchar(c1);
        else if(del_cr == FALSE) 
            putchar(c1);
    } else {
        if((c1<0x20 || 0x7e<c1) ||
           (c2<0x20 || 0x7e<c2)) {
            estab_f = FALSE;
            return; /* too late to rescue this char */
        }
        putchar(c2 | 0x080);
        putchar(c1 | 0x080);
    }
    return;
}


static void
s_oconv(c2, c1)
    int    c2, c1;
{
    c2 = pre_convert(c1,c2); c1 = c1_return;
    if(fold_f) {
        switch(line_fold(c2,c1)) {
            case '\n': 
                if(add_cr == TRUE) {
                   putchar('\r');
                   c1 = '\n';
                }
                putchar('\n');
                break;
            case '\r': 
                c1 = '\n'; c2 = 0;
                break;
            case 0:    return;
            case '\t': 
            case ' ': 
                c1 = ' '; c2 = 0;
                break;
        }
    }
    if(c2==DOUBLE_SPACE) {
        putchar(' '); putchar(' ');
        return;
    }
    if(c2 == EOF)
        return;
    else if(c2 == 0) {
        if(c1 == '\n' && add_cr == TRUE) 
            putchar('\r');
        if(c1 != '\r') 
            putchar(c1);
        else if(del_cr == FALSE) 
            putchar(c1);
    } else {
        if((c1<0x20 || 0x7e<c1) ||
           (c2<0x20 || 0x7e<c2)) {
            estab_f = FALSE;
            return; /* too late to rescue this char */
        }
        putchar((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
        putchar((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
    }
    return;
}


static void
j_oconv(c2, c1)
    int    c2, c1;
{
    c2 = pre_convert(c1,c2); c1 = c1_return;
    if(fold_f) {
        switch(line_fold(c2,c1)) {
            case '\n': 
                if(output_mode) {
                    putchar(ESC);
                    putchar('(');
                    putchar(ascii_intro);
                }
                if(add_cr == TRUE) {
                    putchar('\r');
                    c1 = '\n';
                }
                putchar('\n');
                output_mode = ASCII;
                break;
            case '\r': 
                c1 = '\n'; c2 = 0;
                break;
            case '\t': 
            case ' ': 
                c1 = ' '; c2 = 0;
                break;
            case 0:    return;
        }
     }
    if(c2 == EOF) {
        if(output_mode) {
            putchar(ESC);
            putchar('(');
            putchar(ascii_intro);
        }
    } else if(c2 == 0 && (c1 & 0x80)) {
        if(input_mode==X0201 || !iso8859_f) {
            if(output_mode!=X0201) {
                putchar(ESC);
                putchar('(');
                putchar('I');
                output_mode = X0201;
            }
            c1 &= 0x7f;
        } else {
            /* iso8859 introduction, or 8th bit on */
            /* Can we convert in 7bit form using ESC-'-'-A ? 
               Is this popular? */
        }
        putchar(c1);
    } else if(c2 == 0) {
        if(output_mode) {
            putchar(ESC);
            putchar('(');
            putchar(ascii_intro);
            output_mode = ASCII;
        }
        if(c1 == '\n' && add_cr == TRUE) 
            putchar('\r');
        if(c1 != '\r') 
            putchar(c1);
        else if(del_cr == FALSE) 
            putchar(c1);
    } else if(c2 == DOUBLE_SPACE) {
        if(output_mode) {
            putchar(ESC);
            putchar('(');
            putchar(ascii_intro);
            output_mode = ASCII;
        }
        putchar(' ');
        if(c1 == '\n' && add_cr == TRUE) 
            putchar('\r');
        if(c1 != '\r') 
            putchar(c1);
        else if(del_cr == FALSE) 
            putchar(c1);
    } else {
        if(output_mode != X0208) {
            putchar(ESC);
            putchar('$');
            putchar(kanji_intro);
            output_mode = X0208;
        }
        if(c1<0x20 || 0x7e<c1) 
            return;
        if(c2<0x20 || 0x7e<c2) 
            return;
        putchar(c2);
        if(c1 == '\n' && add_cr == TRUE) 
            putchar('\r');
        if(c1 != '\r') 
            putchar(c1);
        else if(del_cr == FALSE) 
            putchar(c1);
    }
    return;
}



#define rot13(c)  ( \
      ( c < 'A' ) ? c: \
      (c <= 'M')  ? (c + 13): \
      (c <= 'Z')  ? (c - 13): \
      (c < 'a')   ? (c): \
      (c <= 'm')  ? (c + 13): \
      (c <= 'z')  ? (c - 13): \
      (c) \
)

#define  rot47(c) ( \
      ( c < '!' ) ? c: \
      ( c <= 'O' ) ? (c + 47) : \
      ( c <= '~' ) ?  (c - 47) : \
      c \
)


/* 
  Return value of line_fold()

       \n  add newline  and output char
       \r  add newline  and output nothing
       ' ' space
       0   skip  
       1   (or else) normal output 

  fold state in prev (previous character)

      >0x80 Japanese (X0208/X0201)
      <0x80 ASCII
      \n    new line 
      ' '   space

  This fold algorthm does not preserve heading space in a line.
  This is the main difference from fmt.
*/

static int
line_fold(c2,c1) 
int c2,c1;
{ 
    int prev0;
    if(c1=='\r') 
        return 0;               /* ignore cr */
    if(c1== 8) {
        if(line>0) line--;
        return 1;
    }
    if(c2==EOF && line != 0)    /* close open last line */
        return '\n';
    /* new line */
    if(c1=='\n') {
        if(prev == c1) {        /* duplicate newline */
            if(line) {
                line = 0;
                return '\n';    /* output two newline */
            } else {
                line = 0;
                return 1;
            }
        } else  {
            if(prev&0x80) {     /* Japanese? */
                prev = c1;
                return 0;       /* ignore given single newline */
            } else if(prev==' ') {
                return 0;
            } else {
                prev = c1;
                if(++line<=fold_len) 
                    return ' ';
                else {
                    line = 0;
                    return '\r';        /* fold and output nothing */
                }
            }
        }
    }
    if(c1=='\f') {
        prev = '\n';
        if(line==0)
            return 1;
        line = 0;
        return '\n';            /* output newline and clear */
    }
    /* X0208 kankaku or ascii space */
    if( (c2==0&&c1==' ')||
        (c2==0&&c1=='\t')||
        (c2==DOUBLE_SPACE)||
        (c2=='!'&& c1=='!')) {
        if(prev == ' ') {
            return 0;           /* remove duplicate spaces */
        } 
        prev = ' ';    
        if(++line<=fold_len) 
            return ' ';         /* output ASCII space only */
        else {
            prev = ' '; line = 0;
            return '\r';        /* fold and output nothing */
        }
    } 
    prev0 = prev; /* we still need this one... , but almost done */
    prev = c1;
    if(c2 || (SSP<=c1 && c1<=0xdf)) 
        prev |= 0x80;  /* this is Japanese */
    line += (c2==0)?1:2;
    if(line<=fold_len) {   /* normal case */
        return 1;
    }
    if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */
        line = (c2==0)?1:2;
        return '\n';       /* We can't wait, do fold now */
    }
    /* simple kinsoku rules  return 1 means no folding  */
    if(c2==0) {
        if(c1==0xde) return 1; /* 