/*

dmove86 version 1.20c
Copyright (c) 1993 Delmonta

dmmenu.c -- メニューモジュール

*/

#include<stdio.h>
#include<dos.h>
#include"dmove86.h"

unsigned int	Pagenum,Lastnum;	/* ページ数･最終ページのエントリ数 */
unsigned int	Page,Pos;		/* 現在のページ番号とカーソル位置  */
unsigned int	Selected;		/* 選択され反転表示されている番号  */
struct DIRENTRY	far **Dirtbl;


static	void	putfilename(p)		/* 画面にファイル名を表示          */
int		p;
{
	printf("\033[%d;%df ",p/6+3,(p%6)*13+1);

	if	(Page*96+p == Selected)
		printf("\033[7");	/* 最後の'm'はまだつけない */
	else
		printf("\033[0");

	if	(Dirtbl[Page*96+p]->filename[0]=='\xe5')
		printf("m::::::::.:::");
	else
	{
		int	i;

		if	(Dirtbl[Page*96+p]->attr & _A_SUBDIR)
			printf(";32m");		/* ディレクトリは緑 */
		else if	(Dirtbl[Page*96+p]->attr & _A_VOLID)
			printf(";35m");		/* ボリュームIDは紫 */
		else if	(Dirtbl[Page*96+p]->attr & _A_SYSTEM)
			printf(";31m");		/* システムファイルは赤 */
		else
			printf(";37m");		/* そのほかは白 */

		for	(i=0 ; i<8 ; i++)
			putchar(Dirtbl[Page*96+p]->filename[i]);

		putchar('.');

		for	(i=0 ; i<3 ; i++)
			putchar(Dirtbl[Page*96+p]->extname[i]);
	}
	printf(" \n\033[0;37m");
}

static	void	putpage(n)	/* ページ表示 */
int		n;		/* n!=0なら一度画面を消す */
{
	int		i;

	printf("\033[3;1f");

	if	(n)
		for	(i=0 ; i<16 ; i++)
			printf("\033[2K\n");

	for	(i=0 ; i<96 ; i++)
	{
		if	(Page==Pagenum-1 && i==Lastnum)
			break;
		else
			putfilename(i);
	}
}

void	putcursor(void)
{
static	int		oldx = -1,
			oldy = -1;

	if	(oldx != -1)
	{
		printf("\033[%d;%df",oldy+3,oldx*13+1);
		putchar(' ');
		printf("\033[%d;%df",oldy+3,oldx*13+13+1);
		putchar(' ');
	}

	oldx = Pos%6;
	oldy = Pos/6;

	printf("\033[%d;%df",oldy+3,oldx*13+1);
	putchar('<');
	printf("\033[%d;%df",oldy+3,oldx*13+13+1);
	putchar('>');
}

static	char	movecursor(flag)	/* カーソル移動・キー入力           */
int		flag;			/* ｶｰｿﾙ･ｽﾍﾟｰｽ･ESC以外を受け付けるか */
{
	int	c;

	selectflag(!flag);

LOOP:;
	putcursor();

	c = dm_getch();

	if	(c == '\3')
		endscreen();

	if	(c == '\x1a')
		endscreen();

	switch	(c)
	{
	case '6':
	case 'D'-0x40:	/* ^D */
	case RIGHTKEY:
		Pos++;
		if	(Pos==96 || (Page==Pagenum-1 && Pos==Lastnum) )
			Pos=0;
		break;

	case '4':
	case 'S'-0x40:	/* ^S */
	case LEFTKEY:
		if	(Pos==0)
		{
			if	(Page==Pagenum-1)
				Pos = Lastnum-1;
			else
				Pos = 95;
		}
		else
			Pos--;
		break;

	case '8':
	case 'E'-0x40:	/* ^E */
	case UPKEY:
		if	(Pos>=6)
			Pos = Pos-6;
		break;

	case '2':
	case 'X'-0x40:	/* ^X */
	case DOWNKEY:
		if	(Pos>=96-6 || (Page==Pagenum-1 && Pos+6>=Lastnum) )
			;	/* Pos>=Lastnum-6では、Lastnum-6<0となって   */
		else		/* Posがunsignedの為正確に判断できない場合有 */
			Pos = Pos+6;
		break;

	case '-':
		if	(Page>=1)
		{
			Page--;
			putpage(1);
		}
		break;

	case '+':
		if	(Page<Pagenum-1)
		{
			Page++;

			if	(Page==Pagenum-1 && Pos>=Lastnum)
				Pos = Lastnum-1;

			putpage(1);
		}
		break;

	case ' ':
		if	(Dirtbl[Page*96+Pos]->filename[0]!='.')
			return c;
		else
			dm_errmes("\".\"や\"..\"に対しては操作できません.");
		break;

	case '\033':
		return c;

	default:
		if	(flag)
			return c;

		break;
	}

	goto LOOP;
}

unsigned int	dmmenu(dirtbl,dirnum,cursorpos)
struct DIRENTRY	far **dirtbl;
unsigned int	dirnum,cursorpos;
{

	struct DIRENTRY	far *d;
	unsigned int	i;

	Dirtbl = dirtbl;	/* 下請関数でも値を使えるようにするため */

	Selected = -1;

	Pagenum = dirnum/96;
	Lastnum = dirnum%96;
	if	(Lastnum)	Pagenum++;
	else			Lastnum = 96;

	if	(cursorpos>dirnum)	/* cursorposが不正な場合 */
		cursorpos = 0;

	Page = cursorpos/96;
	Pos  = cursorpos%96;

	putpage(1);

dmmenu_loop:;

	switch(movecursor(1))
	{
	case 'I':
	case 'i':
		if	((d=dirtbl[dirnum-1])->filename[0]=='\xe5')
		{
			for	(i=dirnum-1 ; i>Page*96+Pos ; i--)
				dirtbl[i] = dirtbl[i-1];

			dirtbl[Page*96+Pos] = d;

			putpage(0);
		}
		else
			putchar('\7');

		break;

	case 'D':
	case 'd':
		if	((d=dirtbl[Page*96+Pos])->filename[0]=='\xe5')
		{
			for	(i=Page*96+Pos ; i<dirnum-1 ; i++)
				dirtbl[i] = dirtbl[i+1];

			dirtbl[dirnum-1] = d;
			putpage(0);
		}
		else
			putchar('\7');

		break;

	case ' ':
		Selected = Page*96+Pos;

		putfilename(Pos);			/* 反転表示 */
		if	(movecursor(0)==' ' && Selected!=Page*96+Pos)
		{
			d = dirtbl[Selected];
			dirtbl[Selected] = dirtbl[Page*96+Pos];
			dirtbl[Page*96+Pos] = d;
		}

		if	(Selected/96 == Page)		/* 反転を解除 */
		{
			i = Selected%96;
			Selected = -1;
			putfilename(i);
		}
		else
			Selected = -1;

		putfilename(Pos);

		break;

	case 'S':
	case 's':
		Selected = Page*96+Pos;

		putfilename(Pos);			/* 反転表示 */

		printf( "\033[19;1f\033[37m"
			"ソート:終点を指定してください\n");

		if	(movecursor(0)==' ' && Selected!=Page*96+Pos)
		{
			unsigned int	s = Selected,
					e = Page*96+Pos;

			if	(s>e)
			{
				register unsigned int	a = e;
				e = s;
				s = a;
			}

			dmsort(dirtbl,s,e);
		}

		printf("\033[19;1f\033[2K");
		Selected = -1;
		putpage(0);

		break;

	case 'C':
	case 'c':
	case '\r':
		if	((dirtbl[Page*96+Pos]->attr & _A_SUBDIR)
			&& dirtbl[Page*96+Pos]->filename[0]!='.')
			return (Page*96+Pos)*4 + CHGDIR;
		break;

	case 'O':
	case 'o':
		return (Page*96+Pos)*4 + ORIGIN;

	case 'U':
	case 'u':
	case '\033':
			return (Page*96+Pos)*4+UPDIR;

	case 'W':
	case 'w':
		return (Page*96+Pos)*4 + WRTDIR;

	case 'Q':
	case 'q':
		endscreen();

	default:
		putchar('\7');
	}
	goto dmmenu_loop;
}
