/*//////////////////////////////////////////////////////////////////////////
// spf.h
// 主筆　プラグイン開発基本クラスライブラリ
// 2005/10/31
//////////////////////////////////////////////////////////////////////////*/

#include <malloc.h>
#include <string>
#include <wchar.h>
#include <memory.h>
#include <stdlib.h>
#include "../syuhitu/PluginFuncID.h"

#if !defined( SPF_H_INCLUDED_ )
#define SPF_H_INCLUDED_

// エラーが発生したときに例外として投げられるオブジェクト
class CSP_Err
{
public:
	CSP_Err( int argLF ) : LastFunction( argLF ) {};
	CSP_Err( const CSP_Err &r ) : LastFunction( r.LastFunction ) {};

	// 最後に実行した関数
	int LastFunction;
};

// プラグインに対し提供する機能
class CSyuhituPlugin
{
public:
	CSyuhituPlugin( void* (*argFunc)( int ) ) :
		GetAPIFunction( argFunc )
	{};

	CSyuhituPlugin( const CSyuhituPlugin &r ) :
		GetAPIFunction( r.GetAPIFunction )
	{};

	const CSyuhituPlugin& operator =( const CSyuhituPlugin &r ) {
		GetAPIFunction = r.GetAPIFunction;
		return (*this);
	};

	// 確認終了
	wchar_t GetChar( unsigned long argLine, unsigned long argCPos ) {
		PFT_GetChar pF = (PFT_GetChar)GetAPIFunction( PFID_GETCHAR );
		if ( !pF ) throw CSP_Err( PFID_GETCHAR );
		wchar_t r;
		if ( pF( argLine, argCPos, &r ) )
			return r;
		throw CSP_Err( PFID_GETCHAR );
		return NULL;
	};

	// 確認終了
	void SetChar( unsigned long argLine, unsigned long argCPos, wchar_t c ) {
		PFT_SetChar pF = (PFT_SetChar)GetAPIFunction( PFID_SETCHAR );
		if ( !pF ) throw CSP_Err( PFID_SETCHAR );
		if ( !pF( argLine, argCPos, c ) )
			throw CSP_Err( PFID_SETCHAR );
	};

	// 確認終了
	std::wstring GetString( unsigned long SLP, unsigned long SCP, unsigned long ELP, unsigned long ECP ) {
		PFT_GetCharCount GetCharCount = (PFT_GetCharCount)GetAPIFunction( PFID_GETCHARCOUNT );
		PFT_GetString GetString = (PFT_GetString)GetAPIFunction( PFID_GETSTRING );
		if ( !GetCharCount ) throw CSP_Err( PFID_GETSTRING );
		if ( !GetString ) throw CSP_Err( PFID_GETSTRING );
		unsigned long i;
		unsigned long len = 0;
		unsigned long wLen;
		wchar_t  *pBuf;
		std::wstring rStr;

		// 文字列を取得するために必要となる文字列長を取得する
		if ( SLP != ELP ) {
			if ( !GetCharCount( SLP, &wLen ) )
				throw CSP_Err( PFID_GETSTRING );
			len = wLen - SCP;
			for ( i = SLP + 1; i < ELP; i++ ) {
				if ( !GetCharCount( i, &wLen ) )
					throw CSP_Err( PFID_GETSTRING );
				len += wLen;
			}
			len += ECP;
		}
		else {
			len = ECP - SCP;
		}

		// メモリ領域を確保する
		pBuf = (wchar_t*)malloc( sizeof( wchar_t ) * ( len + 1 ) );
		if ( NULL == pBuf ) throw CSP_Err( PFID_GETSTRING );

		// 文字を取得する
		if ( !GetString( SLP, SCP, ELP, ECP, pBuf, len + 1 ) ) {
			free( pBuf );
			throw CSP_Err( PFID_GETSTRING );
		}
		rStr = pBuf;
		free( pBuf );
		return rStr;
	};

	// 確認終了
	void Replace( unsigned long SLP, unsigned long SCP, unsigned long ELP, unsigned long ECP, const wchar_t* pStr ) {
		PFT_Replace pF = (PFT_Replace)GetAPIFunction( PFID_REPLACE );
		if ( !pF ) throw CSP_Err( PFID_REPLACE );
		if ( pF( SLP, SCP, ELP, ECP, pStr ) ) return ;
		throw CSP_Err( PFID_REPLACE );
	};

	// 確認終了
	unsigned long GetLineCount() {
		PFT_GetLineCount pF = (PFT_GetLineCount)GetAPIFunction( PFID_GETLINECOUNT );
		if ( !pF ) throw CSP_Err( PFID_GETLINECOUNT );
		unsigned long r;
		if ( pF( &r ) ) return r;
		throw CSP_Err( PFID_GETLINECOUNT );
		return 0;
	};

	// 確認終了
	unsigned long GetCharCount( unsigned long argL ) {
		PFT_GetCharCount pF = (PFT_GetCharCount)GetAPIFunction( PFID_GETCHARCOUNT );
		if ( !pF ) throw CSP_Err( PFID_GETCHARCOUNT );
		unsigned long r;
		if ( pF( argL, &r ) ) return r;
		throw CSP_Err( PFID_GETCHARCOUNT );
		return 0;
	};

	// 確認終了
	void GetCurPosition( unsigned long *pLP, unsigned long *pCP ) {
		PFT_GetCurPosition pF = (PFT_GetCurPosition)GetAPIFunction( PFID_GETCURSORPOSITION );
		if ( !pF ) throw CSP_Err( PFID_GETCURSORPOSITION );
		unsigned long w1, w2;
		if ( !pLP ) pLP = &w1;
		if ( !pCP ) pCP = &w2;
		if ( pF( pLP, pCP ) ) return ;
		throw CSP_Err( PFID_GETCURSORPOSITION );
	};

	// 確認終了
	void SetCurPosition( unsigned long LP, unsigned long CP ) {
		PFT_SetCurPosition pF = (PFT_SetCurPosition)GetAPIFunction( PFID_SETCURSORPOSITION );
		if ( !pF ) throw CSP_Err( PFID_SETCURSORPOSITION );
		if ( pF( LP, CP ) ) return ;
		throw CSP_Err( PFID_SETCURSORPOSITION );
	};

	// 確認終了
	void GetSelectionRange( unsigned long *pSLP, unsigned long *pSCP, unsigned long *pELP, unsigned long *pECP ) {
		PFT_GetSelectionRange pF = (PFT_GetSelectionRange)GetAPIFunction( PFID_GETSELECTIONRANGE );
		if ( !pF ) throw CSP_Err( PFID_GETSELECTIONRANGE );
		unsigned long w1, w2, w3, w4;
		if ( !pSLP ) pSLP = &w1;
		if ( !pSCP ) pSCP = &w2;
		if ( !pELP ) pELP = &w3;
		if ( !pECP ) pECP = &w4;
		if ( pF( pSLP, pSCP, pELP, pECP ) ) return ;
		throw CSP_Err( PFID_GETSELECTIONRANGE );
	};

	// 確認終了
	void SetSelectionRange( unsigned long SLP, unsigned long SCP, unsigned long ELP, unsigned long ECP ) {
		PFT_SetSelectionRange pF = (PFT_SetSelectionRange)GetAPIFunction( PFID_SETSELECTIONRANGE );
		if ( !pF ) throw CSP_Err( PFID_SETSELECTIONRANGE );
		if ( pF( SLP, SCP, ELP, ECP ) ) return ;
		throw CSP_Err( PFID_SETSELECTIONRANGE );
	};

	// 確認終了
	const wchar_t* GetConfigValue( const wchar_t *pConf ) {
		PFT_GetConfigValue pF = (PFT_GetConfigValue)GetAPIFunction( PFID_GETCONFIGVALUE );
		if ( !pF ) throw CSP_Err( PFID_GETCONFIGVALUE );
		return pF( pConf );
	};

	// 確認終了
	const char* GetFileName() {
		PFT_GetFileName pF = (PFT_GetFileName)GetAPIFunction( PFID_GETFILENAME );
		if ( !pF ) throw CSP_Err( PFID_GETFILENAME );
		return pF();
	};

	// 確認終了
	const void ShowInformationMsgBox( const wchar_t *pMsg ) {
		PFT_ShowInformationMsgBox pF = (PFT_ShowInformationMsgBox)GetAPIFunction( PFID_SHOWINFORMATIONMSGBOX );
		if ( !pF ) throw CSP_Err( PFID_SHOWINFORMATIONMSGBOX );
		pF( pMsg );
	};

	// 確認終了
	int ShowQuestionMsgBox( const wchar_t *pMsg, PFT_BOOL ShowCancel ) {
		PFT_ShowQuestionMsgBox pF = (PFT_ShowQuestionMsgBox)GetAPIFunction( PFID_SHOWQUESTIONMSGBOX );
		if ( !pF ) throw CSP_Err( PFID_SHOWQUESTIONMSGBOX );
		return pF( pMsg, ShowCancel );
	};

	// 確認終了
	const void ShowErrorMsgBox( const wchar_t *pMsg ) {
		PFT_ShowErrorMsgBox pF = (PFT_ShowErrorMsgBox)GetAPIFunction( PFID_SHOWERRORMSGBOX );
		if ( !pF ) throw CSP_Err( PFID_SHOWERRORMSGBOX );
		pF( pMsg );
	};

	// 確認終了
	bool GetModifiedFlg() {
		PFT_GetModifiedFlg pF = (PFT_GetModifiedFlg)GetAPIFunction( PFID_GETMODIFIEDFLG );
		if ( !pF ) throw CSP_Err( PFID_GETMODIFIEDFLG );
		return pF();
	};

	// 確認終了
	int GetVersion() {
		PFT_GetVersion pF = (PFT_GetVersion)GetAPIFunction( PFID_GETVERSION );
		if ( !pF ) throw CSP_Err( PFID_GETVERSION );
		return pF();
	};

	// 確認終了
	int GetExtendInfoCount() {
		PFT_GetExtendInfoCount pF = (PFT_GetExtendInfoCount)GetAPIFunction( PFID_GETEXTENDINFOCOUNT );
		if ( !pF ) throw CSP_Err( PFID_GETEXTENDINFOCOUNT );
		return pF();
	};

	// 確認終了
	bool GetExtendInfo( unsigned long LP, unsigned long idx ) {
		PTF_GetExtendInfo pF = (PTF_GetExtendInfo)GetAPIFunction( PFID_GETEXTENDINFO );
		if ( !pF ) throw CSP_Err( PFID_GETEXTENDINFO );
		PFT_BOOL flg;
		if ( !pF( LP, idx, &flg ) ) throw CSP_Err( PFID_GETEXTENDINFO );
		return flg ? true : false;
	};

	// 確認終了
	void SetExtendInfo( unsigned long LP, unsigned long idx, bool flg ) {
		PTF_SetExtendInfo pF = (PTF_SetExtendInfo)GetAPIFunction( PFID_SETEXTENDINFO );
		if ( !pF ) throw CSP_Err( PFID_SETEXTENDINFO );
		if ( pF( LP, idx, flg ? PFT_TRUE : PFT_FALSE ) ) return ;
		throw CSP_Err( PFID_SETEXTENDINFO );
	};

	// 確認終了
	bool SaveFile() {
		PFT_SaveFile pF = (PFT_SaveFile)GetAPIFunction( PFID_SAVEFILE );
		if ( !pF ) throw CSP_Err( PFID_SAVEFILE );
		return pF() ? true : false;
	};

	// 確認終了
	bool OpenFile( const char* pFName ) {
		PFT_OpenFile pF = (PFT_OpenFile)GetAPIFunction( PFID_OPENFILE );
		if ( !pF ) throw CSP_Err( PFID_OPENFILE );
		return pF( pFName ) ? true : false;
	};

	// 確認終了
	bool OpenFileNewWindow( const char* pFName ) {
		PFT_OpenFileNewWindow pF = (PFT_OpenFileNewWindow)GetAPIFunction( PFID_OPENFILENEWWINDOW );
		if ( !pF ) throw CSP_Err( PFID_OPENFILENEWWINDOW );
		return pF( pFName ) ? true : false;
	};

	// 確認終了
	void* AllocWorkMemory( unsigned long size, const wchar_t* pName, bool IsGlobal ) {
		PFT_AllocWorkMemory pF = (PFT_AllocWorkMemory)GetAPIFunction( PFID_ALLOCWORKMEMORY );
		if ( !pF ) throw CSP_Err( PFID_ALLOCWORKMEMORY );
		return pF( size, pName, IsGlobal ? PFT_TRUE : PFT_FALSE );
	};

	// 確認終了
	void* FindWorkMemory( const wchar_t *pName, bool IsGlobal ) {
		PFT_FindWorkMemory pF = (PFT_FindWorkMemory)GetAPIFunction( PFID_FINDWORKMEMORY );
		if ( !pF ) throw CSP_Err( PFID_FINDWORKMEMORY );
		return pF( pName, IsGlobal ? PFT_TRUE : PFT_FALSE );
	};

	// 確認終了
	void FreeWorkMemory( const wchar_t *pName, bool IsGlobal ) {
		PFT_FreeWorkMemory pF = (PFT_FreeWorkMemory)GetAPIFunction( PFID_FREEWORKMEMORY );
		if ( !pF ) throw CSP_Err( PFID_FREEWORKMEMORY );
		pF( pName, IsGlobal ? PFT_TRUE : PFT_FALSE );
	};

	// ワイドバイト文字列に変換
	static std::wstring MbstoWcs( const char *pStr ) {
		wchar_t *pBuf;
		std::wstring rStr;
		size_t len = mbstowcs( NULL, pStr, 0 ) + 1;
		if ( len == 0 ) return L"";

		// メモリ領域を確保
		pBuf = (wchar_t*)malloc( sizeof( wchar_t ) * len );
		if ( NULL == pBuf ) throw CSP_Err( -1 );

		// ワイドバイト文字列に変換
		if ( mbstowcs( pBuf, pStr, len * sizeof( wchar_t ) ) == (size_t)-1 ) {
			free( pBuf );
			throw CSP_Err( -1 );
		}

		// 戻り値に設定
		rStr = pBuf;

		// メモリ領域を開放
		free( pBuf );
		pBuf = NULL;

		return rStr;
	};

	// マルチバイト文字列に変換
	static std::string WcstoMbs( const wchar_t *pStr ) {
		char *pBuf;
		std::string rStr;
		size_t len = wcstombs( NULL, pStr, 0 ) + 1;
		if ( len == 0 ) return "";

		// メモリ領域を確保
		pBuf = (char*)malloc( sizeof( char ) * len );
		if ( NULL == pBuf ) throw CSP_Err( -1 );

		// マルチバイト文字列に変換
		if ( wcstombs( pBuf, pStr, len * sizeof( char ) ) == (size_t)-1 ) {
			free( pBuf );
			throw CSP_Err( -1 );
		}

		// 戻り値に設定
		rStr = pBuf;

		// メモリ領域を開放
		free( pBuf );
		pBuf = NULL;

		return rStr;
	};

protected:
	void* (*GetAPIFunction)( int );
};

#endif // SPF_H_INCLUDED_

