/*<Header>==============================================================
*
*	メモる / "MAIN.C"
*
*		[ EIN(tm) project : サンプルプログラム ]
*
*	COPYRIGHT  Nam  1995, All rights reserved.
*
*	配付・組込・改変・商利用すべて自由。ただし無保証っす
*
*-----------------------------------------------------------------------
*	V1.0L01α	95.05.29/Nam	プロトタイプ
*	V1.0L01β	95.08.01/Nam	メモ内リジューム機能追加
*	V1.0L01γ	95.08.09/Nam	メタタスク拡張メッセージ対応
*	V1.0L01δ	95.10.31/Nam	存在しないファイル名のチェック/DRAG&DROP対応
*</Header>==============================================================*/
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<snd.h>
#include	<winb.h>
#include	<te.h>
#include	<fntb.h>
#include	<gui.h>
#include	<egb.h>
#include	<file_dlg.h>
//#include	<tifflib.h>
#include	<msdos.cf>
#include	<loader.h>
#include	<math.h>
#include	<io.h>
#include	<guidbg.h>
#include	<wgb.h>
// ※ ここまでが平均的に使用されるヘッダ

#include	<time.h>		// このサンプルでのみ必要
#include	<mos.h>			// このサンプルでのみ必要
#include	<pocket.h>			// このサンプルでのみ必要

#include	"..\ein\eintm.h"	// EIN(TM)関連ライブラリのヘッダ
#include	"..\eindd\eindd.h"	// DRAG&DROPライブラリのヘッダ


#define	ERROR	(-1)
#define	PSET	(0)

#define	DISPMODE_ICON	(0)
#define	DISPMODE_PANEL	(1)

#define	ID_MWtime		(6)
#define	ID_MWtext		(4)
#define	ID_EVfname		(10)

int		ID_ICON[1];					// アイコン部品のID
int		ID_IWIN[8];					// メモウィンドゥ部品のID
int		ID_IWINMN0[11] ;			// (  〃 サブメニュー部品ID)
int		ID_ENV[11];					// 環境設定ウィンドゥ部品のID
int		ID_ABOUT[10];				// アバウトウィンドゥ部品のID

char	GV_workBuf[32*32*4] ;		// パターン書換え用ワークエリア
int		ndlCol[3];					// 時計の針の色
int		updateFlag = ERROR;			// 画面更新中か否かを示すフラグ

int		dispMode=DISPMODE_PANEL;	// 表示状態(0:アイコン,1:メモウィンドゥ)

char	memoname[128]="";
char	tmpname[128]="";

/*= リジューム用設定=================================================*/
FRAME	RSM_ICONFR;
FRAME	RSM_IWINFR;
char	RSMID[]="%%% メモる %%%";
char	RSMTITLE[]="メモる  V1.1 L11A";
char	RSMFNAME[128];
int		RSMDMODE=DISPMODE_ICON;
/*===================================================================*/

char	*GV_egbWork ;
int		GV_apliLot ;
char	*guiEgbPtr ;				//	EGB のワークアドレス

void	( *GV_defIdleTask )() ;

MMICTRL	mmic = {
				 SCREEN16 | SCREENIGNORE,		//	resolution
				 SCREENUNUSED,
				 0, SCREENAVAILABLE, 0,	//	write_page,display_page,priority
				 SCREENAVAILABLE,	//	mode
				 SCREENEXPAND,		//	vram_x
				 0,0,0,0,			//	size,*ptr,asize,*atpr
				 0,0,0,0,			//	frame
				 -32767,			//	move
				 -32767,
				  32767,
				  32767,
				 15,8,7,15			//	color
				} ;

/*===================================================================*/
/*  メインループ                                                     */
/*===================================================================*/
void main()
{
	extern int APL_init() ;
	extern int func_HIDE();

	int		kobj;

	// 初期化処理
	if (MMI_Open( &mmic ) == NOERR){
		// 二重起動のcheck
		if ( (kobj = MMI_CallMessage( MMI_GetApliId(), GM_QUERYID, QM_KIND, 1)) > NOERR ){
			MMI_CallMessage( MMI_GetApliId(), GM_SWITCH, FALSE, kobj );
		} else {
			// アイドルタスクに登録
			setIdleTask();
			// 初期化に成功すればメインループに
			if ( APL_init()==NOERR ){
				// メインループ
				MMI_ExecSystem();
			}
			// アイドルの解除
			resetIdleTask();
			// ウィンドゥ消去(※SHELLに消去させると遅いので)
			func_HIDE( ID_ICON[0] );
			func_HIDE( ID_IWIN[0] );
			func_HIDE( ID_ENV[0] );
		}
	}
	// 終了処理
	MMI_Close() ;
}

/*===================================================================*/
/*  初期化処理                                                       */
/*===================================================================*/
int APL_init()
{
	extern	MMIINIT	initDataRES_ICON ;
	extern	MMIINIT	initDataRES_IWIN ;
	extern	MMIINIT	initDataRES_ENV ;
	extern	MMIINIT	initDataRES_ABUT ;

	extern	int ICONmaxId;
	extern	unsigned char *ICONTbl[];

	extern int	userFunc();
	extern int	startUpdate();

	HYPER	hyp;
	register int	ret ;


	// EGB ワークアドレスを取得し、ローカルワークにコピー
	guiEgbPtr = MMI_GetEgbPtr() ;
	if ( (GV_apliLot = TL_getLot()) < 1 ){
		return ERROR ;
	}
	if( (GV_egbWork = TL_mallocMemory( GV_apliLot, EgbWorkSize )) == NULL ){
		return ERROR ;
	}
	FM_memcpy( GV_egbWork, guiEgbPtr, EgbWorkSize ) ;

	// GUI部品の初期化
	if ((ret = MMI_initHyper()) < 0)			//	ハイパー型
		return ret;
	if ((ret = MMI_initDialogL40()) < 0)		//	ダイアログ型
		return ret;
	if ((ret = MMI_initAlertL40()) < 0)			//	アラート型
		return ret;
	if ((ret = MMI_initMessageL40()) < 0)		//	メッセージ型
		return ret;
	if ((ret = MMI_initMenuL40()) < 0)			//	メニュー型
		return ret;
	if ((ret = MMI_initButtonL40()) < 0)		//	ボタン型
		return ret;
	if ((ret = MMI_initDrawButtonL40()) < 0)	//	ドロウボタン型
		return ret;
//	if ((ret = MMI_initToggleIconL40()) < 0)	//	トグルボタン型
//		return ret;
	if ((ret = MMI_initIconL40()) < 0)			//	アイコン型
		return ret;
	if ((ret = MMI_initScrollBarL40()) < 0)		//	スクロールバー型
		return ret;
	if ((ret = MMI_initTextL40()) < 0)			//	テキスト型
		return ret;
	if ((ret = MMI_initMenuItemL40()) < 0)		//	メニューアイテム型
		return ret;
	if ((ret = MMI_initWindowL40()) < 0)		//	ウィンドウ型
		return ret;
//	if ((ret = MMI_initNumBoxL40()) < 0)		//	数値入力パネル型
//		return ret;
	/*	ファイルダイアログを使うときはさらにリストメニューの初期化も必要	*/
	/*	リストメニュー型部品の初期化			*/
	if ((ret = MMI_initListMenuL40()) < 0)
		return ret ;

	// リソースを登録
	if ((ret = MMI_Init(&initDataRES_ICON)) < 0)
		return ret ;
	if ((ret = MMI_Init(&initDataRES_IWIN)) < 0)
		return ret ;
	if ((ret = MMI_Init(&initDataRES_ENV)) < 0)
		return ret ;
	if ((ret = MMI_Init(&initDataRES_ABUT)) < 0)
		return ret ;

	// ユーザアイコンを登録
	MMI_SetIconTable( ICONTbl, ICONmaxId ) ;

	// GUI色をメニュー色に設定
	EIN_initGuiColor();
	// 仮想画面情報を更新
	updateResolution();

	/*----------------------------------------------------------------*/
	/*  リジューム読み込み (※のついた処理は必ず行ってください)       */
	/*----------------------------------------------------------------*/
	char	work[RSMWORKSIZE];	// リジュームマネージャのワークエリア
	char	buf[1024];
	char	*ptr;
	int		size, x, y;
	char	s[128];

	// ※リジュームマネージャの初期化(アプリのIDタグ登録)
	EIN_rsmInit( work, RSMID );
	// ※読み込みバッファ設定
	EIN_rsmBufSet( work, buf, 1023 );
	// ※リジューム情報読み込み
	size = EIN_rsmLoad( work );
	#ifdef DEBUG
	printf(" resume size(%d)\n",size);
	#endif
	if ( size > 0 ){
		// ICON表示位置
		if ( ((ptr = strstr(buf,"\nICON: ")) != NULL ) &&
			 (sscanf(ptr,"\nICON: %d %d\n", &x, &y) > 1 ) ){
			if ( x<-31 ){	x=0;	}
			if ( y<-31 ){	y=0;	}
			// 枠座標を得る
			MMI_SendMessage( ID_ICON[0], MM_GETHYPER, 1, &hyp );
			RSM_ICONFR.lupx = x;
			RSM_ICONFR.lupy = y;
			RSM_ICONFR.rdwx = x+(hyp.fr.rdwx-hyp.fr.lupx);
			RSM_ICONFR.rdwy = y+(hyp.fr.rdwy-hyp.fr.lupy);
			#ifdef DEBUG
			printf("ICON: move to (%d,%d)\n", x, y);
			#endif
			MMI_SendMessage( ID_ICON[0], MM_MOVE, 1, &RSM_ICONFR ) ;
		}
		// メモウィンドゥ表示位置
		if ( ((ptr = strstr(buf,"\nIWIN: ")) != NULL ) &&
			 (sscanf(ptr,"\nIWIN: %d %d\n", &x, &y) > 1 ) ){
			if ( x<-31 ){	x=0;	}
			if ( y<-31 ){	y=0;	}
			// 枠座標を得る
			MMI_SendMessage( ID_IWIN[0], MM_GETHYPER, 1, &hyp );
			RSM_IWINFR.lupx = x;
			RSM_IWINFR.lupy = y;
			RSM_IWINFR.rdwx = x+(hyp.fr.rdwx-hyp.fr.lupx);
			RSM_IWINFR.rdwy = y+(hyp.fr.rdwy-hyp.fr.lupy);
			#ifdef DEBUG
			printf("IWIN: move to (%d,%d)\n", x, y);
			#endif
			MMI_SendMessage( ID_IWIN[0], MM_MOVE, 1, &RSM_IWINFR ) ;
		}
		// 表示状態
		if ( ((ptr = strstr(buf,"\nMODE: ")) != NULL ) &&
			 (sscanf(ptr,"\nMODE: %d\n", &x) > 0 ) ){
			dispMode = (x==0) ?DISPMODE_ICON :DISPMODE_PANEL;
			RSMDMODE = dispMode;
			#ifdef DEBUG
			printf("MODE: %d\n", x);
			#endif
		}
		// メモファイル名を得る
		if ( ((ptr = strstr(buf,"\nFNAME: ")) != NULL ) &&
			 (sscanf(ptr,"\nFNAME: %s\n", &s) > 0 ) ){
			#ifdef DEBUG
			printf("FNAME: %s\n", s);
			#endif
			strcpy( RSMFNAME, s );
			strcpy( memoname, s );
		}
		// 編集中のメモがあったら、その一時セーブ名で読み込む
		if ( ((ptr = strstr(buf,"\nTNAME: ")) != NULL ) &&
			 (sscanf(ptr,"\nTNAME: %s\n", &s) > 0 ) ){
			strcpy( tmpname, s );
			func_MWtmpLoad();
		}
	}
	if ( strlen(memoname) < 1 ){
		// メモファイル名が存在しないので"\T_FILE\MEMO.DOC"に仮設定
		extern unsigned char	FSYS_getBOOT();
		x = FSYS_getBOOT();
		/* 起動ドライブがQ以外ならリジューム可能 */
		s[0]= (x!=16) ?(x+'A') :'A';
		s[1]=0;
		strcat(s, ":\\T_FILE\\MEMO.DOC");
		strcpy( memoname, s );
	}

	// ウィンドウ類をベース部品にATTACH
	if ( dispMode == DISPMODE_ICON ){
		MMI_SendMessage( ID_ICON[0], MM_ATTACH, 1, MMI_GetBaseObj() ) ;
	} else {
		MMI_SendMessage( ID_IWIN[0], MM_ATTACH, 1, MMI_GetBaseObj() ) ;
	}

	// スイッチャー対応関数の登録
	MMI_SendMessage( MMI_GetBaseObj(), MM_SETEXEC, 1, userFunc ) ;

	// タスクリストにタイトルを登録
	MMI_CallMessage( MMI_GetApliId(), GM_TITLE, (int)RSMTITLE, 0 ) ;

	//	背景を表示
	MMI_SendMessage( MMI_GetBaseObj(), MM_SHOW, 0 ) ;

	// 画面更新開始
	startUpdate();

	return NOERR ;
}

/*===================================================================*/
/* リジューム情報更新 (※がついた処理は必ず行って下さい)             */
/*===================================================================*/
void	SaveResumeFile()
{
	char	work[RSMWORKSIZE];
	char	buf[1024];
	char	aplpath[128];
	HYPER	hyp1, hyp2;
	TEHandle	*teh;
	register int ret;

	// テキストのサイズ取得
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_GETTEHANDLE, 1, &teh );

	// 枠座標を得る
	MMI_SendMessage( ID_ICON[0], MM_GETHYPER, 1, &hyp1 );
	MMI_SendMessage( ID_IWIN[0], MM_GETHYPER, 1, &hyp2 );
	
	// 移動していたらセーブ
	if ( (RSM_ICONFR.lupx  != hyp1.fr.lupx) ||
	     (RSM_ICONFR.lupy  != hyp1.fr.lupy) ||
	     (RSM_IWINFR.lupx  != hyp2.fr.lupx) ||
	     (RSM_IWINFR.lupy  != hyp2.fr.lupy) ||
		 (RSMDMODE         != dispMode)||		// 表示状態が違う
		 ((int)(teh->Inchar) > 0 )||			// テキストが空では無い
	     (strcmp(RSMFNAME,memoname)!=0) ){		// メモファイル名が違う
		// ※マネージャ初期化
		EIN_rsmInit( work, RSMID );
		// ※バッファ設定(アプリ識別ID,更新時刻は自動設定されます)
		EIN_rsmBufSet( work, buf, 1023 );
		// ※アプリディレクトリ保存
		MMI_CallMessage( MMI_GetApliId(), GM_QUERYID, QM_PATH, (int)aplpath );
		EIN_rsmBufPrintf( work, "APLPATH: %s", aplpath );
		// ※アプリ名保存
		EIN_rsmBufPrintf( work, "TITLE:   %s", RSMTITLE );
		// ※コメント保存
		EIN_rsmBufCat( work, "COMMENT: うっかり防止のメモる");
		// アイコン位置保存
		EIN_rsmBufPrintf( work, "ICON: %d %d", hyp1.fr.lupx, hyp1.fr.lupy );
		// メモウィンドゥ位置保存
		EIN_rsmBufPrintf( work, "IWIN: %d %d", hyp2.fr.lupx, hyp2.fr.lupy );
		// 表示モード保存
		EIN_rsmBufPrintf( work, "MODE: %d", dispMode );
		// メモファイル名保存
		EIN_rsmBufPrintf( work, "FNAME: %s", memoname );
		// 編集中のメモがあったら、その一時セーブ名を保存
		if ( func_MWtmpSave()==NOERR ){
			EIN_rsmBufPrintf( work, "TNAME: %s", tmpname );
		}
		// ※バッファ終端(^A)設定
		EIN_rsmBufTail( work );
		// ※バッファをセーブ
		ret = EIN_rsmSave( work );
		#ifdef DEBUG
		printf(" resume save size(%d)   ptr:(%d,%d)\n",ret, hyp1.fr.lupx, hyp1.fr.lupy);
		#endif
		// リジューム情報を更新
		RSM_ICONFR.lupx = hyp1.fr.lupx;	RSM_ICONFR.lupy = hyp1.fr.lupy;
		RSM_ICONFR.rdwx = hyp1.fr.rdwx;	RSM_ICONFR.rdwy = hyp1.fr.rdwy;
		RSM_IWINFR.lupx = hyp2.fr.lupx;	RSM_IWINFR.lupy = hyp2.fr.lupy;
		RSM_IWINFR.rdwx = hyp2.fr.rdwx;	RSM_IWINFR.rdwy = hyp2.fr.rdwy;
		RSMDMODE = dispMode;
	}
}

/*===================================================================*/
/*  イベントループ関数                                               */
/*===================================================================*/
int		userFunc( int apliId, int messId, int info, int data )
{
    // メタタスク拡張メッセージ ( GM_EXECUSER で、info で渡す )
    #define MTL_ICONIZE     0x8000      // アイコン化
    #define MTL_RESTORE     0x8001      // 復元
    #define MTL_MAXIMIZE    0x8002      // 最大化

	extern int startUpdate();
	extern int	func_MWhide();
	extern int	func_MWshow();

	register	int		ret ;

	ret = ILLEGAL_FUNCTION ;
	switch( messId ){
		//	他タスクからスイッチしてきた
		case GM_WAKE :
			break ;

		//	他タスクにスイッチする
		case GM_SLEEP :
			break ;

		//	画面変更前処理
		case GM_PRESCRCHG :
			updateFlag = ERROR;		// 画面更新禁止
			break ;

		//	画面変更後処理
		case GM_POSTSCRCHG :
//			updateResolution();
//			startUpdate();
			/*=======================================================*/
			/*  本来はこの処理中で画面解像度を得られるはずなのですが */
			/*  どうもうまく処理されません(T-T)                      */
			/*  仕方無いので、解像度取得・変更関数をイベントに積んで */
			/*  関数終了後に呼ぶようにしました。                     */
			/*  （この方法を教えてくれた、ま〜おじさんに感謝!）      */
			/*=======================================================*/
			static int	argv[2] = { 1, 1 } ;
			EVENT	ev ;
			ev.what = EVEXEC ;
			ev.shift = 0 ;
			ev.info = (int)startUpdate;
			ev.data = (int)argv ;
			MMI_SetEvnt(&ev) ;
			break ;

		//	一時停止要求が出た
		case GM_PAUSE :
			updateFlag = ERROR;
			break ;

		//	一時停止解除要求が出た
		case GM_CONTINUE :
			updateFlag = NOERR;
			break ;

		//	終了要求が出た
		case GM_QUIT :
			// リジューム
			SaveResumeFile();
			//	正常終了
			MMI_SetHaltFlag( TRUE ) ;	//	イベントループを終了させるフラグ
			ret = NOERR ;
			break ;

		// メタタスク拡張メッセージ対応
		case GM_EXECUSER :				// メタタスクが送信する
			if ( info == MTL_ICONIZE ){
				// アイコン化メッセージだったら
				func_MWhide();
			} else if ( info == MTL_RESTORE ){
				// サイズ復元メッセージだったら
				func_MWshow();
			} else if ( info == MTL_MAXIMIZE ){
				// 最大化メッセージだったら
				func_MWshow();
			}
			ret = NOERR ;
			break;
		// DRAG&DROPメッセージ対応 '95.10.31
		case GM_SENDDATA :
			// プールからファイル名を受け取る
			EINDD_receivePool( info, data, memoname, NULL );
			ret = NOERR ;
			break ;

	}

	return ret ;
}

/*===================================================================*/
/*  アイドルタスク関数(アイコン上に時計表示)                         */
/*===================================================================*/
void	userIdleTask()
{
	#define	PI_B_2	(3.14159265358979323846*2.0)	/* PI×2 */
	#define	PI_D_2	(3.14159265358979323846/2.0)	/* PI÷2 */

	typedef	struct {
		_Far char *pixel;
		short	x1,y1;
		short	x2,y2;
		} EGB_BLOCK;

	typedef	struct {
		short	sum;
		short	x1,y1;
		short	x2,y2;
		} EGB_LINE;

	static int	oldsec = -1;
	static char	datestr[32];
	
	EGB_BLOCK	put;
	EGB_LINE	line;
	HYPER	hyp ;
	int		hour, min, sec, ox, oy;
	double	rm, r, th;
	int		btn, bx, by;
	Rect	rmos;
	time_t		ct = time(NULL);
	struct tm  *lt = localtime(&ct);
	char		cl[EINCLIPSIZE];


	// SCREENCHANGE中なので更新しない
	if ( updateFlag != NOERR ){
		return;
	}
	
	hour = lt->tm_hour;
	min  = lt->tm_min;
	sec  = lt->tm_sec;
	
	// まだ一秒経っていないなら終了
	if ( sec == oldsec ){
		return;
	}
	oldsec = sec;

	// もし入力ウィンドゥ状態なら文字列書換え
	if ( dispMode==DISPMODE_PANEL){
		WINCLIP	*wc;
		sprintf( datestr, "%4d/%2d/%2d  %2d:%02d:%02d",
			(lt->tm_year)+1900, (lt->tm_mon)+1, (lt->tm_mday), hour, min, sec );
		//	原点移動を戻し、描画エリアにクリップをかける
		MMI_SendMessage( ID_IWIN[ID_MWtime], MM_GETHYPER, 1, &hyp );
		wc = WIN_getClipMemory( &(hyp.fr), NULL );
		wc = WIN_clipWindow( ID_IWIN[ID_MWtime], wc, FALSE );
		MMI_SendMessage( ID_IWIN[ID_MWtime], MM_SETMSG, 1, datestr );
		MMI_SendMessage( ID_IWIN[ID_MWtime], MM_SHOW, 0 );
		// クリップ解除
		WIN_freeClipMemory( wc );
		return;
	}
	
	// 書込先の座標を得る
	MMI_SendMessage( ID_ICON[0], MM_GETHYPER, 1, &hyp );
	ox = (hyp.fr.rdwx - hyp.fr.lupx -2) / 2;
	oy = (hyp.fr.rdwy - hyp.fr.lupy -2) / 2;
	rm = (ox + oy) / 2;
	
	// 仮想画面消去
	EGB_writePage( GV_egbWork, 0x80 ) ;
	EGB_clearScreen( GV_egbWork ) ;

	/* 短針 */
	EGB_color( GV_egbWork, 0, ndlCol[2] );
	EGB_penSize( GV_egbWork, 3 );
	r = (double)rm * 0.8;
	th = -(PI_B_2 * (((((double)(hour % 12)) * 3600.0 + ((double)min) * 60.0)) / (12.0 * 3600.0)) - PI_D_2);
	line.sum= 2;
	line.x1 = ox;
	line.y1 = oy;
	line.x2 = ox + (int)(r * cos(th));
	line.y2 = oy - (int)(r * sin(th));
	EGB_connect( GV_egbWork, (char *)&line );
	/* 長針 */
	EGB_color( GV_egbWork, 0, ndlCol[1] );
	EGB_penSize( GV_egbWork, 2 );
	r = (double)rm;
	th = -(PI_B_2 * ((((double)min) * 60.0 + (double)sec) / (60.0 * 60.0)) - PI_D_2);
	line.x2 = ox + (int)(r * cos(th));
	line.y2 = oy - (int)(r * sin(th));
	EGB_connect( GV_egbWork, (char *)&line );
	/* 秒針 */
	EGB_color( GV_egbWork, 0, ndlCol[0] );
	EGB_penSize( GV_egbWork, 1 );
	r = (double)rm * 0.9;
	th = -(PI_B_2 * (((double)sec) / 60.0) - PI_D_2);
	line.x2 = ox + (int)(r * cos(th));
	line.y2 = oy - (int)(r * sin(th));
	EGB_connect( GV_egbWork, (char *)&line );

	// クリップ
	//	原点移動を戻し、描画エリアにクリップをかける
	EIN_clipOpen( cl );
	put.pixel = GV_workBuf ;
	put.x1    = hyp.fr.lupx+2;
	put.y1    = hyp.fr.lupy+2;
	put.x2    = hyp.fr.rdwx-2;
	put.y2    = hyp.fr.rdwy-2;
	EGB_writeMode( guiEgbPtr, PSET ) ;
	// 現在のマウスカーソルの位置を読む
	MOS_rdpos( &btn, &bx, &by );
	rmos.left = bx;
	rmos.up   = by;
	rmos.right= rmos.left + 32;
	rmos.down = rmos.up   + 32;
	
	if ( SectRect( &rmos, (Rect *)&hyp.fr ) ){
		// 内側なのでマウスを消そうね
		MG_mosDisp(2);
		WGB_putBlock( guiEgbPtr, 3, (char *)&put ) ;
		MG_mosDisp(3);
	} else {
		// 外側
		WGB_putBlock( guiEgbPtr, 3, (char *)&put ) ;
	}
	// クリップ解除
	EIN_clipClose( cl );
}

/*===================================================================*/
/*  アイドルタスクに登録                                             */
/*===================================================================*/
int		setIdleTask()
{
	void	( *idleTask )() ;

	/*	アイドル処理関数の取得	*/
	idleTask = MMI_GetIdleTaskFunc() ;

	/*	二重登録禁止チェック	*/
	if( idleTask != userIdleTask ){
		GV_defIdleTask = idleTask ;
		MMI_SetIdleTaskFunc( (void ((*)(void)))userIdleTask );
	}

	return ERROR ;
}

/*===================================================================*/
/*  アイドルタスクから削除                                           */
/*===================================================================*/
int		resetIdleTask()
{
	void	( *IdleTask )() ;

	/*	アイドル処理関数の取得	*/
	IdleTask = MMI_GetIdleTaskFunc() ;

	/*	USER関数登録のチェック	*/
	if( IdleTask == userIdleTask ){
		MMI_SetIdleTaskFunc( GV_defIdleTask ) ;
		GV_defIdleTask = 0 ;
	}

	return ERROR ;
}

/*===================================================================*/
/*  現在の画面モードに応じて仮想画面再設定                           */
/*===================================================================*/
int		updateResolution()
{
	int		modebuf[8];
	int		vbits;
	int		clsColor;
	
	// EGB 画面情報取得
	EGB_getResolutionPage( 0, modebuf );
	vbits = modebuf[4];
	#ifdef DEBUG
	printf("### updateResolution():  bit=%d\n", vbits );
	#endif
	// 時計の針の描画色をGUI色で再設定
	ndlCol[0] = MG_colorChange( 10 );	// 秒針
	ndlCol[1] = MG_colorChange( 8 );	// 長針
	ndlCol[2] = MG_colorChange( 8 );	// 短針
	clsColor = MG_colorChange( 4 );
	// EGB 仮想画面再初期化
	EGB_resolutionRam( GV_egbWork, 0x80, vbits, 32, 32, GV_workBuf );
	EGB_writePage( GV_egbWork, 0x80 ) ;
	EGB_color( GV_egbWork, 0, clsColor ) ;
	EGB_color( GV_egbWork, 1, clsColor ) ;
	EGB_writeMode( GV_egbWork, PSET ) ;
	EGB_paintMode( GV_egbWork, 0x02 ) ;
	EGB_pen( GV_egbWork, 0 ) ;
	EGB_writePage( GV_egbWork, 0x00 ) ;
	
	return NOERR;
}

/*===================================================================*/
/*  画面情報取得＆更新再開                                           */
/*===================================================================*/
int		startUpdate()
{
	updateFlag = NOERR;
	
	updateResolution();
	userIdleTask();

	return NOERR;
}

/*===================================================================*/
/*  アイコン化されたウィンドゥの関数                                 */
/*===================================================================*/
int		func_ICON( int kobj, int messId, int ac, EVENT *pev, int trigger )
{
	HYPER	hyp;
	FRAME	fr;

	if( messId == MM_SHOW ){
		userIdleTask();
		return ERROR;
	}
	// ※ ここでダブルクリックなら関数起動 / それ以外ならMOVE
	if( messId == MM_MOUSEON ){
		// 枠座標を得る
		MMI_SendMessage( kobj, MM_GETHYPER, 1, &hyp );
		fr = hyp.fr;
		do {
			MMI_iosense();
		} while( (MMI_GetEvnt((EVMOSUP|EVMOSDRAG), &pev)) < NOERR);
		if ( pev->what == EVMOSUP ){
			// ダブルクリックチェック
			if ( MMI_DoubleClickCheck(&fr, pev) != FALSE ){
				// 「アイコン→ウィンドゥ表示」
				func_MWshow();
			}
			return NOERR;
		}
		// ダブルクリックでは無いのでMOVE処理へ
	}
	// エラーで抜けるとWINDOW部品本来の動作をしまっする♪
	return ERROR;
}

/*===================================================================*/
/*  部品表示(汎用)                                                   */
/*===================================================================*/
int	func_SHOW( int id )
{
	char		clp[EINCLIPSIZE];
	register int	ret;

	// アイコンをATTACHする
	ret = MMI_SendMessage( id, MM_ATTACH, 1, MMI_GetBaseObj() ) ;
	// アイコンを表示する
	EIN_clipOpen( clp );
	MMI_SendMessage( id, MM_SHOW, 0 ) ;
	MMI_SendMessage( id, MM_WAKE, 0 ) ;
	EIN_clipClose( clp );

	return ret;
}

/*===================================================================*/
/*  部品消去(汎用)                                                   */
/*===================================================================*/
int	func_HIDE( int id )
{
	MMI_SendMessage( id, MM_SLEEP, 0 );
	MMI_SendMessage( id, MM_ERASE, 0 );
	MMI_SendMessage( id, MM_DETACH, 0 );
	return NOERR;
}

/*===================================================================*/
/*  入力ウィンドゥ表示 & アイコン消去                                */
/*===================================================================*/
int	func_MWshow()
{
	// 既にウィンドゥが表示されているなら何もしない
	if ( dispMode==DISPMODE_PANEL){
		return NOERR;
	}
	dispMode=DISPMODE_PANEL;

	// アイコンを消去する
	func_HIDE( ID_ICON[0] );
	// 入力ウィンドゥを表示する
	func_SHOW( ID_IWIN[0] );

	return NOERR;
}

/*===================================================================*/
/*  入力ウィンドゥ一時消去                                           */
/*===================================================================*/
int	func_MWhide()
{
	// パネルが表示されていないなら何もしない
	if ( dispMode!=DISPMODE_PANEL){
		return ERROR;
	}
	dispMode=DISPMODE_ICON;

	// 入力ウィンドゥを消去する
	func_HIDE( ID_IWIN[0] );
	// アイコンを表示
	func_SHOW( ID_ICON[0] );

	return NOERR;
}

int	func_MWheader( char *str )
{
	static char wday[8][4]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	time_t		ct = time(NULL);
	struct tm  *lt = localtime(&ct);

	sprintf( str, "Date: %04d-%02d-%02d %2d:%02d:%02d (%s)\n\n",
			(lt->tm_year)+1900, (lt->tm_mon)+1, (lt->tm_mday),
			(lt->tm_hour), (lt->tm_min), (lt->tm_sec),
			wday[(lt->tm_wday)] );
	return NOERR;
}

int	func_MWsave( char *sname, int hflag )
{
	#define	SBUFSIZE	(1024)
	char	buf[SBUFSIZE];
	int		csize, nsize, lfg, ret = NOERR;
	TEHandle		*teh;
	FILE			*fp;

	// テキストのサイズ取得
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_GETTEHANDLE, 1, &teh );
	csize = (int)(teh->Inchar);
	#ifdef DEBUG
	printf("func_MWsave(%s):  textsize:%d\n",sname, csize);
	#endif
	if ( csize < 1 ){
		#ifdef DEBUG
		printf("func_MWsave(): No text.\n");
		#endif
		return NOERR;
	}
	if ( (fp=fopen(sname,"a")) == (FILE *)NULL ){
		#ifdef DEBUG
		printf("func_MWsave(%s,\"a\"): open error\n", sname);
		#endif
		return ERROR;
	}
	// ヘッダフラグが0で無いならヘッダ書き込み
	if ( hflag != 0 ){
		// (まず日付)
		strcpy(buf,"\n###\n");
		if ( fwrite(buf, (strlen(buf)), 1, fp )<1 ){
			return ERROR;
		}
		func_MWheader( buf );
		if ( fwrite(buf, (strlen(buf)), 1, fp )<1 ){
			return ERROR;
		}
	}
	if ( csize > SBUFSIZE ){
		csize = SBUFSIZE;
	}
	if ( csize > 0 ){
		/* テキスト終端まで書き込み */
		for ( lfg=FALSE, ret=NOERR; ; lfg=TRUE ){
			nsize = MMI_SendMessage( ID_IWIN[ID_MWtext], MM_GETTEXT, 3, buf, SBUFSIZE, lfg );
			if ( fwrite(buf, ((csize>SBUFSIZE)?SBUFSIZE:csize), 1, fp )<1 ){
				#ifdef DEBUG
				printf("func_MWsave(%s): Write error.\n",sname);
				#endif
				ret = ERROR;
				break;
			}
			if ( (csize = nsize) < 1 ){
				break;
			}
		}
		if ( hflag != 0 ){
			strcpy(buf,"\n");
			fwrite(buf, strlen(buf), 1, fp );
		}
	}
	fclose( fp ) ;
	return ret;
}

int	func_MWclose()
{
	if ( func_MWsave( memoname, 1 )!=NOERR ){
		return ERROR;
	}
	// テキストをクリア
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_SETTEXT, 3, NULL, 0, FALSE );
	return func_MWhide();
}

int	func_MWpocketOut()
{
	#define	RBUFSIZE	(1024)
	char	buf[RBUFSIZE];
	int		csize;

	if ( SCB_open()==NOERR ){
		if ( SCB_isFormatAvailable(SCBF_CSTR) > 0 ){
			SCB_seek(SCBF_CSTR, 0, SCBS_SET);
			/* ファイル終端まで読み込み */
			for ( ; (csize=SCB_read(SCBF_CSTR, buf, RBUFSIZE))>0;  ){
				MMI_SendMessage( ID_IWIN[ID_MWtext], MM_SETTEXT, 3, buf, csize, TRUE );
			}
			MMI_SendMessage( ID_IWIN[ID_MWtext], MM_SHOW, 0 );
		}
		SCB_close();
	}
	return NOERR;
}

int	func_MWpocketIn()
{
	#define	WBUFSIZE	(1024)
	char	buf[WBUFSIZE];
	int		csize, nsize, lfg, ret=NOERR;
	TEHandle		*teh;

	// テキストのサイズ取得
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_GETTEHANDLE, 1, &teh );
	csize = (int)(teh->Inchar);
	if ( csize < 1 ){
		#ifdef DEBUG
		printf("func_MWpocketIn(): No text.\n");
		#endif
		return NOERR;
	}
	if ( SCB_open()==NOERR ){
		SCB_empty();
		// (まず日付)
		func_MWheader( buf );
		SCB_write(SCBF_CSTR, buf, strlen(buf));
		if ( csize > 0 ){
			/* テキスト終端まで書き込み */
			for ( lfg=FALSE, ret=NOERR; ; lfg=TRUE ){
				nsize = MMI_SendMessage( ID_IWIN[ID_MWtext], MM_GETTEXT, 3, buf, WBUFSIZE, lfg );
				if ( SCB_write(SCBF_CSTR,buf,((csize>WBUFSIZE)?WBUFSIZE:csize)) < 1 ){
					ret = ERROR;
					break;
				}
				if ( (csize = nsize) < 1 ){
					break;
				}
			}
		}
		strcpy(buf,"\n");
		SCB_write(SCBF_CSTR,buf,strlen(buf));
		SCB_seek(SCBF_CSTR, 0, SCBS_SET);
		SCB_close();
	}
	return ret;
}

int	func_MWnew()
{
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_SETTEXT, 3, NULL, 0, FALSE );
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_SHOW, 0 );
	return NOERR;
}

int	func_MWtmpSave()
{
	TEHandle		*teh;
	int				i;
	char			s[32];
	FILE	*fp;

	// テキストのサイズ取得
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_GETTEHANDLE, 1, &teh );
	if ( (int)(teh->Inchar) < 1 ){
		#ifdef DEBUG
		printf("func_MWpocketIn(): No text.\n");
		#endif
		return ERROR;
	}
	// テンポラリ名を設定
	extern unsigned char	FSYS_getBOOT();
	i = FSYS_getBOOT();
	/* 起動ドライブがQ以外ならリジューム可能 */
	s[0]= (i!=16) ?(i+'A') :'A';
	s[1]=0;
	strcat(s, ":\\T_FILE\\");
	// ほんとはここで名前がUniqになるようにするんだけど、とりあえずやんない
	for ( i=0; i< 1000; i++ ){
		/* テンポラリ名を生成 */
		sprintf( tmpname, "%s#MEM%03d#.$$$", s, i );
		/* ファイル名のバッティングをチェック */
		if ( (fp = fopen( tmpname, "r" )) == (FILE *)NULL ){
			/* 失敗→同じファイル名は無いので正常終了 */
			break;
		} else {
			/* 成功→同じファイル名が有ったので，とりあえずcloseしてループ */
			fclose( fp );
		}
	}
	if ( i>999 ){
		strcpy(tmpname,"");
		return ERROR;
	}
	return func_MWsave( tmpname, 0 );
}

int	func_MWtmpLoad()
{
	#define	LBUFSIZE	(1024)
	char	buf[LBUFSIZE];
	int		csize;
	FILE	*fp;

	if ( (fp = fopen( tmpname, "r" )) == (FILE *)NULL ){
		return ERROR;
	}
	/* ファイル終端まで読み込み */
	for ( ; (csize=fread(buf,1,LBUFSIZE,fp))>0;  ){
		MMI_SendMessage( ID_IWIN[ID_MWtext], MM_SETTEXT, 3, buf, csize, TRUE );
	}
	MMI_SendMessage( ID_IWIN[ID_MWtext], MM_SHOW, 0 );
	fclose( fp );
	remove( tmpname );
	strcpy( tmpname,"" );
	return NOERR;
}

static char	_fname[128];	// 設定取消用テンポラリ

/*===================================================================*/
/*  環境設定ダイアログ表示                                           */
/*===================================================================*/
int	func_MWenv()
{
	// 時計更新を停止
	updateFlag = ERROR;

	MMI_SendMessage( ID_ENV[ID_EVfname], MM_SETMSG, 1, memoname );
	func_SHOW( ID_ENV[0] );
	strcpy( _fname, memoname );
	return NOERR;
}

int	func_EVfname()
{
	unsigned int	InfSw;
	char			*ExtStr[]={"*.*", NULL};
	unsigned int	MSlctCnt;
	int				Atr, i, ret;
	char			path[128], filename[12];
	FILE	*fp;

retry:
	ret = FDG_InitFileDlg();
	if ( ret < 0 ){
		return ERROR;
	}
	FDG_SaveCurDir();
	// Qドライブはパスする
	FDG_SetPassDrv("Q");
	FDG_SetTitle( "メモファイル名", "実行", "取消" );
	InfSw=(FDG_TEXT|FDG_FILEONLY|FDG_REDRAW|FDG_ALERT);
	// 初期パスを設定
	// (指定ファイルの存在をチェック  '95.10.31)
	if ( (strlen(_fname)>0) &&
		 (fp = EIN_fopen( _fname, "r" )) != (FILE *)NULL ){
		fclose(fp);
		EIN_fnameNonDirectory( _fname, filename );
		EIN_fnameDirectory( _fname, path );
		// パス名末尾の"￥"を削除する(FDGの仕様)
		i=strlen(path)-1;
		if (i>0){
			path[i] = 0;
		}
		#ifdef DEBUG
		printf("%s\n%s\n", filename, path);
		#endif
		FDG_SetFileText( filename );
		ret=FDG_DspFileDlg( MMI_GetBaseObj(), InfSw, path, ExtStr, &MSlctCnt );
	} else {
		// ファイルが無い場合
		ret=FDG_DspFileDlg( MMI_GetBaseObj(), InfSw, NULL, ExtStr, &MSlctCnt );
	}
	FDG_RecovCurDir();
	// 取り消されたら終了
	if ( ret != 1 ){
		FDG_FreeFileDlg();
		return ERROR;
	}
	FDG_GetPathName( _fname, &Atr, 0 );
	FDG_FreeFileDlg();
	// 小文字は大文字に
	for ( i=0; i<strlen(_fname); i++ ){
		_fname[i] = toupper( (int)_fname[i] );
	}
	// ファイル名を表示
	strcpy(path, "                              ");
	MMI_SendMessage( ID_ENV[ID_EVfname], MM_SETMSG, 1, path );
	MMI_SendMessage( ID_ENV[ID_EVfname], MM_SHOW, 0 );
	MMI_SendMessage( ID_ENV[ID_EVfname], MM_SETMSG, 1, _fname );
	MMI_SendMessage( ID_ENV[ID_EVfname], MM_SHOW, 0 );

	return NOERR;
}

/*  環境設定ダイアログ消去 */
int	func_EVerase()
{
	func_HIDE( ID_ENV[0] );
	// 時刻表示復帰
	updateFlag = NOERR;

	return NOERR;
}

int	func_EVexit()
{
	strcpy( memoname, _fname );
	return func_EVerase();
}

int	func_EVcalcel()
{
	return func_EVerase();
}

int	func_MWabout()
{
	// 時刻表示一時停止
	updateFlag = ERROR;
	return func_SHOW( ID_ABOUT[0] );
}

int	func_ABclose()
{
	func_HIDE( ID_ABOUT[0] );
	// 時刻表示復帰
	updateFlag = NOERR;
	return NOERR;
}
