#include "stdafx.h"
#include "dKingyoMacro.h"
#include "dkutilDefinedC.h"
#include "dkutilDefined.h"
#include "dKingyoUtilClass.h"

namespace dkutil{ // begin dKingyoUtility namespace 

		


bool BitIsVisualized( char *buff,size_t buffsize,unsigned int dt ){
    int i, len;
		char *p=buff;
    len = sizeof(dt) * CHAR_BIT;
    int a=0;
		for ( i=len-1; i >= 0; i-- ){
        // ビットをぶち込む
				if(0 > _snprintf(p,buffsize,"%u",( dt>>i ) & 0x0001))
					return false;
				p++;
		}
		return true;
}



bool CharMatch(const char *src,const char *str){
	bool r=false;
	int SrcLen=strlen(src);
	int i=0;
	for(i=0;i<SrcLen;i++){
		if( str[i]==NULL && src[i] != str[i])
			break;
	}
	if(i-1 == SrcLen)
		r=true;

	return r;
}



/*!
@note
	出典：二反田 雅彦 氏のKittyエンジンより

  strnicmp - ２つの文字列中の文字を、大文字小文字を区別せずに
              比較します。

  ※この関数は、Visual C++にはあるが、ボーランドコンパイラには
  なかった。このため、ボーランド用に作成した。
  　ここでは、あまり役に立たない文字列の大小の判定は行わないこ
  ととする。

　引数：
    const char *string1　比較する文字１
    const char *string2　比較する文字２
    size_t     count　　 比較する文字数

  戻り値：
    int ２つの文字が等しければ０を、等しくなければ１を返す
        ※比較する文字数に達する前に、文字列の終端に達した場合は、
        等しくないとみなす。

@param string1　比較する文字１
@param string2　比較する文字２
@param 比較する文字数
@return ２つの文字が等しければ０を、等しくなければ１を返す
※比較する文字数に達する前に、文字列の終端に達した場合は、等しくないとみなす。
*/
DINLINE int strnicmp(
    const char *string1, const char *string2, size_t count)
{
    int c1, c2;
    
    --count;
    
    for (; count ; --count){
        c1 = string1[count];
        c2 = string2[count];
        
        // 文字列の終端チェック
        if (!c1) return 1;
        if (!c2) return 1;
        
        // 大文字の場合、小文字に変換する
        if ('A' <= c1 && c1 <= 'Z') c1 += 'a' - 'A';
        if ('A' <= c2 && c2 <= 'Z') c2 += 'a' - 'A';
        
        // 両方とも小文字になったので、比較する
        if (c1 != c2) return 1;
    }
    
    return 0;
}// _strnicmp




/*
char *dGetCurrentDirectory(void){
	static char str[MAX_PATH];
	::memset(str,0,sizeof(str));
	::GetCurrentDirectory(MAX_PATH,str);
	return str;
}
*/


//ファイル情報取得とか？



	

//**********************************************************
//ログ吐き系
//**********************************************************



int dSentenceOut(char *filename,size_t plusbytesize,char *str,...){
	int result=-1;

	size_t strlength=strlen(str) + 1;
	size_t buffsize = strlength + plusbytesize;
	char *s = (char *)::malloc(buffsize);
	if(!s){goto dSentenceOutExit;}
	memset(s,'\0',buffsize);//メモリ初期化
	SET_VA_LIST_INSERT_YEN_N(s,buffsize,str);
	FILE *fp;
	//ファイルをオープン
	if(NULL == (fp = fopen( filename , "at" )))
		goto dSentenceOutExit;
		

	// エラーログファイルに書き出す
	fputs( s , fp ) ;
	fclose( fp ) ;
	result=0;
	goto dSentenceOutExit;
dSentenceOutExit:
	if(s){::free((void *)s);s=NULL;}
	return result;
}

int OutputWindowString( HWND hWnd,DWORD dwStyle,char *str,... ){
	if ( hWnd == NULL ) return -1;
	char buff[1024]="";
	SET_VA_LIST(buff,1024,str);
	//switch(dwStyle){
	//	case NULL 
	::SendMessage( hWnd, LB_ADDSTRING, 0, (long)buff );
	::SendMessage( hWnd , WM_VSCROLL, SB_LINEDOWN, 0 );
	//}
	return 0;
}

//***********************************
//忌み嫌われるレジストリ系
//gotoとかを使用すればもっとキレイなプログラムにナルハズ。
//いや、try catchかな？
//なお、関数類のテストは行っていません。(爆！
//だれかテストしてくれい＾＾；(2002/12/7)



/*lpSubKey サブキーの名前 
lpValueName レジストリの名前
dwType タイプを設定する。詳しくはRegSetValueExにて
lpData Dataを入れる
cdData Dataのサイズを指定する
*/
bool dSaveRegData(LPCTSTR lpSubKey,LPCTSTR lpValueName,DWORD dwType,CONST BYTE *lpData,	DWORD cbData){
	LONG r=ERROR_SUCCESS; 
	HKEY regKeyH;//レジストリのキーらしい
	DWORD sized;
	//レジストリから調べる
	r=RegCreateKeyEx(
		HKEY_CURRENT_USER,
		lpSubKey,//"DxLibSaverData\\Path",
		NULL, 
		"",
		REG_OPTION_NON_VOLATILE,
		KEY_ALL_ACCESS,
		NULL,
		(PHKEY)&regKeyH,
		(LPDWORD)&sized 
		);
	if(r!=ERROR_SUCCESS){
		MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}

	r= RegSetValueEx(
		regKeyH,		// 現在オープンしているキーのハンドル
		lpValueName,	// 値の「名前」が入った文字列へのポインタ
		NULL,		// 予約パラメータ。0を指定する
		dwType,		// 値の「種類」を指定する。NULLで終わる文字列はREG_SZ、32ビット値はREG_DWORD
		(CONST BYTE *)lpData,	// 格納する値の「データ」が入ったバッファへのポインタ
		cbData		// lpDataのサイズを指定する
	);
	if(r!=ERROR_SUCCESS ){
		MessageBox(NULL, "レジストリに値を設定できませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}
	RegCloseKey(regKeyH);

	return true;
}

/*
lpSubKey,      サブキーの名前
lpValueName レジストリの名前
lpType 受け取るタイプ
lpData 受け取るデータ
lpcdData   lpDataのサイズを指定する。関数実行後はlpDataにコピーされたデータのサイズになる
*/
bool dGetRegData(LPCTSTR lpSubKey,LPTSTR lpValueName,LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData){
	LONG r=ERROR_SUCCESS; 
	HKEY regKeyH;//レジストリのキーらしい
	DWORD sized;
	//レジストリから調べる
	r=RegCreateKeyEx(
		HKEY_CURRENT_USER,
		lpSubKey,//"DxLibSaverData\\Path",
		NULL, 
		"",
		REG_OPTION_NON_VOLATILE,
		KEY_ALL_ACCESS,
		NULL,
		(PHKEY)&regKeyH,
		(LPDWORD)&sized 
		);
	if(r!=ERROR_SUCCESS){
		MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}
	r= RegQueryValueEx(
		regKeyH,		// 現在オープンしているキーのハンドル
		 lpValueName,	// 取得する値の「名前」が入った文字列へのポインタ
		NULL,	// 予約パラメータ。NULLを指定する
		lpType,		// 値の「種類」を受け取る
		lpData,		// 値の「データ」を受け取る。NULLを指定することも可能だが、データは受け取れない
		lpcbData		// lpDataのサイズを指定する。関数実行後はlpDataにコピーされたデータのサイズになる
	);
	if(r!=ERROR_SUCCESS){
		MessageBox(NULL, "レジストリの中身を抜き取れませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}
	RegCloseKey(regKeyH);
	return true;
}

bool dDeleteValueRegData(LPCTSTR lpSubKey,LPTSTR lpValueName)
//LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData
{
	LONG r=ERROR_SUCCESS; 
	HKEY regKeyH;//レジストリのキーらしい
	DWORD sized;
	//レジストリから調べる
	r=RegCreateKeyEx(
		HKEY_CURRENT_USER,
		lpSubKey,//"DxLibSaverData\\Path",
		NULL, 
		"",
		REG_OPTION_NON_VOLATILE,
		KEY_ALL_ACCESS,
		NULL,
		(PHKEY)&regKeyH,
		(LPDWORD)&sized 
		);
	if(r!=ERROR_SUCCESS){
		MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}
	r=RegDeleteValueA(
			regKeyH,       //キーのハンドル
			lpValueName  //削除する値の名前
	);

	if(r!=ERROR_SUCCESS){
		MessageBox(NULL, "レジストリの中身を初期化(削除)できませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}
	RegCloseKey(regKeyH);
	return true;
}

//9x系では,下のキーを全て削除してしまうので気をつけるように。
bool dDeleteRegData(LPCTSTR lpSubKey)
//LPTSTR lpValueName,LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData
{
	LONG r=ERROR_SUCCESS; 
	HKEY regKeyH;//レジストリのキーらしい
	DWORD sized;
	//レジストリから調べる
	r=RegCreateKeyEx(
		HKEY_CURRENT_USER,
		lpSubKey,//"DxLibSaverData\\Path",
		NULL, 
		"",
		REG_OPTION_NON_VOLATILE,
		KEY_ALL_ACCESS,
		NULL,
		(PHKEY)&regKeyH,
		(LPDWORD)&sized 
		);

	if(r!=ERROR_SUCCESS){
		MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}
	r=RegDeleteKey(
		HKEY_CURRENT_USER,
		lpSubKey
	);

	if(r!=ERROR_SUCCESS){
		MessageBox(NULL, "レジストリを初期化(削除)できませんでした。", "設定値取得エラー", MB_OK);
		RegCloseKey(regKeyH);
		return(false);
	}
	RegCloseKey(regKeyH);
	return true;
}


//*****************************************
//システム情報等、取得系
//**************************************



void GetCharOfTimeUpToMinute(char *buff,size_t buffsize,bool Sysflag)
{
	SYSTEMTIME lpSystemTime={0};
	if(Sysflag){
		GetSystemTime(
			&lpSystemTime   // address of system time structure
		);
	}else{
		GetLocalTime(&lpSystemTime);
	}
	_snprintf(buff,buffsize,"%d:%d %d/%d/%d",
		lpSystemTime.wHour,
		lpSystemTime.wMinute,
		lpSystemTime.wYear,
		lpSystemTime.wMonth,
		lpSystemTime.wDay
		);
		//10:47 2003/05/31
}
void GetCharOfMemoPadTypeTime(char *buff,size_t buffsize){
	GetCharOfTimeUpToMinute(buff,buffsize,false);
}

void GetCharOfSystemTimeAll(char *buff,size_t buffsize)
{
	SYSTEMTIME lpSystemTime={0};
	GetSystemTime(
		&lpSystemTime   // address of system time structure
	);
	LPSTR lpszDayOfWeek = NULL;
	//曜日文字列の作成
  switch (lpSystemTime.wDayOfWeek){
  case 0: lpszDayOfWeek = "Sun";   break;
  case 1: lpszDayOfWeek = "Mon";   break;
  case 2: lpszDayOfWeek = "Tue";   break;
  case 3: lpszDayOfWeek = "Wed";   break;
  case 4: lpszDayOfWeek = "Thu";   break;
  case 5: lpszDayOfWeek = "Fri";   break;
  case 6: lpszDayOfWeek = "Sat";   break;
  }   // 曜日文字列の作成
	_snprintf(buff,buffsize,"%d:%d:%d.%d %d/%d/%d/%s",
		lpSystemTime.wHour,
		lpSystemTime.wMinute,
		lpSystemTime.wSecond,
		lpSystemTime.wMilliseconds,
		lpSystemTime.wYear,
		lpSystemTime.wMonth,
		lpSystemTime.wDay,
		lpszDayOfWeek
		);
}

void GetCharOfLocalTimeAllJapanese(char *buff,size_t buffsize){
  SYSTEMTIME  time;           //時刻
  LPCSTR      lpszDayOfWeek;  //曜日

  //ローカル時間の取得
  GetLocalTime (&time);

  //曜日文字列の作成
  switch (time.wDayOfWeek){
  case 0: lpszDayOfWeek = "日";   break;
  case 1: lpszDayOfWeek = "月";   break;
  case 2: lpszDayOfWeek = "火";   break;
  case 3: lpszDayOfWeek = "水";   break;
  case 4: lpszDayOfWeek = "木";   break;
  case 5: lpszDayOfWeek = "金";   break;
  case 6: lpszDayOfWeek = "土";   break;
  }   // 曜日文字列の作成

  //文字列の書式か
  _snprintf(buff,buffsize,"%d年%d月%d日（%s曜日） %d時%d分%d.%d秒",
      time.wYear, time.wMonth, time.wDay, lpszDayOfWeek,
      time.wHour, time.wMinute, time.wSecond, time.wMilliseconds
  );

}


//クリップボードのテキストをパクル
//たまにうまくクリップボードを開けないときがあるので何度か試すように。
//また、pstrMemoryのポインタはGlobalAllocで確保したものにすること。
bool GetClipboardText(char *pstrMemory,DWORD size)
{
	HANDLE hText;
	//char *pText;
	bool f=true;
	if(TRUE==OpenClipboard(NULL))
		return false;

	hText = GetClipboardData(CF_TEXT);
	if(hText == NULL){
		f=false;
		CloseClipboard();
		return f;
	}
	
	LPSTR m;
	m= (LPSTR)GlobalLock(hText);
	if(m!=NULL){
		// テキストオブジェクトからデータを取得
    strncpy(pstrMemory, m,size);
		GlobalUnlock(m);
		CloseClipboard();
	}	
		
	
	return f;	

}







void ERROR_BOX(char *str,...){
		char s[512];
		va_list VaList ;
		va_start( VaList , str ) ;
		vsprintf( s , str , VaList ) ;
		va_end( VaList ) ;
		MessageBox(NULL,s,"ERROR_BOX",MB_OK);
}

int DefaultOutputDebugString(char *str){
	OutputDebugString(str);
	return 0;
}
void Return(){
}


#define jms1(c) (((((unsigned char)(c))>=0x81)&&(((unsigned char)(c))<=0x9F))||((((unsigned char)(c))>=0xE0)&&(((unsigned char)(c))<=0xFC)))
#define jms2(c) ((((unsigned char)(c))!=0x7F)&&(((unsigned char)(c))>=0x40)&&(((unsigned char)(c))<=0xFC))

//*********************************************************
// 文字列 str の str[nPos] について、
//   ０ …… １バイト文字
//   １ …… ２バイト文字の一部（第１バイト）
//   ２ …… ２バイト文字の一部（第２バイト）
// のいずれかを返す。
//*********************************************************
int isJMS( const char *str, int nPos )
{
	int i;
	int state; // { 0, 1, 2 } = { １バイト文字, ２バイト文字の第１バイト, ２バイト文字の第２バイト }

	state = 0;
	for( i = 0; str[i] != '\0'; i++ )
	{
		if      ( ( state == 0 ) && ( jms1( str[i] ) ) ) state = 1; // 0 -> 1
		else if ( ( state == 1 ) && ( jms2( str[i] ) ) ) state = 2; // 1 -> 2
		else if ( ( state == 2 ) && ( jms1( str[i] ) ) ) state = 1; // 2 -> 1
		else                                             state = 0; // 2 -> 0, その他

		// str[nPos] での状態を返す。
		if ( i == nPos ) return state;
	}
	return 0;
}//isJMS



//memory swap;
void memswap( void *va, void *vb, size_t size )
{
	char *ca;
	char *cb;
	char  cTmp;
	for( ca = (char *)va, cb = (char *)vb; size > 0; size--, ca++, cb++ )
	{
		cTmp = *ca;
		*ca  = *cb;
		*cb  = cTmp;
	}
}//memswap



// 大きさ size の要素 num 個からなる配列 array の要素を
// 逆順に並べ替える。
void memreverse( void *array, size_t num, size_t size )
{
	char *l;
	char *r;

	l = (char *)array;
	r = (char *)array + ((num-1) * size);
	for( ; l < r; l = l+size, r = r-size )
		memswap( l, r, size );
}//memreverse


// 大きさ size の要素 num 個からなる配列 array の要素を
// 右方向に要素 shift 個分だけ回転移動する。
void memrrotate( void *array, size_t shift, size_t num, size_t size )
{
	memreverse( array,                      num,       size ); // 012345678 -> 876543210
	memreverse( array,                      shift,     size ); // 876543210 -> 678543210
	memreverse( (char *)array+(size*shift), num-shift, size ); // 678543210 -> 678012345
}//memrrotate


// 大きさ size の要素 num 個からなる配列 array の要素を
// 左方向に要素 shift 個分だけ回転移動する。
void memlrotate( void *array, size_t shift, size_t num, size_t size )
{
	memreverse( array,                      shift,     size ); // 012345678 -> 210345678
	memreverse( (char *)array+(size*shift), num-shift, size ); // 210345678 -> 210876543
	memreverse( array,                      num,       size ); // 210876543 -> 345678012
}//memlrotate

// 閏年(leap year)かどうかを確かめる。
// 閏年であれば真、さもなくば偽を返す
int IsLeapYear( int Year )
{
	return (((Year%4)==0)&&((Year%100)!=0)||((Year%400)==0));
}//IsLeapYear


// 有効な日付であれば真、さもなくば偽を返す
int IsGoodDate( int Year, int Month, int Day )
{
	return ((Month>=1)&&(Month<=12)&&(Day>=1)&&(Day<=DaysInMonth(Year,Month)));
}//IsGoodDate

// 指定された月の最終日を返す
// 入力された月が不正（１月〜12月の範囲外）であれば０を返す
int DaysInMonth( int nYear, int nMonth )
{
	const int nDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

	if ( ( nMonth < 1 ) || ( nMonth > 12 ) ) return 0;
	if ( (2 == nMonth) && IsLeapYear(nYear) ) return 29;

	return nDaysInMonth[nMonth-1];
}//DaysInMonth



// グレゴリウス歴(Gregorian calendar)の範囲内かどうかを確かめる。
// 1582年10月15日以降であれば真、さもなくば偽を返す
int IsGregory( int Year, int Month, int Day )
{
	return ((Year>1582)||((Year==1582)&&((Month>10)||((Month==10)&&(Day>=15)))));
}//IsGregory


// 最大公約数（Greatest Common Divisor）を返す。
// 引数に０がある場合は０を返す。

int gcd( int m, int n )
{
	// 引数に０がある場合は０を返す
	if ( ( 0 == m ) || ( 0 == n ) )
		return 0;
	
	// ユークリッドの互除法
	while( m != n )
	{
		if ( m > n ) m = m - n;
		else         n = n - m;
	}
	return m;
}//gcd

// 最小公倍数（Least Common Multiple）を返す。
// 引数に０がある場合は０を返す。
int lcm( int m, int n )
{
	// 引数に０がある場合は０を返す
	if ( ( 0 == m ) || ( 0 == n ) )
		return 0;
	
	return ((m / gcd(m, n)) * n); // lcm = m * n / gcd(m,n)
}//lcm



} // the end of dKingyoUtility namespace


/*
class dURLEncode{
protected:
public:
	dURLEncode(){}
	virtual ~dURLEncode(){}
	virtual int TwoHex2Int(char c1, char c2) {
		int Hi = c1, Lo = c2 , Result;
    
		if ('0'<=Hi && Hi<='9')      Hi -= '0';
		else if ('a'<=Hi && Hi<='f') Hi -= ('a'-10);
		else if ('A'<=Hi && Hi<='F') Hi -= ('A'-10);
    
		if ('0'<=Lo && Lo<='9')      Lo -= '0';
		else if ('a'<=Lo && Lo<='f') Lo -= ('a'-10);
		else if ('A'<=Lo && Lo<='F') Lo -= ('A'-10);

		Result = Lo + 16*Hi;
		return Result;
	}
	
	 // URLエンコード
	 //  引数の文字列を URLエンコードした文字列を返す
	 //
	int URLEncode(char *src,char *buff,size_t buffsize)
	{
		int len;
		char *DestString=(char *)malloc(len=strlen(src));
		memset(DestString,0,len);
		for(int i=0; i<len; i++)
		{
			char c = src[i];
			//if( isalnum(c) )  // Alpha Numeric Char
			if (  (c>=48 && c<= 57) || ( c>= 65 && c<= 90) || (c>= 97 && c<= 122) ) {
				//DestString += c;
				strncat(DestString,&c,len);
			} 
			else if(c == ' ') { // Space Char
				strncat(DestString,"+",len);
			} 
			else {              // Other Char
				char temp[512];
				//temp.Format("%%%02x", (unsigned char)c);
				_snprintf( temp,512,"%%%02x",(unsigned char)c);
				strncat(DestString,temp,len);
			}
		}
		strncpy(buff,DestString,buffsize);
		free(DestString);
		return 0;
	}

};

class dURLEncode_of_MFC : public dURLEncode{
public:
	dURLEncode_of_MFC(){}
	virtual ~dURLEncode_of_MFC(){}
	

 // URLエンコード
   //引数の文字列を URLエンコードした文字列を返す
 
	CString URLEncode(CString & SrcString)
	{
		CString DestString;
		int len = SrcString.GetLength();
		for(int i=0; i<len; i++)
		{
			TCHAR c = SrcString[i];
			//if( isalnum(c) )  // Alpha Numeric Char
			if (  (c>=48 && c<= 57) || ( c>= 65 && c<= 90) || (c>= 97 && c<= 122) ) {
				DestString += c;
			} 
			else if(c == ' ') { // Space Char
				DestString += "+";
			} 
			else {              // Other Char
				CString temp;
				temp.Format("%%%02x", (unsigned char)c);
				DestString += temp;
			}
		}
		return DestString;
	}
	
	 // URLデコード
	 //  引数の文字列を URLデコードした文字列を返す
	 
	CString URLDecode(CString & SrcString)
	{
		CString DestString;
		int len = SrcString.GetLength();
		for(int i=0; i<len; i++)
		{
			if(SrcString[i]=='%') {      // Non Alpha Numeric Char
				i++;
				if (isxdigit(SrcString[i]) && isxdigit(SrcString[i+1])) {
					DestString += (TCHAR) TwoHex2Int(SrcString[i], SrcString[i+1]);
					
					i++;
				}
			}
			else if(SrcString[i]=='+') { // Space Char
				DestString += " ";
			}
			else {                       // Other Char
				DestString += SrcString[i];
			}
		}
		return DestString;
	}
};





*/

