⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ckeymacromgr.cpp

📁 日本的开源编辑器源码
💻 CPP
字号:
//	$Id: CKeyMacroMgr.cpp,v 1.18 2005/01/30 16:27:51 Administrator Exp $
/*!	@file
	@brief キーボードマクロ

	@author Norio Nakatani

	@date 20011229 aroka バグ修正、コメント追加
	YAZAKI 組替え
	$Revision: 1.18 $
*/
/*
	Copyright (C) 1998-2001, Norio Nakatani
	Copyright (C) 2001, aroka

	This source code is designed for sakura editor.
	Please contact the copyright holder to use this code for other purpose.
*/

#include <stdio.h>
//	#include <stdlib.h>
//	#include <malloc.h>
#include <string.h>
#include "CKeyMacroMgr.h"
#include "CMacro.h"
#include "CSMacroMgr.h"// 2002/2/10 aroka
#include "debug.h"
#include "charcode.h"
#include "etc_uty.h" // Oct. 5, 2002 genta
//	#include "global.h"
//	#include "CEditView.h"
#include "CMemory.h"
#include "CMacroFactory.h"

CKeyMacroMgr::CKeyMacroMgr()
{
	m_pTop = NULL;
	m_pBot = NULL;
//	m_nKeyMacroDataArrNum = 0;	2002.2.2 YAZAKI
	//	Apr. 29, 2002 genta
	//	m_nReadyはCMacroManagerBaseへ
	return;
}

CKeyMacroMgr::~CKeyMacroMgr()
{
	/* キーマクロのバッファをクリアする */
	ClearAll();
	return;
}


/*! キーマクロのバッファをクリアする */
void CKeyMacroMgr::ClearAll( void )
{
	CMacro* p = m_pTop;
	CMacro* del_p;
	while (p){
		del_p = p;
		p = p->GetNext();
		delete del_p;
	}
//	m_nKeyMacroDataArrNum = 0;	2002.2.2 YAZAKI
	m_pTop = NULL;
	m_pBot = NULL;
	return;

}

/*! キーマクロのバッファにデータ追加
	機能番号と、引数ひとつを追加版。
	@date 2002.2.2 YAZAKI pcEditViewも渡すようにした。
*/
void CKeyMacroMgr::Append( int nFuncID, LPARAM lParam1, CEditView* pcEditView )
{
	CMacro* macro = new CMacro( nFuncID );
	macro->AddLParam( lParam1, pcEditView );
	Append(macro);
}

/*! キーマクロのバッファにデータ追加
	CMacroを指定して追加する版
*/
void CKeyMacroMgr::Append( CMacro* macro )
{
	if (m_pTop){
		m_pBot->SetNext(macro);
		m_pBot = macro;
	}
	else {
		m_pTop = macro;
		m_pBot = m_pTop;
	}
//	m_nKeyMacroDataArrNum++;	2002.2.2 YAZAKI
	return;
}



/*! キーボードマクロの保存
	エラーメッセージは出しません。呼び出し側でよきにはからってください。
*/
BOOL CKeyMacroMgr::SaveKeyMacro( HINSTANCE hInstance, const char* pszPath ) const
{
	HFILE		hFile;
	char		szLine[1024];
	CMemory		cmemWork;
	hFile = _lcreat( pszPath, 0 );
	if( HFILE_ERROR == hFile ){
		return FALSE;
	}
	strcpy( szLine, "//キーボードマクロのファイル\r\n" );
	_lwrite( hFile, szLine, strlen( szLine ) );
	CMacro* p = m_pTop;

	while (p){
		p->Save( hInstance, hFile );
		p = p->GetNext();
	}
	_lclose( hFile );
	return TRUE;
}



/*! キーボードマクロの実行
	CMacroに委譲。
*/
void CKeyMacroMgr::ExecKeyMacro( CEditView* pcEditView ) const
{
	CMacro* p = m_pTop;
	while (p){
		p->Exec(pcEditView);
		p = p->GetNext();
	}
}

/*! キーボードマクロの読み込み
	エラーメッセージは出しません。呼び出し側でよきにはからってください。
*/
BOOL CKeyMacroMgr::LoadKeyMacro( HINSTANCE hInstance, const char* pszPath )
{
	/* キーマクロのバッファをクリアする */
	ClearAll();

	FILE* hFile = fopen( pszPath, "r" );
	if( NULL == hFile ){
		m_nReady = false;
		return FALSE;
	}

	char	szFuncName[100];
	char	szFuncNameJapanese[256];
	int		nFuncID;
	int		i;
	int		nBgn, nEnd;
	CMemory cmemWork;
	CMacro* macro = NULL;

	//	Jun. 16, 2002 genta
	m_nReady = true;	//	エラーがあればfalseになる
	static const char MACRO_ERROR_TITLE[] = "Macro読み込みエラー";

	// 一行ずつ読みこみ、コメント行を排除した上で、macroコマンドを作成する。
	char	szLine[10240];
	
	int line = 1;	//	エラー時に行番号を通知するため.1始まり.
	for( ; NULL != fgets( szLine, sizeof(szLine), hFile ) ; ++line ){
		int nLineLen = strlen( szLine );
		// 先行する空白をスキップ
		for( i = 0; i < nLineLen; ++i ){
			//	Jun. 16, 2002 genta '\r' 追加
			if( szLine[i] != SPACE && szLine[i] != TAB && szLine[i] != '\r' ){
				break;
			}
		}
		nBgn = i;
		// コメント行の検出
		//# パフォーマンス:'/'のときだけ2文字目をテスト
		if( szLine[nBgn] == '/' && nBgn + 1 < nLineLen && szLine[nBgn + 1] == '/' ){
			continue;
		}
		//	Jun. 16, 2002 genta 空行を無視する
		if( szLine[nBgn] == '\n' || szLine[nBgn] == '\0' ){
			continue;
		}

		// 関数名の取得
		szFuncName[0]='\0';// 初期化
		for( ; i < nLineLen; ++i ){
			//# バッファオーバーランチェック
			if( szLine[i] == '(' && (i - nBgn)< sizeof(szFuncName) ){
				memcpy( szFuncName, &szLine[nBgn], i - nBgn );
				szFuncName[i - nBgn] = '\0';
				++i;
				nBgn = i;
				break;
			}
		}
		// 関数名にS_が付いていたら

		/* 関数名→機能ID,機能名日本語 */
		//@@@ 2002.2.2 YAZAKI マクロをCSMacroMgrに統一
//		nFuncID = CMacro::GetFuncInfoByName( hInstance, szFuncName, szFuncNameJapanese );
		nFuncID = CSMacroMgr::GetFuncInfoByName( hInstance, szFuncName, szFuncNameJapanese );
		if( -1 != nFuncID ){
			macro = new CMacro( nFuncID );
			// Jun. 16, 2002 genta プロトタイプチェック用に追加
			int nArgs;
			const MacroFuncInfo* mInfo= CSMacroMgr::GetFuncInfoByID( nFuncID );
			//	Skip Space
			for(nArgs = 0; szLine[i] ; ++nArgs ) {
				// Jun. 16, 2002 genta プロトタイプチェック
				if( nArgs >= sizeof( mInfo->m_varArguments ) / sizeof( mInfo->m_varArguments[0] )){
					::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE,
						_T("Line %d: Column %d: 引数が多すぎます\n" ), line, i + 1 );
					m_nReady = false;
				}

				while( szLine[i] == ' ' || szLine[i] == '\t' )
					i++;

				//@@@ 2002.2.2 YAZAKI PPA.DLLマクロにあわせて仕様変更。文字列は''で囲む。
				//	Jun. 16, 2002 genta double quotationも許容する
				if( '\'' == szLine[i] || '\"' == szLine[i]  ){	//	'で始まったら文字列だよきっと。
					// Jun. 16, 2002 genta プロトタイプチェック
					// Jun. 27, 2002 genta 余分な引数を無視するよう,VT_EMPTYを許容する.
					if( mInfo->m_varArguments[nArgs] != VT_BSTR && 
						mInfo->m_varArguments[nArgs] != VT_EMPTY ){
						::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE,
							_T("Line %d: Column %d\r\n"
							"関数%sの%d番目の引数に文字列は置けません." ), line, i + 1, szFuncName, nArgs + 1 );
						m_nReady = false;
						break;
					}
					int cQuote = szLine[i];
					++i;
					nBgn = i;	//	nBgnは引数の先頭の文字
					//	Jun. 16, 2002 genta
					//	行末の検出のため,ループ回数を1増やした
					for( ; i <= nLineLen; ++i ){		//	最後の文字+1までスキャン
						if( _IS_SJIS_1( (unsigned char)szLine[i] ) ){
							++i;
							continue;
						}
						if( szLine[i] == '\\' ){	// エスケープのスキップ
							++i;
							continue;
						}
						if( szLine[i] == cQuote ){	//	始まりと同じquotationで終了。
							nEnd = i;	//	nEndは終わりの次の文字(')
							break;
						}
						if( szLine[i] == '\0' ){	//	行末に来てしまった
							::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE,
								_T("Line %d:\r\n関数%sの%d番目の引数の終わりに%cがありません." ),
								line, szFuncName, nArgs + 1, cQuote);
							m_nReady = false;
							nEnd = i - 1;	//	nEndは終わりの次の文字(')
							break;
						}
					}
					//	Jun. 16, 2002 genta
					if( !m_nReady ){
						break;
					}
					cmemWork.SetData( szLine + nBgn, nEnd - nBgn );
					cmemWork.Replace( "\\\'", "\'" );

					//	Jun. 16, 2002 genta double quotationもエスケープ解除
					cmemWork.Replace( "\\\"", "\"" );
					cmemWork.Replace( "\\\\", "\\" );
					macro->AddParam( cmemWork.GetPtr() );	//	引数を文字列として追加
				}
				else if ( '0' <= szLine[i] && szLine[i] <= '9' ){	//	数字で始まったら数字列だ。
					// Jun. 16, 2002 genta プロトタイプチェック
					// Jun. 27, 2002 genta 余分な引数を無視するよう,VT_EMPTYを許容する.
					if( mInfo->m_varArguments[nArgs] != VT_I4 && 
						mInfo->m_varArguments[nArgs] != VT_EMPTY){
						::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE,
							_T("Line %d: Column %d\r\n"
							"関数%sの%d番目の引数に数値は置けません." ), line, i + 1, szFuncName, nArgs + 1);
						m_nReady = false;
						break;
					}
					nBgn = i;	//	nBgnは引数の先頭の文字
					for( ; i < nLineLen; ++i ){		//	最後の文字までスキャン
						if( '0' <= szLine[i] && szLine[i] <= '9' ){	// まだ数値
//							++i;
							continue;
						}
						else {
							nEnd = i;	//	数字の最後の文字
							i--;
							break;
						}
					}
					cmemWork.SetData( szLine + nBgn, nEnd - nBgn );
					// Jun. 16, 2002 genta
					//	数字の中にquotationは入っていないよ
					//cmemWork.Replace( "\\\'", "\'" );
					//cmemWork.Replace( "\\\\", "\\" );
					macro->AddParam( cmemWork.GetPtr() );	//	引数を文字列として追加
				}
				//	Jun. 16, 2002 genta
				else if( szLine[i] == ')' ){
					//	引数無し
					break;
				}
				else {
					//	Parse Error:文法エラーっぽい。
					//	Jun. 16, 2002 genta
					nBgn = nEnd = i;
					::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE,
						_T("Line %d: Column %d: Syntax Error\n" ), line, i );
					m_nReady = false;
					break;
				}

				for( ; i < nLineLen; ++i ){		//	最後の文字までスキャン
					if( szLine[i] == ')' || szLine[i] == ',' ){	//	,もしくは)を読み飛ばす
						i++;
						break;
					}
				}
				if (szLine[i-1] == ')'){
					break;
				}
			}
			//	Jun. 16, 2002 genta
			if( !m_nReady ){
				//	どこかでエラーがあったらしい
				delete macro;
				break;
			}
			/* キーマクロのバッファにデータ追加 */
			Append( macro );
		}
		else {
			::MYMESSAGEBOX( NULL, MB_OK | MB_ICONSTOP | MB_TOPMOST, MACRO_ERROR_TITLE,
				_T("Line %d: %sは存在しない関数です.\n" ), line, szFuncName );
			//	Jun. 16, 2002 genta
			m_nReady = false;
			break;
		}
	}
	fclose( hFile );

	//	Jun. 16, 2002 genta
	//	マクロ中にエラーがあったら異常終了できるようにする.
	return m_nReady ? TRUE : FALSE;
}

//	From Here Apr. 29, 2002 genta
/*!
	Factory

	@param ext [in] オブジェクト生成の判定に使う拡張子(小文字)

	@date 2004-01-31 genta RegisterExtの廃止のためRegisterCreatorに置き換え
		そのため,過ったオブジェクト生成を行わないために拡張子チェックは必須.
*/
CMacroManagerBase* CKeyMacroMgr::Creator(const char* ext)
{
	if( strcmp( ext, "mac" ) == 0 ){
		return new CKeyMacroMgr;
	}
	return NULL;
}

/*!	CKeyMacroManagerの登録

	@date 2004.01.31 genta RegisterExtの廃止のためRegisterCreatorに置き換え
*/
void CKeyMacroMgr::declare (void)
{
	//	常に実行
	CMacroFactory::Instance()->RegisterCreator( Creator );
}
//	To Here Apr. 29, 2002 genta

/*[EOF]*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -