/*<Header>==============================================================
*
*	メモリ残量表示 / "GUI.C"
*
*		[ EIN(tm) project : サンプルプログラム ]
*
*	COPYRIGHT  Nam  1994, All rights reserved.
*
*	配付・組込・改変・商利用すべて自由。ただし無保証っす
*
*-----------------------------------------------------------------------
*	V1.0L01α	94.04.15/Nam	プロトタイプ
*	V1.0L30		94.07.19/Nam	EIN(TM)公開版
*	V1.0L31		94.09.05/Nam	GM_PURGEのメモリ開放時に問い合わせるように
*</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	<mos.h>			// このサンプルでのみ必要(MOS_getTimeの為)

#include	"..\ein\eintm.h"	// EIN(TM)関連ライブラリのヘッダ


#define	ERROR	(-1)

#define	DISPMODE_ICON	(0)
#define	DISPMODE_PANEL	(1)

#define	ID_BASE		(0)
#define	ID_BTNBASE	(1)
#define	ID_NUMBASE	(2)
#define	ID_NUM1		(3)
#define	ID_NUM2		(4)
#define	ID_NUM3		(5)

#define	PT_NON		(513)
#define	PT_NUM		(514)
#define	PT_MEM		(524)
//#define	PT_MEMMIN	(543)
#define	PT_MEMMIN	(542)
#define	PT_MEMSIZE	(19)
#define	PT_ANIMST	(544)
#define	PT_ANIMEND	(546)
#define	PT_ANGEL	(547)

#define	ID_MEMREM	(6)
#define	ID_MEMGET	(7)


extern	int		ID_ICON[];
extern	int		ID_PANEL[];
extern	int		dispMode;

extern	int	ICONmaxId;

int		memLot = 0;
char	*memMallocPtr = NULL;
int		memMalloc = 0;
int		memSize   = 0;
int		memLimit = (1024*1024*4);	// アニメーションを開始する残メモリ(byte)

/*===================================================================*/
/* 終了処理                                                              */
/*===================================================================*/
int		func_Quit()
{
	extern void SaveResumeFile();

	/* リジューム */
	SaveResumeFile();
	// メモリ開放
	purgeMem();

	MMI_SetHaltFlag( TRUE ) ;	/*	イベントループを終了させるフラグ	*/

	return NOERR ;
}

/*===================================================================*/
/*  昇天表示                                                         */
/*===================================================================*/
int		func_Angel()
{
	// 数値表示をしない
	MMI_SendMessage( ID_ICON[ID_NUMBASE], MM_DETACH, 0 );
	MMI_SendMessage( ID_ICON[ID_NUM1], MM_DETACH, 0 );
	MMI_SendMessage( ID_ICON[ID_NUM2], MM_DETACH, 0 );
	MMI_SendMessage( ID_ICON[ID_NUM3], MM_DETACH, 0 );

	// ICONパターンを"昇天"に (リジューム処理中に呼ばれる)
	MMI_SendMessage( ID_ICON[ID_BTNBASE], MM_SETSHAPE, 1, PT_ANGEL);
	MMI_SendMessage( ID_ICON[ID_BTNBASE], MM_SHOW, 0 );

	return NOERR ;
}

/*===================================================================*/
/* メモリ開放                                                        */
/*===================================================================*/
int		purgeMem()
{
	// 確保していたメモリを開放
	if (memLot>0){
		TL_freeLot( memLot );
		memLot = 0;
		memMallocPtr = NULL;
		memMalloc = 0;
	}
	return NOERR;
}

/*===================================================================*/
/* メモリ開放(問い合わせる)                                          */
/*===================================================================*/
int	purgeMemInteractive()
{
	static char	*alertStr[]={"mem.exg:\nメモリを開放します?", "やだやだ", "仕方ないなぁ"};
	if (memLot>0){
		/* 削除要求のアラート表示 */
		if ( MMI_CallMessage(MMI_GetApliId(), GM_ALERT, 
				AM_ALERT2 | AM_ALERTB1E,(int)alertStr) == 1 ){
			/* メモリ開放 */
			purgeMem();
		}
	}
	return NOERR;
}

/*===================================================================*/
/*  アイコン上に残メモリを数値表示                                   */
/*===================================================================*/
int	dispMem( m )
{
	static char	ms[8] = "00.000";
	register int	foo, bar;
	
	if ( m < 0 ){
		m = 0;
	}
//	sprintf( memstr, "%2d.%03d", m/1000, m%1000 );
	foo = (m / 1000) % 100;
	bar = ((foo % 100) / 10);
	ms[0] = ( bar > 0 ) ?(bar+'0') :' ';
	ms[1] =  (foo % 10)        +'0';
	foo = (m % 1000);
	ms[3] =  (foo / 100)       +'0';
	ms[4] = ((foo % 100) / 10) +'0';
	ms[5] =  (foo % 10)        +'0';
	MMI_SendMessage( ID_PANEL[ID_MEMREM], MM_SETMSG, 1, ms );
	MMI_SendMessage( ID_PANEL[ID_MEMREM], MM_ERASE, 0 );
	MMI_SendMessage( ID_PANEL[ID_MEMREM], MM_SHOW, 0 );
	return NOERR;
}

/*===================================================================*/
/*  メモリ破棄関数(パネル上ボタンよりcall)                           */
/*===================================================================*/
int	func_purgeMem()
{
	int	var, min, max, delta, ptColum;
	
	purgeMem();
	dispMem( EIN_checkMem()/1024 );

	MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_GETNUMBOX, 5, &var, &min, &max, &delta, &ptColum );
	MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_SETNUMBOX, 5, 0, min, max, delta, ptColum );
	MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_ERASE, 0 );
	MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_SHOW, 0 );

	return NOERR;
}
/*===================================================================*/
/*  残メモリ表示関数(パネル上ボタンよりcall)                         */
/*===================================================================*/
int	func_getSize()
{
	int	m;
	int	var, min, max, delta, ptColum;
	
	MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_GETNUMBOX, 5, &var, &min, &max, &delta, &ptColum );
	m = (EIN_checkMem()+memMalloc)/1024;
	if ( var > m ){
		var = m;
		MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_SETNUMBOX, 5, var, min, max, delta, ptColum );
	}
	dispMem( m - var );

	return NOERR;
}
/*===================================================================*/
/*  メモリ取得関数(パネル上ボタンよりcall)                           */
/*===================================================================*/
int	func_mallocMem()
{
	int	var, min, max, delta, ptColum;
	
	MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_GETNUMBOX, 5, &var, &min, &max, &delta, &ptColum );
	if (memLot>0){
		TL_freeLot( memLot );
		memLot = 0;
		memMallocPtr = NULL;
		memMalloc = 0;
	}
	// 指定確保の為のメモリlot取得
	if ( (memLot=TL_getLot())<0 ){
		return ERROR;
	}
	for ( ; var>0; var-- ){
		memMalloc = var * 1024;
		if ( (memMallocPtr=TL_mallocMemory(memLot,memMalloc))!=NULL ){
			MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_SETNUMBOX, 5, var, min, max, delta, ptColum );
			MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_ERASE, 0 );
			MMI_SendMessage( ID_PANEL[ID_MEMGET], MM_SHOW, 0 );
			break;
		}
	}
	dispMem( EIN_checkMem()/1024 );

	return NOERR;
}

/*===================================================================*/
/*  パネル表示                                                       */
/*===================================================================*/
int	func_Panel()
{
	char		clp[EINCLIPSIZE];
	register int	ret;

	// 既にパネルが表示されているなら何もしない
	if ( dispMode==DISPMODE_PANEL){
//		printf("dispMode!=0\n");
		return NOERR;
	}
	dispMode=DISPMODE_PANEL;

	//	パネルをATTACHする
	ret = MMI_SendMessage( ID_PANEL[0], MM_ATTACH, 1, MMI_GetBaseObj() ) ;

	EIN_clipOpen( clp );
	MMI_SendMessage( ID_PANEL[0], MM_SHOW, 0 ) ;
	MMI_SendMessage( ID_PANEL[0], MM_WAKE, 0 ) ;
	dispMem( EIN_checkMem()/1024 );
	EIN_clipClose( clp );

	return NOERR;
}

/*===================================================================*/
/*  パネル消去                                                       */
/*===================================================================*/
int	func_Close()
{
	char		clp[EINCLIPSIZE];

	// パネルが表示されていないなら何もしない
	if ( dispMode!=DISPMODE_PANEL){
		return ERROR;
	}
	dispMode=DISPMODE_ICON;
	//	PANELウィンドゥをDETACHする
	MMI_SendMessage( ID_PANEL[0], MM_SLEEP, 0 ) ;
	MMI_SendMessage( ID_PANEL[0], MM_ERASE, 0 ) ;
	MMI_SendMessage( ID_PANEL[0], MM_DETACH, 0 ) ;

	return NOERR;
}

/*===================================================================*/
/*  アイコン関数                                                     */
/*===================================================================*/
int		func_ICON( int kobj, int messId, int ac, EVENT *pev, int trigger )
{
	HYPER	hyp;
	FRAME	fr;

	if( pev->what == EVMOSDN ){
		// 枠座標を得る
		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 ){
				return func_Panel();
			}
			return NOERR;
		}
	}
	// エラーで抜けるとWINDOW部品本来の動作をするのだ
	return ERROR;
}

/* 数値をICONに設定し表示 */
/* id:部品ID, no:表示したい数値(-1〜9) */
void	__setNumFnt( int id, int no )
{
	if ( no >= 0 ){
		MMI_SendMessage( id, MM_SETSHAPE, 1, ((no % 10) + PT_NUM) );
	} else {
		/* 番号表示を" "に */
		MMI_SendMessage( id, MM_SETSHAPE, 1, PT_NON );
	}

//	printf("  %d -> %d\n", no, (no % 10) );
}

/*===================================================================*/
/*  アイドルタスク関数                                               */
/*===================================================================*/
void	userIdleTask()
{
	static int		btime = 0;
	register int	ntime;

	static int		omem = 0;
	static int		optn = 0;
	register int	ptn;
	register int	mem, pmem, dmem;

	ntime = MOS_getTime();
	/* 前回から600ms未満なら終了 */
	if ( abs(ntime - btime) < 30 ){
		return;
	}
	btime = ntime;

	mem = EIN_checkMem();
	// 
	if ( mem > memLimit ){
		// 残りメモリが最初に取得した最大メモリ値以上なら
		ptn = PT_MEM;
	} else {
		if ( mem > 262144 ){
			// 256K以上ならメモリ表示
			ptn = PT_MEMMIN - ((mem / (memLimit / PT_MEMSIZE))%PT_MEMSIZE);
		} else {
			// 256K以下なら"涙"に
			if ( optn < PT_ANIMST ){
				ptn = PT_ANIMST;
			} else {
				ptn = (optn < PT_ANIMEND) ?optn+1 :PT_ANIMST;
			}
		}
	}
	// パターンが前と同じなら更新しない
	if ( ptn != optn ){
		MMI_SendMessage( ID_ICON[ID_BTNBASE], MM_SETSHAPE, 1, ptn);
		MMI_SendMessage( ID_ICON[ID_BTNBASE], MM_SHOW, 0 );
//		printf(" ptn=%d  (old:%d)\n", ptn, optn);
	}
	optn = ptn;
	
	// 残量が前と同じなら残量表示は更新しない
	dmem = mem / 100000;
	if ( dmem != omem ){
		// メモリ残量を数値表示
		pmem = mem / 10000000;
		if ( pmem < 1 ){
			pmem = -1;
		}
		__setNumFnt( ID_ICON[ID_NUM1], pmem );
		pmem = mem / 1000000;
		__setNumFnt( ID_ICON[ID_NUM2], pmem );
		pmem = mem / 100000;
		__setNumFnt( ID_ICON[ID_NUM3], pmem );
		
		MMI_SendMessage( ID_ICON[ID_NUMBASE], MM_SHOW, 0 );
		MMI_SendMessage( ID_ICON[ID_NUM1], MM_SHOW, 0 );
		MMI_SendMessage( ID_ICON[ID_NUM2], MM_SHOW, 0 );
		MMI_SendMessage( ID_ICON[ID_NUM3], MM_SHOW, 0 );
		
//		printf(" mem=%d  (%d: omem=%d)\n", mem, dmem, omem);
	}
	omem = dmem;
}

