/********************************************

	文書デ−タの取得

*********************************************/
#include    "defs.h"

static	int	cd_stat = 0;
static	int	cd_ank_mode = FALSE;
static	int	cd_left_spc = 0;
static	int	cd_eof_flag = FALSE;
static	int	cd_attr = 0;

static	int	cd_bak_char = ERR;
static	int	cd_bak_data = ERR;

static	uchar	*cd_mac_str = NULL;

static	POINT	sub_pos;

	int	menu_max = 0;
	int	betu_max = 0;

	MENUPTR *menu_top = NULL;
	MENUPTR	*betu_top = NULL;

	MENUPTR	menu_tab[MENU_MAX];
	MENUPTR	betu_tab[BETU_MAX];

static	int	cd_getc()
{
    int     ch;

    if ( cd_bak_char != ERR ) {
	ch = cd_bak_char;
	cd_bak_char = ERR;
	return ch;
    }
    return IO_getc();
}
static	void	cd_ungetc(int ch)
{
    cd_bak_char = ch;
}
static	int	cd_getw()
{
    int   ch;

    ch = cd_getc() << 8;
    ch |= cd_getc();
    return ch;
}
static	ushort	cd_get_short(int len)
{
    int     c;
    ushort  n = 0;

    while ( len-- > 0 ) {
	if ( (c = cd_getc()) == EOF )
	    break;
	n = n * 10 + (c >> 4);
	n = n * 10 + (c & 0x0F);
    }
    return n;
}
static	ulong	cd_get_long(int len)
{
    int     c;
    ulong   n = 0;

    while ( len-- > 0 ) {
	if ( (c = cd_getc()) == EOF )
	    break;
	n = n * 10 + (c >> 4);
	n = n * 10 + (c & 0x0F);
    }
    return n;
}
static	int	cd_get_col()
{
    int     c;
    int     n = 0;

    while ( (c = cd_getc()) == 0x1E ) {
	if ( (c = cd_getc()) == EOF )
	    break;
	n = n * 10 + (c >> 4);
	n = n * 10 + (c & 0x0F);
    }
    cd_ungetc(c);
    return n;
}
int	cd_get_data()
{
    uint   ch;

    if ( cd_eof_flag )
	return EOF;

RESTART:
    if ( cd_bak_data != ERR ) {
	ch = cd_bak_data;
	cd_bak_data = ERR;
	return ch;
    }

    if ( cd_mac_str != NULL ) {
	if ( (ch = *(cd_mac_str++)) != '\0' ) {
	    if ( iskanji(ch) && iskanji2(*cd_mac_str) )
		ch = (ch << 8) | (*(cd_mac_str++) & 0xFF);
	    return ch;
	}
	cd_mac_str = NULL;
    }

NEXT:
    if ( (ch = cd_getw()) == EOF ) {
	ch = EOF;
	goto ENDOF;
    }

    if ( ch >= 0x2121 ) {
	if ( cutof_flag == FALSE && cd_stat == 3 ) {
	    ch = EOF;
	    goto ENDOF;
	}

	if ( ch >= 0xA121u ) {	/* 外字文字 */
	    ch |= (cd_ank_mode ? 0x0080:0x0000);
	    if ( (cd_mac_str = Gaiji_convert(&ch)) != NULL )
		goto RESTART;
	}

	ch = jistosjis(ch);

	if ( cd_ank_mode )
	    ch = zentohan(ch);

#ifdef	EUC
	if ( (ch & 0xFF00) != 0 )
	    ch = jistoeuc(sjistojis(ch));
#endif	/* EUC */

    } else {
        switch(ch) {
        case 0x0000:
	    ch = EOF;
	    break;

        case 0x1F02:		/* 表示開始指定 */
	    goto NEXT;
        case 0x1F03:		/* 表示終了指定 */
	    ch = EOF;
	    break;

        case 0x1F04:		/* 半角開始指定 */
	    cd_ank_mode = TRUE;
	    goto NEXT;
        case 0x1F05:		/* 半角終了指定 */
	    cd_ank_mode = FALSE;
	    goto NEXT;

        case 0x1F06:		/* ルビ開始指定 */
        case 0x1F07:		/* ルビ終了指定 */
	    goto NEXT;

        case 0x1F09:		/* 字下げ指定 */
	    cd_left_spc = (cd_get_short(2) - 1) * 2;
	    goto NEXT;

        case 0x1F0A:		/* 改行指定 */
	    switch(cd_stat) {
	    case 0: cd_stat = 1; break;
	    case 1: cd_stat = 2; break;
	    }
	    ch = '\n';
	    break;

        case 0x1F0E:		/* 添字上開始指定 */
        case 0x1F0F:		/* 添字上終了指定 */
        case 0x1F10:		/* 分割禁止開始指定 */
        case 0x1F11:		/* 分割禁止終了指定 */
	    goto NEXT;
        case 0x1F12:		/* 強調開始指定 */
	    ch = CH_BOLD_ON;
	    break;
        case 0x1F13:		/* 強調終了指定 */
	    ch = CH_BOLD_OFF;
	    break;

        case 0x1F14:		/* 色指定開始指定 */
	    cd_get_col();
        case 0x1F15:		/* 色指定終了指定 */
	    goto NEXT;

        case 0x1FE0:		/* 拡張強調表示開始指定 */
	    cd_get_short(2);
	    ch = CH_BOLD_ON;
	    break;
        case 0x1FE1:		/* 拡張強調表示終了指定 */
	    ch = CH_BOLD_OFF;
	    break;

        case 0x1FE2:		/* 保護開始指定 */
	    cd_get_short(2);
        case 0x1FE3:		/* 保護終了指定 */
	    goto NEXT;

        case 0x1F41:		/* 検索キ−識別子 */
	    switch(cd_stat) {
	    case 0: cd_stat = 1; break;
	    case 2: cd_stat = 3; break;
	    }
	    cd_getw();
	    ch = CH_BOLD_ON;
	    break;
        case 0x1F61:		/* 検索キ−終了識別子 */
	    ch = CH_BOLD_OFF;
	    break;

        case 0x1F42:		/* 別項目参照識別子 */
	    break;
        case 0x1F62:		/* 別項目参照終了識別子 */
	    sub_pos.block  = cd_get_long(4);		/* Block No */
	    sub_pos.offset = cd_get_short(2);		/* Offset */
	    break;

        case 0x1F43:		/* メニュ−識別子 */
	    break;
        case 0x1F63:		/* メニュ−終了識別子 */
	    sub_pos.block  = cd_get_long(4);
	    sub_pos.offset = cd_get_short(2);
	    break;

        case 0x1F44:		/* 図版デ−タ識別子 */
	    cd_get_short(2);		/* 図版再生法識別 */
	    cd_get_long(4);		/* 縦ドット数 */
	    cd_get_long(4);		/* 横ドット数 */
	    goto NEXT;
        case 0x1F64:		/* 図版デ−タ終了識別子 */
	    sub_pos.block  = cd_get_long(4);		/* Block No */
	    sub_pos.offset = cd_get_short(2);		/* Offset */
	    goto NEXT;

        case 0x1F45:		/* 図版デ−タ群識別子 */
        case 0x1F65:		/* 図版デ−タ群終了識別子 */
	    goto NEXT;

        case 0x1F46:		/* 図版メニュ−識別子 */
	    goto NEXT;
        case 0x1F66:		/* 図版メニュ−終了識別子 */
	    sub_pos.block  = cd_get_long(4);		/* Block No */
	    sub_pos.offset = cd_get_short(2);		/* Offset */
	    goto NEXT;

        case 0x1F47:		/* 色見本メニュ−識別子 */
	    goto NEXT;
        case 0x1F67:		/* 色見本メニュ−終了識別子 */
	    cd_get_col();
	    goto NEXT;

        case 0x1F48:		/* 音声デ−タ識別子 */
	    cd_get_short(2);		/* トラック番号 */
	    cd_get_long(4);		/* 先頭アドレス */
	    cd_get_long(4);		/* 容量 */
	    goto NEXT;
        case 0x1F68:		/* 音声デ−タ終了識別子 */
	    goto NEXT;

        default:
#ifdef	DEBUG
	printf("Unkow Code %04x\n", ch);
#endif
	    ch = '?';
	    break;
        }
    }

ENDOF:
    if ( ch == EOF )
	cd_eof_flag = TRUE;

    return ch;
}
static	void	cd_unget_data(int ch)
{
    cd_bak_data = ch;
}
char	*cd_gets(char *buf, int max, int line)
{
    int     ch, n;
    int     len = 0;
    int     attr = 0;

    while ( len < max ) {

	if ( (ch = cd_get_data()) == EOF ) {
	    if ( len == 0 )
	        return NULL;
	    break;
	}

	if ( ch == '\n' )
	    break;

	while ( len < cd_left_spc && len < max )
	    buf[len++] = ' ';

	n = (ch & 0xFF00) != 0 ? 2:1;
	if ( (len + n) > max ) {
	    cd_unget_data(ch);
	    break;
	}

        if ( ch == 0x1F43 ) {			/* メニュ−識別子 */
	    if ( menu_max >= MENU_MAX )
		continue;
	    menu_tab[menu_max].sx = len;
	    menu_tab[menu_max].sy = line;
	    menu_tab[menu_max].next = menu_top;
	    menu_top = &(menu_tab[menu_max]);
	    menu_max++;
	    continue;

	} else if ( ch == 0x1F63 ) {		/* メニュ−終了識別子 */
	    if ( menu_top == NULL )
		continue;
	    menu_top->bx = len;
	    menu_top->by = line;
	    menu_top->pos.block  = sub_pos.block;
	    menu_top->pos.offset = sub_pos.offset;
	    if ( menu_top->sx == len &&
		 menu_top->sy == line ) {
		menu_top->bx = len + 2;
		ch = 0x819E;		/* ◇ */
#ifdef	EUC
		ch = jistoeuc(sjistojis(ch));
#endif	/* EUC */
		menu_top = menu_top->next;
	    } else {
		menu_top = menu_top->next;
	        continue;
	    }

	} else if ( ch == 0x1F42 ) {		/* 別項目参照識別子 */
	    if ( betu_max >= BETU_MAX )
		continue;
	    betu_tab[betu_max].sx = len;
	    betu_tab[betu_max].sy = line;
	    betu_tab[betu_max].next = betu_top;
	    betu_top = &(betu_tab[betu_max]);
	    betu_max++;
	    ch = CH_ITALIC_ON;
	    n = 1;

	} else if ( ch == 0x1F62 ) {		/* 別項目参照終了識別子 */
	    if ( betu_top == NULL )
		continue;
	    betu_top->bx = len;
	    betu_top->by = line;
	    betu_top->pos.block  = sub_pos.block;
	    betu_top->pos.offset = sub_pos.offset;
	    if ( betu_top->sx == len &&
		 betu_top->sy == line ) {
		betu_top->bx = len + 2;
		betu_top = betu_top->next;
		ch = ('#' << 8) | CH_ITALIC_OFF;
		n = 2;

	    } else {
		betu_top = betu_top->next;
		ch = CH_ITALIC_OFF;
	        n = 1;
	    }
	}

	switch(ch) {
	case CH_BOLD_ON:    cd_attr |= 1; break;
	case CH_BOLD_OFF:   cd_attr &= 2; break;
	case CH_ITALIC_ON:  cd_attr |= 2; break;
	case CH_ITALIC_OFF: cd_attr &= 1; break;
	default:
	    if ( (cd_attr & 0x01) != (attr & 0x01) )
		buf[len++] = (cd_attr & 1) == 0 ? CH_BOLD_OFF:CH_BOLD_ON;
	    if ( (cd_attr & 0x02) != (attr & 0x02) )
		buf[len++] = (cd_attr & 2) == 0 ? CH_ITALIC_OFF:CH_ITALIC_ON;
	    attr = cd_attr;
	    if ( n == 2 )
	        buf[len++] = (char)(ch >> 8);
	    buf[len++] = (char)(ch);
	    break;
	}
    }
    if ( (attr & 1) != 0 )
	buf[len++] = CH_BOLD_OFF;
    if ( (attr & 2) != 0 )
	buf[len++] = CH_ITALIC_OFF;
    buf[len++] = '\n';
    buf[len] = '\0';

    return buf;
}
int	dic_seek(ulong block, ushort offset)
{
    cd_stat = 0;
    cd_ank_mode = FALSE;
    cd_left_spc = 0;
    cd_eof_flag = FALSE;
    cd_attr     = 0;

    menu_max = betu_max = 0;
    menu_top = betu_top = NULL;

    cd_bak_char = ERR;
    cd_bak_data = ERR;

    return IO_seek(block, offset);
}
