/*

MercuryInstaller コンソール入力ルーチン

*/

#include<conio.h>
#include<jctype.h>
#include"mercury.h"
/*------------------------------文字単位の処理-------------------------------*/
static	int	Ungetch_buf[16];
static	int	Ungetch_num = 0;

extern	void	ds_ungetch(int a)
{
	Ungetch_buf[Ungetch_num++] = a;
}

extern	int	ds_kbhit(void)
{
	return (Ungetch_num || kbhit());
}

extern	int	ds_getch(void)
{
	unsigned char	a;

	if	(Ungetch_num)
		return Ungetch_buf[--Ungetch_num];

rep:
	a = getch();

	if	(a=='\0' && kbhit())
	{
		a = getch();

		if	(0x3b<=a && a<=0x44)	/* IBM ファンクションキー */
			return FKEY_F1-0x3b+a;

		if	(0x54<=a && a<=0x5d)	/* IBM Shift+ファンクション */
			return FKEY_F1-0x54+a;

		switch	(a)
		{
		case 0x03:	return 0;	/* Ctrl+@ */
		case 0x48:	return FKEY_UP;
		case 0x4b:	return FKEY_RIGHT;
		case 0x4d:	return FKEY_LEFT;
		case 0x50:	return FKEY_DOWN;
		case 0x52:	return FKEY_INS;
		case 0x53:	return FKEY_DEL;
		case 0x00:	return 0; /* 単にCtrl+@のキーコードが0x00で */
					/* リピートがかかっている場合を考慮 */
		default:	goto rep;
		}
	}
	else if	(a=='\x1b' && kbhit())
	{
		switch	(getch())
		{
		case 0x53:	return FKEY_F1;
		case 0x54:	return FKEY_F2;
		case 0x55:	return FKEY_F3;
		case 0x56:	return FKEY_F4;	/* TOWNSではDELと同じコード */
		case 0x57:	return FKEY_F5;
		case 0x45:	return FKEY_F6;
		case 0x4a:	return FKEY_F7;
		case 0x50:	return FKEY_F8;	/* INSのコードでもある */
		case 0x51:	return FKEY_F9;
		case 0x5a:	return FKEY_F10;
		case 0x44:	return FKEY_DEL;

		case 0x1b:		/* ESCにキーリピートがかかっている */
			while	(kbhit())
				getch();
			return 0x1b;

		default:	goto rep;
		}
	}

	switch	(a)
	{					/* 98のカーソルキー対策 */
	case 0x08:	return FKEY_LEFT;	/* 98ではBSと←は同じコード */
	case 0x0a:	return FKEY_DOWN;
	case 0x0b:	return FKEY_UP;
	case 0x0c:	return FKEY_RIGHT;
	case 0x1c:	return FKEY_RIGHT;	/* TOWNSのカーソルキー対策 */
	case 0x1d:	return FKEY_LEFT;
	case 0x1e:	return FKEY_UP;
	case 0x1f:	return FKEY_DOWN;
	case 'E'-0x40:	return FKEY_UP;		/* ダイヤモンドカーソル */
	case 'S'-0x40:	return FKEY_LEFT;
	case 'D'-0x40:	return FKEY_RIGHT;
	case 'X'-0x40:	return FKEY_DOWN;

	default:	return a;
	}
}
/*---------------------------------文字列入力--------------------------------*/
extern	int	ds_strinput(char *buf,unsigned len)
{
	int		_ctypebuf[81];
	int		*ctypebuf = _ctypebuf + 1;
			/* Pascalならctypebuf[-1..79]としたいところだが... */

	unsigned	l = 0;	/* 入力中の文字列の長さ */
	unsigned	i;
	int		c;

	_ctypebuf[0] = CT_ANK;

	while	((c=*buf)!='\0')
	{
		putchar(c);

		*ctypebuf = chkctype(c,*(ctypebuf-1));

		buf++;
		ctypebuf++;
		l++;
	}

	for	(i=l ; i<len ; i++)	putchar(' ');
	for	(i=l ; i<len ; i++)	putchar('\b');

rep:

	c = ds_getch();

	if	(c=='\b' && l)
	{
		do
		{
			printf("\b \b");
			l--;
			buf--;
		} while( *--ctypebuf==CT_KJ2 || *ctypebuf==CT_ILGL);

	}
	else if	(c=='\r' || c=='\033')
	{
		*buf = '\0';

		return c=='\r';
	}
	else if	(c<0x100 && c>=' ' && l<len)
	{
		*ctypebuf = chkctype(c,*(ctypebuf-1));

		if	(*ctypebuf == CT_KJ1 && l==len-1)
		{			/* バッファの最後に漢字の第1バイトが */
			ds_getch();	/* 来た場合はその漢字全体を捨てる     */
			putchar('\a');
		}
		else
		{
			l++;
			*buf++ = c;
			ctypebuf++;
			putchar(c);
		}
	}
	else		/* コントロールコード */
		putchar('\a');

	goto rep;
}
/*-------------------------------End of _conio.c-----------------------------*/
