#pragma ident "@(#) ftpfrm.cc 1.2.2 2012.12.10,14:57"
#include "ftx.h"
#include "filer.h"

//以下のインスタンス名は本ライブラリで固定されている。
ListBox *pFilerListBox;	//ファイラーのためのリストボックスクラス
ListBox *pListBox;	//ホスト、ユーザ、パスワードを管理するリストボックスクラス
ListBox *ImmLog;	//FTPとの応答を記録するリストボックスクラス（詳細情報）
OpenFileListBox *ftp;	//サーバ側のファイル情報を抽出するためのクラス
LocalFiler *minicw;	//ファイル選択用のミニファイラーを表示するクラス
//JmvwGetnStr *jw;	//

extern "C" void FTPConnect(void);
extern "C" int filer(int,int);
extern "C" int jmvwgetnstr(WINDOW *win, int y, int x, unsigned char *str, int n, int wmode, int cmode);

//本プログラムは PDS です。利用者の責任で変更改編出来ます。
//本プログラムはとても大きなサンプルプログラムですが、難しいところはクラス内で部品化されているので楽しく改変出来ます。
//このまま FTP として利用可能です。
//クラスライブラリを活用することが出来るのでアップグレードが最適です。
//パスワードは現在生見えなのでセキュリティは利用者におまかせします。
//FTXの核となるソースファイル ftplib.cc と ftpcom.cc を同梱してありますのでそれを参考にアップグレードしてください。
//本プログラムを使用して損害を被っても作者は全く責任を負いません。
//2009年7月16日 Shigeki Ono

//-1 で終了処理へ 2 で再接続へ その他はLIST コマンドで画面更新
void frmSockFTP::ftx(void)
{
	int ret;

	while(1)
	{
		ftp->ExtractFileListBox(txtTmpDirListFile);
		sprintf(ftp->title,"%s",cdHostPath);

		ret = ftp->FilerListbox(txtEditDir);
		switch(ret)
		{
		case 2:
			ftp->Clear();
			intDoReConnect(cdHostPath);
			break;
		case -1:
			ftp->Clear();
			return;
		default:
			ftp->Clear();
			intDoListCommand();
			break;
		}
	}
}

void frmSockFTP::ftx2(void)
{
	int ret;

	ftp->ExtractFileListBox(txtTmpDirListFile);
	sprintf(ftp->title,"%s",cdHostPath);

	ftp->Filerbox(txtEditDir);
	intDoListCommand();
}


//以下は frmSockFTP クラスのコマンドライブラリとのインターフェース

//テンポラリを設定する
void frmSockFTP::setTmpDir(void)
{
	char *tmp,*home;

	tmp_pid = getpid();
	if((tmp = getenv("TMP")) != (char *)NULL)
	{
		if(strlen(tmp) == 0)
		{
			MsgBox("$TMP に変数がセットされていません。");
			endwin();
			exit(2);
		}
		sprintf(txtTmpDir,"%s",tmp);
		sprintf(txtTmpDirListFile,"%s/ftx-%d/%s",txtTmpDir,tmp_pid,"LIST.CMD");
#ifdef CYGWIN
		sprintf(txtEditDir,"c:/cygwin%s/ftx-%d",txtTmpDir,tmp_pid);
#else
		sprintf(txtEditDir,"%s/ftx-%d",txtTmpDir,tmp_pid);
#endif
		if(mkdir(txtEditDir,S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWOTH|S_IWGRP|S_IXUSR|S_IXGRP|S_IXOTH) == -1)
		{
			MsgBox("$TMP にテンポラリディレクトリを作成出来ません。");
			endwin();
			exit(2);
		}
	}
	else
	{
		if((home = getenv("HOME")) != (char *)NULL)
		{
			if(strlen(home) == 0)
			{
				MsgBox("$HOME に変数がセットされていません。");
				endwin();
				exit(2);
			}
			sprintf(txtTmpDir,"%s",home);
			sprintf(txtTmpDirListFile,"%s/ftx-%d/%s",home,tmp_pid,"LIST.CMD");
			sprintf(txtEditDir,"%s/ftx-%d",home,tmp_pid);
			if(mkdir(txtEditDir,S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWOTH|S_IWGRP|S_IXUSR|S_IXGRP|S_IXOTH) == -1)
			{
				MsgBox("$HOME にテンポラリディレクトリを作成出来ません。");
				endwin();
				exit(2);
			}
		}
		else
		{
			sprintf(txtTmpDir,"/tmp");
			sprintf(txtTmpDirListFile,"%s/ftx-%d/%s",txtTmpDir,tmp_pid,"LIST.CMD");
			sprintf(txtEditDir,"%s/ftx-%d",txtTmpDir,tmp_pid);
			if(mkdir(txtEditDir,S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWOTH|S_IWGRP|S_IXUSR|S_IXGRP|S_IXOTH) == -1)
			{
				MsgBox("/tmp にテンポラリディレクトリを作成出来ません。");
				endwin();
				exit(2);
			}
		}
	}
}

//ホスト設定ファイルを読み込む
void frmSockFTP::readHostSetFile(void)
{
	FILE *fp;
	int i;
	int n = 0;
	char buff[256], path[256];;
	char *nwl;
	char *env;

	if((env = getenv("CMSPATH")) == NULL)
	{
		sprintf(path,"/home/cms/etc/hosts.ftx");
	}
	else
	{
		sprintf(path,"%s/etc/hosts.ftx",env);
	}
	sprintf(txtPasswordFile,"%s",path);
	if((fp = fopen(path,"rb")) == NULL)
	{
		return;
	}

	while(fgets(buff,255,fp) != NULL)
	{
		if((nwl = strchr(buff,'\n')) != NULL)
		{
			if(n > 254)
			{
				fclose(fp);
				return;
			}
			nwl = '\0';
			writeListBox(buff,n);
			n++;
		}
	}
	fclose(fp);
}

//ホスト設定ファイルにある内容を各ホストごとにクラスのバッファに保存
void frmSockFTP::writeListBox(char *host,int n)
{
	int i,j,k;
	int len;
	int cnt;
	char buff[256];
	char buff2[256];
	
	cnt = 0;
	len = strlen(host);
	for(i=0,j=0;i<len;i++)
	{
		switch(host[i])
		{
		case ':':
			buff[j] = '\0';
			switch(cnt)
			{
			//ホスト名を読み取りバッファに保存
			case 0:
				sprintf(pFilerListBox->pf[n].hostname,"%s",buff);
				break;
			//ホスト名とユーザID をリストボックスに追加する
			case 1:
				sprintf(pFilerListBox->pf[n].userid,"%s",buff);
				sprintf(buff,"%s: User=%s",pFilerListBox->pf[n].hostname,pFilerListBox->pf[n].userid);
				//リストボックスに追加
				pListBox->AddItem(buff);
				break;
			//パスワードをバッファに保存
			case 2:
				sprintf(pFilerListBox->pf[n].passwd,"%s",buff);
				break;
			//接続時最初に表示するディレクトリをバッファに保存
			case 3:
				sprintf(pFilerListBox->pf[n].homedir,"%s",buff);
				break;
			//LISTコマンドとオプション等
			case 4:
				if(strlen(buff) == 0)
				{
					sprintf(pFilerListBox->pf[n].OPTL,"%s","LIST");
					break;
				}
				sprintf(pFilerListBox->pf[n].OPTL,"%s",buff);
				break;
			//アスキー転送(0)かバイナリ転送(1)か
			case 5:
				if(strlen(buff) == 0)
				{
					pFilerListBox->pf[n].TYPE = 1;
					break;
				}
				pFilerListBox->pf[n].TYPE = atoi(buff);
				break;
			//Active モードか、Passive モードか
			case 6:
				if(strlen(buff) == 0)
				{
					pFilerListBox->pf[n].PASV = 0;
					break;
				}
				for(k=0;k<strlen(buff);k++) {
					buff2[k] = toupper(buff[k]);
				}
				buff2[k] = '\0';
				if((!strcmp(buff2,"PASSIVE")) || (!strcmp(buff2,"PASV")))
				{
					pFilerListBox->pf[n].PASV = 1;
				}
				else
				{
					pFilerListBox->pf[n].PASV = 0;
				}
				break;
			//サーバへの再接続までの時間（秒）
			case 7:
				if(strlen(buff) == 0)
				{
					pFilerListBox->pf[n].WAIT = 300;
					break;
				}
				//接続時間（秒）は決してゼロ秒にしないこと
				pFilerListBox->pf[n].WAIT = atoi(buff);
				break;
			//テキストエディター
			case 8:
				if(strlen(buff) == 0)
				{
					sprintf(pFilerListBox->pf[n].editor,"%s","vi");
					break;
				}
				sprintf(pFilerListBox->pf[n].editor,"%s",buff);
				break;
			//画像ビューワー
			case 9:
				if(strlen(buff) == 0)
				{
#ifdef CYGWIN
					sprintf(pFilerListBox->pf[n].viewer,"%s","/cygdrive/c/\"Program Files\"/Real/RealPlayer/realplay.exe");
#else
					sprintf(pFilerListBox->pf[n].viewer,"%s","eog");
#endif
					break;
				}
				sprintf(pFilerListBox->pf[n].viewer,"%s",buff);
				break;
			//ブラウザ
			case 10:
				if(strlen(buff) == 0)
				{
#ifdef CYGWIN
					sprintf(pFilerListBox->pf[n].browser,"%s","/cygdrive/c/\"program files\"/\"internet explorer\"/iexplore.exe");
#else
					sprintf(pFilerListBox->pf[n].viewer,"%s","epiphany");
#endif
					break;
				}
				sprintf(pFilerListBox->pf[n].browser,"%s",buff);
				break;
			}
			cnt++;
			j = 0;
			break;
		default:
			buff[j] = host[i];
			j++;
			break;
		}
	}
	sprintf(host,"%s",buff);
}

//右側の文字を n 文字返す
char *frmSockFTP::Right(char *s, size_t n)
{
	int i;
	size_t n2;
	char s1[MAX_DATA_BUFF];
	static char s2[MAX_DATA_BUFF];
	char *sr;
	n2 = (size_t)strlen(s) - n;
	for(i=n2; s[i] != '\0';i++)
	{
		s1[i-n2] = s[i];
	}
	s1[i-n2] = '\0';
	strcpy(s2,s1);
	sr = s2;
	return(sr);
}

//左側の文字を n 文字返す
char * frmSockFTP::Left(char *s, size_t n)
{
	int i;
	char s1[MAX_DATA_BUFF];
	static char s2[MAX_DATA_BUFF];
	char *sr;
	for(i=0; s[i] == '\0'|| i < n;i++)
	{
		s1[i] = s[i];
	}
	s1[i] = '\0';
	strcpy(s2,s1);
	sr = s2;
	return(sr);
}

//文字 str の中の左側 start 位置から c 文字までの数を返す
int frmSockFTP::InStr(int start, char *str, int c)
{
	int i;
	for(i=start;i<strlen(str);i++)
	{
		if(str[i] == c)
		{
			return(i);
		}
	}
	return(0);
}

//文字 str の中の右側から c 文字までの数を返す
int frmSockFTP::rInStr(char *s, int c)
{
	int i, j, k;

	k =0;
	j = strlen(s);
	for(i=j;i>0;i--)
	{
		if(s[i] == c)
			break;
		k++;
	}
	if(i < 1)
		return(0);
	i++;
	return(i);
}

//文字列 ss の位置 a から 数 b までの文字の取り出し
char *frmSockFTP::Mid(char *ss, int a, int b)
{
	int k;
	size_t n;
	char *ds;
	static char retds[MAX_DATA_BUFF];

	n=strlen(ss);
	ds = (char *)malloc(n+1);
	if((0<a && a<=n) && (0<b && b<=n) && (a+b-1<=n)){
		for(k=a; k<a+b; k++)
		    ds[k-a]=ss[k-1];
		ds[b]='\0';
	}
	else
		ds[0]='\0';
	sprintf(retds,"%s",ds);
	free(ds);
	return((char *)retds);
}

//文字列 s の中を 文字 t で検索する
int frmSockFTP::Findex(char *s,char *t)
{
	int i, j, k;

	for(i=0;s[i] != '\0';i++)
	{
		for (j=i,k=0;t[k] != '\0' && s[j] == t[k];j++,k++)
			;
		if (t[k] == '\0')
			return(i);
	}
	return(-1);
}

//ASCII コードより大きいコードの文字の判定
int frmSockFTP::IsKanji(char *s)
{
	int i;
	int c;
	for(i=0;i<strlen(s);i++)
	{
		c = s[i] & 0xff;
		//2010.03.07
		//これ以上だった
		if(c >= 0x80)
		{
			return(TRUE);
		}
	}
	return(FALSE);
}

//----------------------------------------------------------------------------
//リストボックスを操作するメンバ関数。

//ファイラーリストボックスを生成するための文字列からファイル名位置を取得
void OpenFileListBox::ExtractFileListBox(char *name)
{
	FILE *fp;
	char *p;
	char *nl;
	char buff[1024];
	int i;
	int maxpos;
	int spos;

	char tmpbuff[1024];

	if((fp = fopen(name,"r")) == NULL) {
		return;
	}

	i = 0;
	while(fgets(buff,1024,fp) != (char *)NULL)
	{
		if((nl = (char *)strchr(buff,'\n')) != (char *)NULL)
		{
			*nl = '\0';
			if(*(nl-1) == '\r')
				*(nl-1) = '\0';
			AddItem(buff);
			if(IsKanji(buff) == TRUE)
			{
				//2010.03.07
				//漢字はとりあえず無視することにした。
				;
			}
			else
			{
				strLISTfilePos = rInStr(itemlist[i], ' ');
			}
			if(Findex(buff, (char *)"->") != -1) {
				//2010.03.07
				//シンボリックリンクはシンボル用文字から逆に戻って探す
				spos = InStr(1, buff, '>');
				buff[spos - 2] = '\0';
				strLISTfilePos = rInStr(buff, ' ');
			}
			i++;
		}
	}
	maxline = i;
	fclose(fp);
}

//ディレクトリ移動時の履歴と階層を保存するバッファを初期化する
void ListBox::InitCursol(int deep)
{
	int i;
	for (i=deep;i<256;i++)
	{
		memset(pFilerListBox->dirlocate[i],'\0',512);
		pFilerListBox->dirlocatey[i] = 0;
		pFilerListBox->dirlocateyy[i] = 0;
	}
	deep = 0;
}

//受信または送信ファイルの属性を調査
char *ListBox::setChmod(char *attr)
{
	static char buff[32];
	int at[9];
	int i,j;
	memset(at,0,sizeof(at));
	for(i=0;i<strlen(attr);i++)
	{
		switch(i)
		{
		case 1:
			switch(attr[i])
			{
			case '-':
				at[0] = 0;
				break;
			case 'r':
				at[0] = 4;
				break;
			}
			break;
		case 2:
			switch(attr[i])
			{
			case '-':
				at[1] = 0;
				break;
			case 'w':
				at[1] = 2;
				break;
			}
			break;
		case 3:
			switch(attr[i])
			{
			case '-':
				at[2] = 0;
				break;
			case 'x':
				at[2] = 1;
				break;
			}
			break;
		case 4:
			switch(attr[i])
			{
			case '-':
				at[3] = 0;
				break;
			case 'r':
				at[3] = 4;
				break;
			}
			break;
		case 5:
			switch(attr[i])
			{
			case '-':
				at[4] = 0;
				break;
			case 'w':
				at[4] = 2;
				break;
			}
			break;
		case 6:
			switch(attr[i])
			{
			case '-':
				at[5] = 0;
				break;
			case 'x':
				at[5] = 1;
				break;
			}
			break;
		case 7:
			switch(attr[i])
			{
			case '-':
				at[6] = 0;
				break;
			case 'r':
				at[6] = 4;
				break;
			}
			break;
		case 8:
			switch(attr[i])
			{
			case '-':
				at[7] = 0;
				break;
			case 'w':
				at[7] = 2;
				break;
			}
			break;
		case 9:
			switch(attr[i])
			{
			case '-':
				at[8] = 0;
				break;
			case 'x':
				at[8] = 1;
				break;
			}
			sprintf(buff,"%d%d%d",at[0]+at[1]+at[2],at[3]+at[4]+at[5],at[6]+at[7]+at[8]);
			break;
		}
	}
	return((char *)buff);
}

//ファイル送信時の後で SITE コマンドで属性を設定するときに使用
void ListBox::attrview(int at,char *attrbuff)
{
	int i;
	char buff[128];
	char ubuff[3][2];
	char gbuff[3][2];
	char obuff[3][2];
	char lbuff[32];

		/*
		_S_IFMT   0170000	   type of file   
		_S_IFREG  0100000	   regular   
		_S_IFBLK  0060000	   block special   
		_S_IFCHR  0020000	   character special   
		_S_IFDIR  0040000	   directory   
		_S_IFIFO  0010000	   pipe or FIFO   
		*/
	if(S_ISDIR(at))
	{
		if(at & S_IFDIR)
		{
			strcpy(buff,"d");
		}
	}
	else
	{
		if(at & S_IFMT)
		{
			strcpy(buff,"-");
		}
		if(S_ISCHR(at))
		{
			strcpy(buff,"c");
		}
		if(S_ISFIFO(at))
		{
			strcpy(buff,"p");
		}
		if(S_ISBLK(at))
		{
			strcpy(buff,"b");
		}
		if(S_ISLNK(at))
		{
			strcpy(buff,"l");
		}
	}

	if(at & S_IRWXU)
	{
		strcpy(ubuff[0],"r");
		strcpy(ubuff[1],"w");
		strcpy(ubuff[2],"x");
	}
	if(at & S_IRWXG)
	{
		strcpy(gbuff[0],"r");
		strcpy(gbuff[1],"w");
		strcpy(gbuff[2],"x");
	}
	if(at & S_IRWXO)
	{
		strcpy(obuff[0],"r");
		strcpy(obuff[1],"w");
		strcpy(obuff[2],"x");
	}

	if(at & S_IRUSR)
		strcpy(ubuff[0],"r");
	else
		strcpy(ubuff[0],"-");

	if(at & S_IWUSR)
		strcpy(ubuff[1],"w");
	else
		strcpy(ubuff[1],"-");

	if(at & S_IXUSR)
		strcpy(ubuff[2],"x");
	else
		strcpy(ubuff[2],"-");


	if(at & S_IRGRP)
		strcpy(gbuff[0],"r");
	else
		strcpy(gbuff[0],"-");

	if(at & S_IWGRP)
		strcpy(gbuff[1],"w");
	else
		strcpy(gbuff[1],"-");

	if(at & S_IXGRP)
		strcpy(gbuff[2],"x");
	else
		strcpy(gbuff[2],"-");


	if(at & S_IROTH)
		strcpy(obuff[0],"r");
	else
		strcpy(obuff[0],"-");

	if(at & S_IWOTH)
		strcpy(obuff[1],"w");
	else
		strcpy(obuff[1],"-");

	if(at & S_IXOTH)
		strcpy(obuff[2],"x");
	else
		strcpy(obuff[2],"-");


	if(at & S_ISUID)
	{
		if(at & S_IXUSR)
			strcpy(ubuff[2],"s");
		else
			strcpy(ubuff[2],"S");
	}
	if(at & S_ISGID)
		strcpy(gbuff[2],"s");
	if(at & S_ISVTX)
	{
		if(at & S_IXUSR)
			strcpy(obuff[2],"t");
		else
			strcpy(obuff[2],"T");
	}

	sprintf(attrbuff,"%-1s%-1s%-1s%-1s%-1s%-1s%-1s%-1s%-1s%-1s",buff,ubuff[0],ubuff[1],ubuff[2],gbuff[0],gbuff[1],gbuff[2],obuff[0],obuff[1],obuff[2]);
}

//ファイラーリストボックスを保存する
int OpenFileListBox::SaveFileListBox(char *name)
{
	FILE *fp;
	int line = 0;
	char *sp;
	char pathname[256];

	if((sp = getenv("HOME")) == NULL)
	{
		return(FALSE);
	}
	else
	{
		sprintf(pathname,"%s/%s",sp,name);
	}

	if((fp = fopen(pathname,"w")) == (FILE *)NULL)
	{
		return(FALSE);
	}
	while(itemlist[line][0] != '\0')
	{
		fprintf(fp,"%s\n",itemlist[line]);
		line++;
	}
	maxline = line;
	fclose(fp);
	return(TRUE);
}

//ポップアップメッセージ
int PopMsg::popmsg(int y,int x,const std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(3,90,y,x);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	for(;;)
	{
		wattron(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[PopMsg]");
		wattroff(pvs,A_REVERSE);

		mvwprintw(pvs,1,4,"[%s]",Message.c_str());
		mvwprintw(pvs,1,70,"Y or N :");
		wrefresh(pvs);
		ch = wgetch(pvs);
		switch(ch)
		{
		case 'y': case 'Y':
			delwin(pvs);
			return(TRUE);
		case 'n': case 'N':
			delwin(pvs);
			return(FALSE);
		}
	}
}

//ポップアップメッセージ（string版)
int PopMsg::popmsgBig(int y,int x,const std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(20,90,y,x);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	for(;;)
	{
		wattron(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[PopMsgBig]");
		wattroff(pvs,A_REVERSE);

		mvwprintw(pvs,1,4,"[%s]",Message.c_str());
		mvwprintw(pvs,18,70,"Y or N :");
		wrefresh(pvs);
		ch = wgetch(pvs);
		switch(ch)
		{
		case 'y': case 'Y':
			delwin(pvs);
			return(TRUE);
		case 'n': case 'N':
			delwin(pvs);
			return(FALSE);
		}
	}
}

//ポップアップメッセージ（エラー用 Y or N が無い)
void PopMsg::errormsg(int y,int x,const std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(4,90,y,x);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	wattron(pvs,A_REVERSE);
	mvwprintw(pvs,0,1,"[ErrorMessage]");
	wattroff(pvs,A_REVERSE);

	mvwprintw(pvs,1,4,"%s",Message.c_str());
	wrefresh(pvs);
	delwin(pvs);
}

//ポップアップメッセージ（string版　エラー用 Y or N が無い)
void PopMsg::ErrorMsg(const std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(4,90,LINES/2,(90/2)-24);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	wattron(pvs,A_REVERSE);
	mvwprintw(pvs,0,1,"[ErrorMessage]");
	wattroff(pvs,A_REVERSE);

	mvwprintw(pvs,1,4,"%s",Message.c_str());
	wrefresh(pvs);
	delwin(pvs);
}

//ダイアログメッセージ（止まらないメッセージ）
void PopMsg::dialogmsg(int y,int x,const std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(3,90,y,x);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	wattron(pvs,A_REVERSE);
	mvwprintw(pvs,0,1,"[DialogMessage]");
	wattroff(pvs,A_REVERSE);

	mvwprintw(pvs,1,4,"%s",Message.c_str());
	wrefresh(pvs);
	delwin(pvs);
}

//メッセージボックス（string版 画面中央に表示)
int PopMsg::MsgBox2(const std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(6,48,LINES/2,(90/2)-24);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	for(;;)
	{
		wattron(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[MsgBox2]");
		wattroff(pvs,A_REVERSE);

		mvwprintw(pvs,2,4,"[%s]",Message.c_str());
		mvwprintw(pvs,3,30,"Y or N :");
		wrefresh(pvs);

		ch = wgetch(pvs);
		switch(ch)
		{
		case 'y': case 'Y':
			delwin(pvs);
			return(TRUE);
		case 'n': case 'N':
			delwin(pvs);
			return(FALSE);
		default:
			delwin(pvs);
			break;
		}
	}
}

//メッセージボックス（string版 大きい表示)
int PopMsg::MsgBoxBig(std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(10,70,LINES/2,(90/2)-24);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	for(;;)
	{
		wattron(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[MsgBoxBig]");
		wattroff(pvs,A_REVERSE);

		mvwprintw(pvs,2,4,"[%s]",Message.c_str());
		mvwprintw(pvs,8,40,"Y or N :");
		wrefresh(pvs);

		ch = wgetch(pvs);
		switch(ch)
		{
		case 'y': case 'Y':
			delwin(pvs);
			return(TRUE);
		case 'n': case 'N':
			delwin(pvs);
			return(FALSE);
		default:
			delwin(pvs);
			break;
		}
	}
}

//メッセージボックス（string版 画面中央に表示)
void PopMsg::MsgBox(std::string Message)
{
	WINDOW *pvs;
	int i;
	int ch;

	pvs = newwin(6,48,LINES/2,(90/2)-24);
	box(pvs,ACS_VLINE,ACS_HLINE);
	noecho();
	for(;;)
	{
		wattron(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[MsgBox]");
		wattroff(pvs,A_REVERSE);

		mvwprintw(pvs,2,4,"[%s]",Message.c_str());
		mvwprintw(pvs,3,18,"何かのキーを押して下さい。");
		wrefresh(pvs);

		ch = wgetch(pvs);
		switch(ch)
		{
		default:
			delwin(pvs);
			return;
		}
	}
}

//日本語入力用ポップアップ。
void *PopMsg::input_window(int y,int x,char *buff,const std::string Message)
{
	WINDOW *mvs;
	int ret;

	mvs = newwin(4,90,y,x);
	wattroff(mvs,A_REVERSE);
	box(mvs,ACS_VLINE,ACS_HLINE);
	mvwprintw(mvs,1,4,Message.c_str());
	wattron(mvs,A_REVERSE);
	mvwprintw(mvs,0,0,"Input  Window");

	mvwprintw(mvs,2,4,"                                                     ");
	wrefresh(mvs);

	mvwprintw(mvs,2,4,"                                                     ");
	echo();
	nocbreak();
	nl();
	ret = jmvwgetnstr(mvs,2,4,(unsigned char *)buff,72,1,1);
	switch(ret)
	{
	case 0x1b:
		break;
	default:
		break;
	}
	noecho();
	cbreak();

	wrefresh(mvs);

	wattroff(mvs,A_REVERSE);
	noecho();
	delwin(mvs);
	return(NULL);
}

void *PopMsg::input_window(int y,int x,char *buff,char *buff2,const std::string Message)
{
	WINDOW *mvs;
	int ret;

	mvs = newwin(4,90,y,x);
	wattroff(mvs,A_REVERSE);
	box(mvs,ACS_VLINE,ACS_HLINE);
	mvwprintw(mvs,1,4,Message.c_str());
	wattron(mvs,A_REVERSE);
	mvwprintw(mvs,0,0,"Input  Window");

	mvwprintw(mvs,2,4,"                                                     ");
	wrefresh(mvs);

	mvwprintw(mvs,2,4,"                                                     ");
	echo();
	nocbreak();
	nl();
	strcpy(buff,buff2);
	ret = jmvwgetnstr(mvs,2,4,(unsigned char *)buff,72,1,1);
	switch(ret)
	{
	case 0x1b:
		break;
	default:
		break;
	}
	noecho();
	cbreak();

	wrefresh(mvs);

	wattroff(mvs,A_REVERSE);
	noecho();
	delwin(mvs);
	return(NULL);
}

//リストボックス。ホスト選択時に利用する。
char * ListBox::Listbox(void)
{
	WINDOW *pvs;

	int ch;
	int i;

	int j = cursol;
	int yy = line;
	int ylen = height-1;
	static char result[256];
	char strCommand[256];
	char findstr[256];
	int findf = 0;
	char buff[256];

	pvs = newwin(height,width,sy,sx);
	wattron(pvs,A_REVERSE);
	box(pvs,' ',' ');
	wattroff(pvs,A_REVERSE);
	mvwprintw(pvs,0,1,"[%s]",title);

	for(;;)
	{
		wattron(pvs,A_REVERSE);
		box(pvs,' ',' ');
		for(i=0;i<ylen-1;i++)
		{
			memset(initmenu[i],' ',width-1);
			mvwprintw(pvs,i+1,0,"%s",initmenu[i]);
			sprintf(initmenu[i],"%s",itemlist[i+yy]);
			mvwprintw(pvs,i+1,1,"%s",initmenu[i]);
		}
		wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[%s]",title);

		wmove(pvs,j+1,2);
		wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,j+1,1,"%s",initmenu[j]);
		wattron(pvs,A_REVERSE);

		wrefresh(pvs);
        ch = wgetch(pvs);

        switch(ch)
        {
		//文字を検索する
		case '/':
		input_window(1,0,findstr,"検索名を入力");
		if(strlen(findstr) < (size_t)0)
			strcpy(findstr," ");
		//再検索する
		case 'n':
			if(strlen(findstr) < (size_t)1)
				break;
			j++;
			for(;j+yy<maxline;j++)
			{
				sprintf(buff,"%s",Mid(itemlist[j+yy],strLISTfilePos+1,strlen(itemlist[j+yy])-strLISTfilePos));
				if(findf = Findex(buff, findstr) != -1)
				{
				//	popmsg(20,0,itemlist[j+yy]);
					yy = yy + j;
					j = 0;
					break;
				}
			}
			if(j+yy > maxline -1)
			{
				j = 0;
				yy = 0;
				break;
			}
			break;

		case '': case 'U':
		/*
		半ページ上へ
		*/
			for(i=0;i<(ylen/2)-2;i++)
			{
				j -= 1;
				if(j < 1)
				{
					j = 0;
					break;
				}
			}
			for(i=0;i<(ylen/2)-2;i++)
				if(j == 0 &&  yy > 0)
					yy--;
			break;
		case '': case 'D': case 'd':
		/*
		半ページ下へ
		*/
			if(j > ylen - (ylen/2)-0)
			{
				for(i=0;i<(ylen/2)-1;i++)
				{
            		if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
						break;
					yy++;
           		}
				break;
			}
			for(i=0;i<(ylen/2)-1;i++)
			{
            	if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
					break;
				j += 1;
				if(j >= MAX_LIST - ylen)
				{
					j = MAX_LIST - ylen;
					break;
				}
			}
			break;
		/*
		リストボックス画面の最後に
		*/
        case 'g':
			if(maxline < ylen)
			{
				j = maxline - 1;
				break;
			}
			if(j + yy > maxline)
				break;
			j = ylen - 2;
			yy = (maxline - ylen)+1;
			break;
		/*
		リストボックス画面のトップに
		*/
        case 't':
			j = 0;
			yy = 0;
			break;
		/*
		下スクロール
		*/
        case 'j': case 0x42:
            if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
                break;
			if(yy > maxline)
				break;
            if(j > ylen - 3)
            {
                yy++;
				break;
            }
            if(j <= ylen - 3 && (maxline-1) > j)
            {
                j++;
            }
            break;
		/*
		上スクロール
		*/
        case 'k': case 0x41:
			j -= 1;
			if(j < 0)
			{
				j = 0;
				if(j == 0 &&  yy > 0)
				{
					yy--;
					break;
				}
			}
            break;
		/*
		Enter で決定
		*/
		case 0x0d: case 0x0a: case'Z':
			saveline(yy,j);
			sprintf(result,"%s",itemlist[(j+yy)]);
			delwin(pvs);
			ListIndex(yy,j);
			return(result);
		/*
		'q' で何もしないでリストボックスを終了
		*/
		case 'q':
			saveline(yy,j);
			delwin(pvs);
			return((char *)NULL);
		defualt:
			break;
		}
	}
}

static char ftxhelp[23][256] =
	{" X X キーダブルで再接続 ",
	" X S キーダブルでローカルファイラーに変身しTABにてファイルを選択して送信() ",
	" X E キーダブルで hosts.ftx を vi で編集 ",
	" X R キーダブルで TABにて複数選択したファイルを受信 ",
	" W W キーダブルで TABにて複数選択したファイルを削除 ",
	" R  でファイルの受信を行う。（選択しているファイルのみ） ",
	" ^H で hosts.ftx に登録された初期ディレクトに戻る ",
	" c  でディレクトリを移動 ",
	" i  でひとつ上のディレクトリに移動 ",
	" e  でファイルを編集 ",
	" v  で画像ファイルを表示 ",
	"  でファイルの属性変更 ",
	"  でファイルの削除。 ",
	" r  でディレクトリの削除 ",
	" m  でディレクトリの作成 ",
	" M  でファイル名の変更 ",
	" L  でイミディエイトウインドウに移動（'q'で戻る） ",
	" /  でファイル検索、'n' で再検索 ",
	" S  でファイルの送信（ファイル名入力） ",
	" j  と 'k' キーでファイラーカーソルの移動 ",
	" g  で画面最下行へ移動 ",
	" t  で画面トップに移動 ",
	" q  で終了 "
	};

void ListBox::helpmsg(int x,int y)
{
	WINDOW *pvs;
	int ch;
	int i;
	pvs = newwin(25,78,y,x);

	box(pvs,' ',' ');

	mvwprintw(pvs,0,1,"                                FTX HELP                             ");

	noecho();
	for(i=0;i<23;i++)
		mvwprintw(pvs,i+1,1,"%s",ftxhelp[i]);
	wrefresh(pvs);
	wgetch(pvs);
	delwin(pvs);
}

//ファイラーリストボックス。FTX のメイン操作を行う。
//'X''X' キーダブルで再接続
//'X''S' キーダブルでローカルファイラーに変身。ファイルを選択して送信 
//'X''E' キーダブルで hosts.ftx を vi で編集
//'X''R' キーダブルでTABにて複数選択したファイルを受信
//'W''W' キーダブルでTABにて複数選択したファイルを削除
//'R' でファイルの受信を行う。（選択しているファイルのみ）
//'' で hosts.ftx に登録された初期ディレクトに戻る
//'c' でディレクトリを移動
//'i' でひとつ上のディレクトリに移動
//'e' でファイルを編集
//'v' で画像ファイルを表示
//'' でファイルの属性変更
//'' でファイルの削除。
//'r' でディレクトリの削除
//'m' でディレクトリの作成
//'M' でファイル名の変更
//'L' でイミディエイトウインドウに移動（'q'で戻る）
//'/' でファイル検索、'n' で再検索/
//'S' でファイルの送信（ファイル名入力）
//'j' と 'k' キーでファイラーカーソルの移動
//'d' と 'u' キーでファイラーカーソルの上下半ページ移動
//'g' で画面最下行へ移動",
//'t' で画面トップに移動"
//'q' で終了

int ListBox::FilerListbox(char *strEditDir)
{
	WINDOW *pvs, *evs;

	int ch,ch2;		//ファイラーの入力キーの受付
	int i,k;		//よく使う変数

	//カーソル行は常に保存されている
	int j = pFilerListBox->dirlocatey[pFilerListBox->deep];

	//画面スクロール行は常に保存されている
	int yy = pFilerListBox->dirlocateyy[pFilerListBox->deep];

//	int j = cursol;	//保存されたカーソル行（未使用）
//	int yy = line;	//保存されたスクロール行（未使用）
	int ylen = height-1;	//ファイラー画面の高さ
	static char result[256];//Enterでカレント行のファイル名を格納
	char strCommand[256];	//送信するコマンドに入るファイル名
	char strFileName[256];	//送信するコマンドに入るファイル名
	char strEditCommand[256];//編集用ローカルファイル名
	pid_t pid;	//未使用
	int ret;	//for system()
	char *cret;	//for getcwd()
	int iret;	//for chdir()
	int arivetime, writetime;	//次のキー操作の時間
	char ftmp[256];	//ディレクトリに使用
	int ap;				//起動するアプリケーション用のフラグ
	char findstr[256];	//検索に使用
	int findf = 0;		//検索された文字列の文字の位置
	char buff[256];		//メッセージに使用
	char tmpbuff[256];	//メッセージのテンポラリに使用

	struct dirent *dp;	//ファイルの属性
	char attrbuff[256];	//ファイルの属性を判定すため利用
	int filer_maxline;	//ローカルファイラーに表示する最大行

	time_t start;	//キー操作開始の時間

	//TABキーによって選択されるファイルの処理のための初期化
	intCPnum = 0;
	for(k=0;k<256;k++)
		cpflag[k] = 0;
	for(k=0;k<FTX_MAX_FILES;k++)
		regline[k] = 0;

	pvs = newwin(height,width,sy,sx);
	wattron(pvs,A_REVERSE);
	box(pvs,' ',' ');
	wattroff(pvs,A_REVERSE);
	//ファイラー画面の下にコマンドメニューを表示
	evs = newwin(1,90,LINES-1,0);
	mvwprintw(evs,0,1,"[%s]",title);
	mvwprintw(evs,0,1,"chdir up recv edit find send Mv mkdir ^Remove Quit    ");
	mvwprintw(evs,0,52+2,"j down k up ^D down ^U up");
	wattron(evs,A_REVERSE);
	mvwprintw(evs,0,1,"%c",'c');
	mvwprintw(evs,0,7,"%c",'u');
	mvwprintw(evs,0,10,"%c",'');
	mvwprintw(evs,0,15,"%c",'e');
	mvwprintw(evs,0,20,"%c",'/');
	mvwprintw(evs,0,25,"%c",'S');
	mvwprintw(evs,0,30,"%c",'M');
	mvwprintw(evs,0,33,"%c",'m');
	mvwprintw(evs,0,39,"%c",'^');
	mvwprintw(evs,0,40,"%c",'R');
	mvwprintw(evs,0,47,"%c",'Q');

	mvwprintw(evs,0,52+2,"%c",'j');
	mvwprintw(evs,0,59+2,"%c",'k');
	mvwprintw(evs,0,64+2,"%c",'^');
	mvwprintw(evs,0,65+2,"%c",'D');
	mvwprintw(evs,0,72+2,"%c",'^');
	mvwprintw(evs,0,73+2,"%c",'U');
	wattroff(evs,A_REVERSE);
	start = time(NULL);
	for(;;)
	{
		start = time(NULL);

		wattron(pvs,A_REVERSE);
		box(pvs,' ',' ');
		for(i=0;i<ylen-1;i++)
		{
			memset(initmenu[i],' ',width-1);
			mvwprintw(pvs,i+1,1,"%s",initmenu[i]);

			sprintf(initmenu[i],"%s",itemlist[i+yy]);
			mvwprintw(pvs,i+1,2,"%s",initmenu[i]);

			if (regline[i+yy] == 1) {
				mvwprintw(pvs,i+1,1,"%s","*");
			} else {
				mvwprintw(pvs,i+1,1,"%s"," ");
			}
		}

		wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[%s]",title);

		wmove(pvs,j+1,2);
	//	wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,j+1,2,"%s",initmenu[j]);
		wattron(pvs,A_REVERSE);

		wrefresh(evs);
		wrefresh(pvs);
        ch = wgetch(pvs);

		if((time(NULL)-start) > pFilerListBox->intWAIT)
		{
			delwin(pvs);
			delwin(evs);
			return(2);
		}
		sprintf(buff,"以前の操作から %ld 秒経過。",time(NULL)-start,pFilerListBox->deep);
		dialogmsg(1,0,buff);

		switch(ch)
		{
		/*
		複数選択送受信（ファイルのみ）
		*/
		//ダブルキー操作で複数通信処理を行う（安全のため）
		case 'X':
			ch2 = wgetch(pvs);
			switch(ch2)
			{
			case 'X':
				//再接続（リターン2は再接続）
				delwin(pvs);
				delwin(evs);
				return(2);
			case 'S':
				//ミニファイラーを表示して複数選択の送信を行う
				minicw = new LocalFiler();
				filer_maxline = LINES;
				minicw->minifiler(1,filer_maxline);
				delete minicw;
				ImmLog->Immediatebox(0);
				return(0);

			case 'R':
				//TABキーにて複数ファイルを選択し、受信を行う
				sprintf(buff," %d 個のファイルを受信します。",intCPnum);
				if(popmsg(1,0,buff) == 1)
				{
					for (k=0;k<maxline;k++)
					{
						if(regline[k] == 1)
						{
							sprintf(strCommand,"%s",Mid(itemlist[k],strLISTfilePos+1,strlen(itemlist[k])-strLISTfilePos));
							if(!access(strCommand,R_OK))
							{
								sprintf(buff,"ファイル %s が存在します。実行しますか？",strCommand);
								if(popmsg(1,0,buff) == 1)
								{
#ifdef SENDANS
									sprintf(buff,"%s をサーバーから受信します",strCommand);
									if(popmsg(1,0,buff) == 1)
									{
#endif
										//2010.03.07
										//一旦既存のファイルを削除する。
										unlink(strCommand);
										sprintf(attrbuff,"%s",Left(itemlist[k],10));
										sprintf(buff,"chmod %s %s",setChmod(attrbuff),strCommand);
										intDoRETRCommand(strCommand, 1);
										ret = system(buff);
#ifdef SENDANS
									}
#endif
								}
							}
							else
							{
								sprintf(attrbuff,"%s",Left(itemlist[k],10));
								sprintf(buff,"chmod %s %s",setChmod(attrbuff),strCommand);
								intDoRETRCommand(strCommand, 1);
								ret = system(buff);
							}
						}
					}
				}
				intCPnum = 0;
				delwin(pvs);
				delwin(evs);
				return(0);

				//パスワードファイルを編集する
			case 'E':
				sprintf(buff,"vi %s",pFilerListBox->txtPasswordFile);
				ret = system(buff);
				clear();
				refresh();
				saveline(yy,j);
				delwin(pvs);
				delwin(evs);
				return(0);

			default:
				break;
			}
			break;
		/*
		複数選択削除（ファイルのみ）
		*/
		//ダブルキー操作で複数ファイルの削除処理を行う（安全のため）
		case '':
			ch2 = wgetch(pvs);
			switch(ch2)
			{
			case '':
				sprintf(buff," %d 個のファイルを削除します。",intCPnum);
				if(popmsg(1,0,buff) == 1)
				{
					for (k=0;k<maxline;k++)
					{
						if(regline[k] == 1)
						{
							sprintf(strCommand,"%s",Mid(itemlist[k],strLISTfilePos+1,strlen(itemlist[k])-strLISTfilePos));
							intDoRMFILECommand(strCommand);
						}
					}
				}
				intCPnum = 0;
				delwin(pvs);
				delwin(evs);
				return(0);

			default:
				break;
			}

		//TAB キーにて複数選択を行う。トグルキー操作
		case '\t':
			if(initmenu[j][0] != '-')
				break;
			if (intCPnum < 256)
			{
				sprintf(selcp[intCPnum],"%s",Mid(itemlist[j+yy],strLISTfilePos+1,strlen(itemlist[j+yy])-strLISTfilePos));
				if (regline[j+yy] == 1)
				{
					mvwprintw(pvs,j+1,1,"%s"," ");
					regline[j+yy] = 0;
					cpflag[intCPnum] = 0;
					intCPnum--;
				}
				else
				{
					mvwprintw(pvs,j+1,1,"%s","*");
					regline[j+yy] = 1;
					cpflag[intCPnum] = j+yy;
					intCPnum++;
				}
			}
			else
			{
				intCPnum = 0;
			}
			break;

		//ヘルプメッセージの表示
		case 'H':
			if(LINES > 31)
				helpmsg(1,9);
			else
				helpmsg(1,4);
			refresh();
			ImmLog->Immediatebox(0);
			break;
		//hosts.ftxにて初期ディレクトリに設定されたディレクトリに移動
		case '':
			strDoCWDCommand(pFilerListBox->txtHomeDir);

			delwin(pvs);
			delwin(evs);
			return(0);
			break;
		//ファイル名やディレクトリ名の検索
		case '/':
			memset(findstr,'\0',sizeof(findstr));
			input_window(1,0,findstr,"検索名を入力");
			if(strlen(findstr) < (size_t)0)
				strcpy(findstr," ");
		//ファイル名やディレクトリ名の再検索
		case 'n':
			if(strlen(findstr) < (size_t)1)
				break;
			j++;
			for(;j+yy<maxline;j++)
			{
				sprintf(buff,"%s",Mid(itemlist[j+yy],strLISTfilePos+1,strlen(itemlist[j+yy])-strLISTfilePos));
				if(findf = Findex(buff, findstr) != -1)
				{
				//	popmsg(20,0,itemlist[j+yy]);
					yy = yy + j;
					j = 0;
					break;
				}
			}
			if(j+yy > maxline -1)
			{
				MsgBox("検索が終わりました。最初に戻ります。");
				j = 0;
				yy = 0;
				break;
			}
			break;

		//画像ファイルやHTMLファイルをアプリで表示する
		case 'v':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			sprintf(strCommand,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
			if(initmenu[j][0] != '-')
				break;
			sprintf(strEditCommand,"%s/%s",strEditDir,strCommand);
			intDoVIEWCommand(strCommand, strEditCommand);

			stat(strEditCommand,fptr);
			arivetime = fptr->st_mtime;

			ap = 0;
			if(!strcmp(Right(strCommand,4),".jpg"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".JPG"))
				ap = 1;
			if(!strcmp(Right(strCommand,5),".jpeg"))
				ap = 1;
			if(!strcmp(Right(strCommand,5),".JPEG"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".gif"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".GIF"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".mp3"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".MP3"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".avi"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".AVI"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".ram"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".RAM"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".wmv"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".WMV"))
				ap = 1;
			if(!strcmp(Right(strCommand,5),".mpeg"))
				ap = 1;
			if(!strcmp(Right(strCommand,5),".MPEG"))
				ap = 1;
			if(!strcmp(Right(strCommand,4),".htm"))
				ap = 2;
			if(!strcmp(Right(strCommand,4),".HTM"))
				ap = 2;
			if(!strcmp(Right(strCommand,5),".html"))
				ap = 2;
			if(!strcmp(Right(strCommand,5),".HTML"))
				ap = 2;
			switch(ap)
			{
			case 1:
				sprintf(buff,"%s %s >/dev/null 2>&1",pFilerListBox->txtViewer,strEditCommand);
				break;
			case 2:
				sprintf(buff,"%s %s >/dev/null 2>&1",pFilerListBox->txtBrowser,strEditCommand);
				break;
			}
			ret = system(buff);
			if((time(NULL)-start) > pFilerListBox->intWAIT)
			{
				delwin(pvs);
				delwin(evs);
				return(2);
			}

			stat(strEditCommand,fptr);
			writetime = fptr->st_mtime;
			if(writetime > arivetime)
			{
				popmsg(1,0,"ファイルが変更されました。");
				cret = getcwd(ftmp,256);
				iret = chdir(strEditDir);
				intDoSTORCommand(strCommand, 0);
				stat(strCommand,fptr);
				attrview(fptr->st_mode,attrbuff);
				sprintf(buff,"%s",setChmod(attrbuff));
				strDoSITECommand("chmod",buff,strCommand);
				iret = chdir(ftmp);
			}
			unlink(strEditCommand);

			clear();
			refresh();
			saveline(yy,j);
			delwin(pvs);
			delwin(evs);
			return(0);

		//テキストエディタでファイルを編集。更新された場合は自動送信する。
		case 'e':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			sprintf(strCommand,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
			if(initmenu[j][0] != '-')
				break;
			sprintf(attrbuff,"%s",Left(initmenu[j],10));

			sprintf(strEditCommand,"%s/%s",strEditDir,strCommand);
			intDoEDITCommand(strCommand, strEditCommand, 0);

			sprintf(buff,"chmod %s %s/%s",setChmod(attrbuff),strEditDir,strCommand);
			ret = system(buff);

			stat(strEditCommand,fptr);
			arivetime = fptr->st_mtime;

			if(!strcmp(pFilerListBox->txtEditor,"vi"))
				sprintf(buff,"%s \"%s\"",pFilerListBox->txtEditor,strEditCommand);
			else
				sprintf(buff,"%s %s",pFilerListBox->txtEditor,strEditCommand);
			ret = system(buff);

			stat(strEditCommand,fptr);
			writetime = fptr->st_mtime;
			if(writetime > arivetime)
			{
				popmsg(1,0,"ファイルが変更されました。");
				cret = getcwd(ftmp,256);
				iret = chdir(strEditDir);
				if(intDoNOOPCommand() != 200)
				{
					MsgBox("切断されました。");
					delwin(pvs);
					delwin(evs);
					return(2);
				}
				intDoSTORCommand(strCommand, 0);
				stat(strCommand,fptr);

			//SYGWINでは以下を実行しないこと。
			//	attrview(fptr->st_mode,attrbuff);

				sprintf(buff,"%s",setChmod(attrbuff));
				strDoSITECommand("chmod",buff,strCommand);
				iret = chdir(ftmp);
			}
			if(intDoNOOPCommand() != 200)
			{
				MsgBox("切断されました。");
				delwin(pvs);
				delwin(evs);
				return(2);
			}
			unlink(strEditCommand);

			clear();
			refresh();
			saveline(yy,j);
			delwin(pvs);
			delwin(evs);
			return(0);

		//ファイルの受信（単一ファイル）
		case 'R':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			if(initmenu[j][0] != '-')
				break;

			sprintf(strCommand,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
			if(!access(strCommand,R_OK))
			{
				if(MsgBox2("ファイルが存在します。実行しますか？") == 1)
				{
					goto execRECV;
				}
				break;
			}
		execRECV:
			if(strCommand[0] == ' ')
			{
				strcpy(tmpbuff,Mid(strCommand,2,strlen(strCommand)-1));
				sprintf(strCommand,"%s",tmpbuff);
			}
			sprintf(buff,"[%s] をサーバーから受信します",strCommand);
			if(popmsg(1,0,buff) == 1)
			{
				sprintf(attrbuff,"%s",Left(initmenu[j],10));
				sprintf(buff,"chmod %s %s",setChmod(attrbuff),strCommand);
				unlink(strCommand);
				intDoRETRCommand(strCommand, 1);
				ret = system(buff);
				delwin(pvs);
				delwin(evs);
				return(0);
			}
			break;
		//ファイルの送信（単一ファイル）
		case 'S':
			memset(strCommand,'\0',sizeof(strCommand));
			memset(buff,'\0',sizeof(buff));
			input_window(1,0,strCommand,buff, "ファイル送信");
			if(access(strCommand,R_OK))
			{
				MsgBox("送信するファイルがありません。");
				break;
			}
			sprintf(buff,"%s をサーバーに送信します",strCommand);
			if(popmsg(1,0,buff) == 1)
			{
				intDoSTORCommand(strCommand, 1);

				stat(strCommand,fptr);
				attrview(fptr->st_mode,attrbuff);
				sprintf(buff,"%s",setChmod(attrbuff));
				strDoSITECommand("chmod",buff,strCommand);
				delwin(pvs);
				delwin(evs);
				return(0);
			}
			break;
		//ファイルのパーミッションの変更（単一ファイル）
		case '':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			memset(buff,'\0',sizeof(buff));
			memset(strFileName,'\0',sizeof(buff));
			sprintf(strFileName,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
			memset(strCommand,'\0',sizeof(strCommand));
			input_window(1,0,strCommand, "パーミッションの変更");
			if(strlen(strCommand) == 3 && (atoi(strCommand) >= 0 && atoi(strCommand) <= 777))
			{
				sprintf(buff,"%s",strCommand);
				strDoSITECommand("chmod",buff,strFileName);
				delwin(pvs);
				delwin(evs);
				return(0);
			}
			else
			{
				MsgBox("000 - 777 までの数字が必要です。");
				break;
			}
			break;
		//テスト用
		case 'x':
		//	ftp->ExtractFileListBox(txtTmpDirListFile);
		//	sprintf(ftp->title,"%s",cdHostPath);
		//	ftp->Clear();
			intDoReConnect(cdHostPath);
			break;
		//テスト用
		case 'p':
		//	sprintf(buff,"txtHostName=%s,passwd=%s,txtOPTL=%s,intTYPE=%d,intPASV=%d,intWAIT=%d",pFilerListBox->txtHostName,pFilerListBox->txtPassword,pFilerListBox->txtOPTL,pFilerListBox->intTYPE,pFilerListBox->intPASV,pFilerListBox->intWAIT);
		//	sprintf(buff,"%s",strExtractQuotedExpression(strDoPWDCommand()));
		//	sprintf(strCommand,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
		//	popmsg(1,0,strCommand);
			intDoNOOPCommand();
			break;
		//ディレクトリの移動
		case 'c': case 0x0d: case 0x0a:
			if(initmenu[j][0] != 'd' && pFilerListBox->txtOPTL[0] == 'L')
				break;
			sprintf(strCommand,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));

			sprintf(pFilerListBox->dirlocate[pFilerListBox->dirlocateyy[pFilerListBox->deep]], "%s",strCommand);
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			pFilerListBox->deep++;

			strDoCWDCommand(strCommand);

			delwin(pvs);
			delwin(evs);
			return(0);
		//ディレクトリを上に移動
		case 'i':
			if(strDoCDUPCommand() == (char *)NULL);
				InitCursol(pFilerListBox->deep);
			if(pFilerListBox->deep > 0)
			{
				pFilerListBox->deep--;
				j = pFilerListBox->dirlocatey[pFilerListBox->deep];
				yy = pFilerListBox->dirlocateyy[pFilerListBox->deep];
			}
			else
			{
				InitCursol(0);
				j = 0;
				yy = 0;
			}
			delwin(pvs);
			delwin(evs);
			return(0);
		//ファイルの削除
		case '':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			if(initmenu[j][0] != '-')
				break;
			if(intCPnum > 0)
			{
				if(MsgBox2("単独のファイルを削除すると、選択が無効になります。") == 0)
				{
					break;
				}
				else
				{
					intCPnum = 0;
				}
			}
			sprintf(strCommand,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
			sprintf(buff,"delete %s を実行します。",strCommand);
			if(popmsg(1,0,buff) == 1)
			{
				intDoRMFILECommand(strCommand);
				delwin(pvs);
				delwin(evs);
				return(0);
			}
			break;
		//ディレクトリの削除
		case 'r':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			if(initmenu[j][0] != 'd')
				break;
			sprintf(strCommand,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
			sprintf(buff,"rmdir %s を実行します。",strCommand);
			if(popmsg(1,0,buff) == 1)
			{
				intDoRMDIRCommand(strCommand);
				delwin(pvs);
				delwin(evs);
				return(0);
			}
			break;
		//ディレクトリの作成
		case 'm':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			memset(tmpbuff,'\0',sizeof(tmpbuff));
			memset(strCommand,'\0',sizeof(strCommand));
			input_window(1,0,strCommand,tmpbuff,"作成するディレクトリを入力してください");
			intDoMKDIRCommand(strCommand);
			delwin(pvs);
			delwin(evs);
			return(0);
		//ファイル名やディレクトリ名の変更
		case 'M':
			pFilerListBox->dirlocatey[pFilerListBox->deep] = j;
			pFilerListBox->dirlocateyy[pFilerListBox->deep] = yy;
			sprintf(buff,"%s",Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos));
			memset(strCommand,'\0',sizeof(strCommand));
			input_window(1,0,strCommand,Mid(initmenu[j],strLISTfilePos+1,strlen(initmenu[j])-strLISTfilePos),"ファイル名の変更を入力して下さい");
			sprintf(tmpbuff,"%s -> %s",buff,strCommand);
			if(MsgBox2(tmpbuff) == 1)
			{
				intDoRNFRCommand(buff);
				intDoRNTOCommand(strCommand);
				delwin(pvs);
				delwin(evs);
				return(0);
			}
			break;
		//イミディエイトウインドウへ移動
		case 'L':
			ImmLog->ImmediateListbox(0);
			break;
		case '': case 'U':
		/*
		半ページ上へ
		*/
			for(i=0;i<(ylen/2)-2;i++)
			{
				j -= 1;
				if(j < 1)
				{
					j = 0;
					break;
				}
			}
			for(i=0;i<(ylen/2)-2;i++)
				if(j == 0 &&  yy > 0)
					yy--;
			break;
		case '': case 'D': case 'd':
		/*
		半ページ下へ
		*/
			if(j > ylen - (ylen/2)-0)
			{
				for(i=0;i<(ylen/2)-1;i++)
				{
            		if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
						break;
					yy++;
           		}
				break;
			}
			for(i=0;i<(ylen/2)-1;i++)
			{
            	if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
					break;
				j += 1;
				if(j >= MAX_LIST - ylen)
				{
					j = MAX_LIST - ylen;
					break;
				}
			}
			break;
		/*
		リストボックス画面の最後に
		*/
        case 'g':
			if(maxline < ylen)
			{
				j = maxline - 1;
				break;
			}
			if(j + yy > maxline)
				break;
			j = ylen - 2;
			yy = (maxline - ylen)+1;
			break;
		/*
		リストボックス画面のトップに
		*/
        case 't':
			j = 0;
			yy = 0;
			break;
		/*
		下スクロール
		*/
        case 'j': case 0x42:
            if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
                break;
			if(yy > maxline)
				break;
            if(j > ylen - 3)
            {
                yy++;
				break;
            }
            if(j <= ylen - 3 && (maxline-1) > j)
            {
                j++;
            }
            break;
		/*
		上スクロール
		*/
        case 'k': case 0x41:
			j -= 1;
			if(j < 0)
			{
				j = 0;
				if(j == 0 &&  yy > 0)
				{
					yy--;
					break;
				}
			}
            break;
		/*
		Enter で決定
		*/
		/*
		'q' で何もしないでリストボックスを終了
		*/
		case 'q': case 'Q':
			if(intDoDisconnect() == 0)
				break;

			//イミディエイトウインドウを消去する。
			ImmLog->Immediatebox(1);

			wclear(pvs);
			wrefresh(pvs);
			saveline(yy,j);
			delwin(pvs);
			delwin(evs);
			return(-1);
		defualt:
			break;
		}
	}
}

//表示だけのファイラー。何もしない。
void ListBox::Filerbox(char *strEditDir)
{
	WINDOW *pvs, *evs;

	int ch;
	int i;

	int j = pFilerListBox->dirlocatey[pFilerListBox->deep];
	int yy = pFilerListBox->dirlocateyy[pFilerListBox->deep];
	int ylen = height-1;

	struct dirent *dp;
	char attrbuff[256];

	pvs = newwin(height,width,sy,sx);
	wattron(pvs,A_REVERSE);
	box(pvs,' ',' ');
	wattroff(pvs,A_REVERSE);
	evs = newwin(1,90,LINES-1,0);
	mvwprintw(evs,0,1,"[%s]",title);
	mvwprintw(evs,0,1,"chdir up recv edit find send Mv mkdir ^Remove Quit    ");
	mvwprintw(evs,0,52+2,"j down k up ^D down ^U up");
	wattron(evs,A_REVERSE);
	mvwprintw(evs,0,1,"%c",'c');
	mvwprintw(evs,0,7,"%c",'u');
	mvwprintw(evs,0,10,"%c",'');
	mvwprintw(evs,0,15,"%c",'e');
	mvwprintw(evs,0,20,"%c",'/');
	mvwprintw(evs,0,25,"%c",'S');
	mvwprintw(evs,0,30,"%c",'M');
	mvwprintw(evs,0,33,"%c",'m');
	mvwprintw(evs,0,39,"%c",'^');
	mvwprintw(evs,0,40,"%c",'R');
	mvwprintw(evs,0,47,"%c",'Q');

	mvwprintw(evs,0,52+2,"%c",'j');
	mvwprintw(evs,0,59+2,"%c",'k');
	mvwprintw(evs,0,64+2,"%c",'^');
	mvwprintw(evs,0,65+2,"%c",'D');
	mvwprintw(evs,0,72+2,"%c",'^');
	mvwprintw(evs,0,73+2,"%c",'U');
	wattroff(evs,A_REVERSE);


		wattron(pvs,A_REVERSE);
		box(pvs,' ',' ');
		for(i=0;i<ylen-1;i++)
		{
			memset(initmenu[i],' ',width-1);
			mvwprintw(pvs,i+1,0,"%s",initmenu[i]);
			sprintf(initmenu[i],"%s",itemlist[i+yy]);
			mvwprintw(pvs,i+1,1,"%s",initmenu[i]);
		}

		wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[%s]",title);

		wmove(pvs,j+1,2);
		wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,j+1,1,"%s",initmenu[j]);
		wattron(pvs,A_REVERSE);

		wrefresh(evs);
		wrefresh(pvs);
}

//イミディエイトリストボックス。FTX のコマンドキューを表示する。
//リストボックスの中で操作可能
//'-'でリスト最下行を削除
//'+'でリスト最下行に追加して線を引く
//'C'でイミディエイトウインドウをクリアする
//'/' でファイル検索、'n' で再検索/
//'j' と 'k' キーでファイラーカーソルの移動
//'d' と 'u' キーでファイラーカーソルの上下半ページ移動
//'g' で画面最下行へ移動",
//'t' で画面トップに移動"
//'q' で終了(ファイラーウインドウに移動)

char * ListBox::ImmediateListbox(int addline)
{
	WINDOW *pvs;
	frmSockFTP *ftpfrm;

	int ch;
	int i;

	initline();

	int j = cursol;
	int yy = line;
	int ylen = height-1;
	static char result[256];
	char findstr[256];
	int findf = 0;
	char buff[256];

	pvs = newwin(height,width,sy,sx);
	wattron(pvs,A_REVERSE);
	box(pvs,' ',' ');
	wattroff(pvs,A_REVERSE);
	mvwprintw(pvs,0,1,"[%s]",title);

	strLISTfilePos = 0;
	yy = addline;
	for(;;)
	{
		wattron(pvs,A_REVERSE);
		box(pvs,' ',' ');
		for(i=0;i<(ylen)-1;i++)
		{
			memset(initmenu[i],' ',width-1);
			mvwprintw(pvs,i+1,0,"%s",initmenu[i]);
		//	sprintf(initmenu[i],"%2d %s",i+1+yy,itemlist[i+yy]);
			sprintf(initmenu[i],"%s",itemlist[i+yy]);
			mvwprintw(pvs,i+1,1,"%s",initmenu[i]);
		}
		wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,0,1,"[%s]",title);

		wmove(pvs,j+1,2);
		wattroff(pvs,A_REVERSE);
		mvwprintw(pvs,j+1,1,"%s",initmenu[j]);
		wattron(pvs,A_REVERSE);

		wrefresh(pvs);
        ch = wgetch(pvs);
       // getyx(pvs,item,x2);

        switch(ch)
        {
		case '1':
			break;
		case 'C':
			Clear();
			break;
		//イミディエイトリストボックス最下行に線の行を追加する
		case '+':
			memset(ImmediateMsg,'-',width-2);
			ImmediateMsg[width-2] = '\0';
			AddItemTail(ImmediateMsg);
			break;
		//イミディエイトリストボックス最下行を削除する
		case '-':
			if(j == maxline - 1)
				j--;
            if(j < 1)
				j = 0;
			DeleteItem();
			break;

		//イミディエイトリストボックス内の文字を検索する
		case '/':
		memset(findstr,'\0',sizeof(findstr));
		input_window(1,0,findstr,"Immediate内を検索");
		if(strlen(findstr) < (size_t)0)
			strcpy(findstr," ");
		//再検索する
		case 'n':
			if(strlen(findstr) < (size_t)1)
				break;
			j++;
			for(;j+yy<maxline;j++)
			{
				sprintf(buff,"%s",Mid(itemlist[j+yy],strLISTfilePos+1,strlen(itemlist[j+yy])-strLISTfilePos));
				if(findf = Findex(buff, findstr) != -1)
				{
				//	popmsg(20,0,itemlist[j+yy]);
					yy = yy + j;
					j = 0;
					break;
				}
			}
			if(j+yy > maxline -1)
			{
				j = 0;
				yy = 0;
				break;
			}
			break;

		case '': case 'U': case 'u':
		/*
		半ページ上へ
		*/
			for(i=0;i<(ylen/2)-2;i++)
			{
				j -= 1;
				if(j < 1)
				{
					j = 0;
					break;
				}
			}
			for(i=0;i<(ylen/2)-2;i++)
				if(j == 0 &&  yy > 0)
					yy--;
			break;
		case '': case 'D': case 'd':
		/*
		半ページ下へ
		*/
			if(j > ylen - (ylen/2)-0)
			{
				for(i=0;i<(ylen/2)-1;i++)
				{
            		if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
						break;
					yy++;
           		}
				break;
			}
			for(i=0;i<(ylen/2)-1;i++)
			{
            	if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
					break;
				j += 1;
				if(j >= MAX_LIST - ylen)
				{
					j = MAX_LIST - ylen;
					break;
				}
			}
			break;
		/*
		リストボックス画面の最後に
		*/
        case 'g':
			if(maxline < ylen)
			{
				j = maxline - 1;
				break;
			}
			if(j + yy > maxline)
				break;
			j = ylen - 2;
			yy = (maxline - ylen)+1;
			break;
		/*
		リストボックス画面のトップに
		*/
        case 't':
			j = 0;
			yy = 0;
			break;
		/*
		下スクロール
		*/
        case 'j': case 0x42:
            if(j + yy >= maxline - 1 || j + yy > MAX_LIST + 1)
                break;
			if(yy > maxline)
				break;
            if(j > ylen - 3)
            {
                yy++;
				break;
            }
            if(j <= ylen - 3 && (maxline-1) > j)
            {
                j++;
            }
            break;
		/*
		上スクロール
		*/
        case 'k': case 0x41:
			j -= 1;
			if(j < 0)
			{
				j = 0;
				if(j == 0 &&  yy > 0)
				{
					yy--;
					break;
				}
			}
            break;
		/*
		Enter で決定
		*/
		case 0x0d: case 0x0a: case'Z':
			saveline(yy,j);
			strcpy(result,itemlist[(j+yy)]);
			delwin(pvs);
			return(result);
		/*
		'q' で何もしないでリストボックスを終了
		*/
		case 'q':
			saveline(yy,j);
			delwin(pvs);
			return((char *)NULL);
		defualt:
			break;
		}
	}
}

//イミディエイトリストボックス。FTX のコマンドキューを表示するだけ。
char * ListBox::Immediatebox(int fin)
{
	WINDOW *pvs;

	int ch;
	int i;

	initline();

	int j = 0;
	int yy = 0;
	int ylen = height-1;
	static char result[256];

	pvs = newwin(height,width,sy,sx);
	wattron(pvs,A_REVERSE);
	box(pvs,' ',' ');
	wattroff(pvs,A_REVERSE);
	mvwprintw(pvs,0,1,"[%s]",title);

	wattron(pvs,A_REVERSE);
	box(pvs,' ',' ');
	if(maxline > height-2)
	{
		for(i=0;i<(ylen)-1;i++)
		{
			memset(initmenu[i],' ',width-1);
			mvwprintw(pvs,i+1,0,"%s",initmenu[i]);
			sprintf(initmenu[i],"%s",itemlist[i+(maxline-(height-2))]);
			mvwprintw(pvs,i+1,1,"%s",initmenu[i]);
		}
	}
	else
	{
		for(i=0;i<(ylen)-1;i++)
		{
			memset(initmenu[i],' ',width-1);
			mvwprintw(pvs,i+1,0,"%s",initmenu[i]);
			sprintf(initmenu[i],"*%s",itemlist[i+line]);
			mvwprintw(pvs,i+1,1,"%s",initmenu[i]);
		}
	}
	wattroff(pvs,A_REVERSE);
	mvwprintw(pvs,0,1,"[%s]",title);

	wmove(pvs,j+1,2);
	wattroff(pvs,A_REVERSE);
	mvwprintw(pvs,j+1,1,"%s",initmenu[j]);
	wattron(pvs,A_REVERSE);

	if (fin)
		wclear(pvs);
	wrefresh(pvs);
	delwin(pvs);
}

