ccommandline.cpp

来自「日本的开源编辑器源码」· C++ 代码 · 共 455 行

CPP
455
字号
//	$Id: CCommandLine.cpp,v 1.11 2004/05/29 23:54:08 genta Exp $
/*!	@file
	@brief コマンドラインパーサ

	@author aroka
	@date	2002/01/08 作成
	$Revision: 1.11 $
*/
/*
	Copyright (C) 1998-2001, Norio Nakatani
	Copyright (C) 2000-2001, genta
	Copyright (C) 2002, aroka CEditAppより分離

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


#include "CCommandLine.h"
#include "CMemory.h"
#include "etc_uty.h"
#include <tchar.h>
#include <io.h>
#include <string.h>
#include "CRunningTimer.h"

CCommandLine* CCommandLine::_instance = NULL;

/* コマンドラインオプション用定数 */
#define CMDLINEOPT_R			1002
#define CMDLINEOPT_NOWIN		1003
#define CMDLINEOPT_GREPMODE		1100
#define CMDLINEOPT_GREPDLG		1101
#define CMDLINEOPT_DEBUGMODE	1999
#define CMDLINEOPT_X			1
#define CMDLINEOPT_Y			2
#define CMDLINEOPT_VX			3
#define CMDLINEOPT_VY			4
#define CMDLINEOPT_TYPE			5
#define CMDLINEOPT_CODE			6
#define CMDLINEOPT_SX			7
#define CMDLINEOPT_SY			8
#define CMDLINEOPT_WX			9
#define CMDLINEOPT_WY			10
#define CMDLINEOPT_GKEY			101
#define CMDLINEOPT_GFILE		102
#define CMDLINEOPT_GFOLDER		103
#define CMDLINEOPT_GOPT			104
#define CMDLINEOPT_GCODE		105

/*!
	コマンドラインのチェックを行って、オプション番号と
	引数がある場合はその先頭アドレスを返す。
	CCommandLine::ParseCommandLine()で使われる。

	@return オプションの番号。どれにも該当しないときは0を返す。

	@author genta
	@date Apr. 6, 2001
*/
int CCommandLine::CheckCommandLine(
	LPSTR  str, //!< [in] 検証する文字列(先頭の-は含まない)
	char** arg	//!< [out] 引数がある場合はその先頭へのポインタ
)
{
	/*!
		コマンドラインオプション解析用構造体配列
	*/
	struct _CmdLineOpt {
		LPCSTR opt;	//!< オプション文字列
		int len;	//!< オプションの文字列長(計算を省くため)
		int value;	//!< 変換後の値
	};

	/*!
		コマンドラインオプション
		後ろに引数を取らないもの
	*/
	static const _CmdLineOpt _COptWoA[] = {
		{"R", 1,			CMDLINEOPT_R},
		{"NOWIN", 5,		CMDLINEOPT_NOWIN},
		{"GREPMODE", 8,		CMDLINEOPT_GREPMODE},
		{"GREPDLG", 7,		CMDLINEOPT_GREPDLG},
		{"DEBUGMODE", 9,	CMDLINEOPT_DEBUGMODE},
		{NULL, 0, 0}
	};

	/*!
		コマンドラインオプション
		後ろに引数を取るもの
	*/
	static const _CmdLineOpt _COptWithA[] = {
		{"X", 1,			CMDLINEOPT_X},
		{"Y", 1,			CMDLINEOPT_Y},
		{"VX", 2,			CMDLINEOPT_VX},
		{"VY", 2,			CMDLINEOPT_VY},
		{"SX", 2,			CMDLINEOPT_SX},
		{"SY", 2,			CMDLINEOPT_SY},
		{"WX", 2,			CMDLINEOPT_WX},
		{"WY", 2,			CMDLINEOPT_WY},
		{"CODE", 4,			CMDLINEOPT_CODE},	// 2002/09/20 Moca _COptWoAから移動
		{"TYPE", 4,			CMDLINEOPT_TYPE},	//!< タイプ別設定 Mar. 7, 2002 genta
		{"GKEY", 4,			CMDLINEOPT_GKEY},
		{"GFILE", 5,		CMDLINEOPT_GFILE},
		{"GFOLDER", 7,		CMDLINEOPT_GFOLDER},
		{"GOPT", 4,			CMDLINEOPT_GOPT},
		{"GCODE", 5,		CMDLINEOPT_GCODE},	// 2002/09/21 Moca 追加
		{NULL, 0, 0}
	};

	const _CmdLineOpt *ptr;
	int len = lstrlen( str );

	//	引数がある場合を先に確認
	for( ptr = _COptWithA; ptr->opt != NULL; ptr++ ){
		if( len >= ptr->len &&	//	長さが足りているか
			//	オプション部分の長さチェック
			( str[ptr->len] == '=' || str[ptr->len] == ':' ) &&
			//	文字列の比較
			memcmp( str, ptr->opt, ptr->len ) == 0 ){
			*arg = str + ptr->len + 1;
			return ptr->value;
		}
	}

	//	引数がない場合
	for( ptr = _COptWoA; ptr->opt != NULL; ptr++ ){
		if( len == ptr->len &&	//	長さチェック
			//	文字列の比較
			memcmp( str, ptr->opt, ptr->len ) == 0 ){
			return ptr->value;
		}
	}
	return 0;	//	該当無し
}

/*! コマンドラインの解析

	WinMain()から呼び出される。
	
	@note
	これが呼び出された時点では共有メモリの初期化が完了していないため,
	共有メモリにアクセスしてはならない.
*/
void CCommandLine::ParseCommandLine(
	LPCSTR	pszCmdLineSrc,	//!< [in]コマンドライン文字列
	bool*		pbGrepMode,	//!< [out] TRUE: Grep Mode
	bool*		pbGrepDlg,	//!< [out] TRUE: Grep Dialog表示
	CMemory*	pcmGrepKey,	//!< [out] GrepのKey
	CMemory*	pcmGrepFile,
	CMemory*	pcmGrepFolder,
	bool*		pbGrepSubFolder,
	bool*		pbGrepLoHiCase,
	bool*		pbGrepRegularExp,
	int*		pnGrepCharSet,
	bool*		pbGrepOutputLine,
	bool*		pbGrepWordOnly,
	int	*		pnGrepOutputStyle,
	bool*		pbDebugMode,
	bool*		pbNoWindow,	//!< [out] TRUE: 編集Windowを開かない
	FileInfo*	pfi,
	bool*		pbReadOnly	//!< [out] TRUE: Read Only
)
{
	MY_RUNNINGTIMER( cRunningTimer, "CCommandLine::Parse" );

	bool			bGrepMode;
	bool			bGrepDlg;
	CMemory			cmGrepKey;
	CMemory			cmGrepFile;
	CMemory			cmGrepFolder;
	bool			bGrepSubFolder;
	bool			bGrepLoHiCase;
	bool			bGrepRegularExp;
	bool			bGrepOutputLine;
	bool			bGrepWordOnly;
	int				nGrepOutputStyle;
	int				nGrepCharSet;
	bool			bDebugMode;
	bool			bNoWindow;
	FileInfo		fi;
	bool			bReadOnly;
	LPSTR			pszCmdLineWork;
	int				nCmdLineWorkLen;
	bool			bFind;
//	WIN32_FIND_DATA	w32fd;
//	HANDLE			hFind;
	TCHAR			szPath[_MAX_PATH + 1];
	int				i;
	int				j;
	int				nPos;
	LPSTR			pszToken;
	CMemory			cmWork;
	//const LPSTR	pszOpt;
	//int			nOptLen;

	bGrepMode = false;
	bGrepDlg = false;

	bGrepSubFolder = false;
	bGrepLoHiCase = false;
	bGrepRegularExp = false;
	bGrepOutputLine = false;
	bGrepWordOnly = false;
	nGrepOutputStyle = 1;
	nGrepCharSet = CODE_SJIS;
	bDebugMode = false;
	bNoWindow = false;

	//	Oct. 19, 2001 genta 初期値を-1にして,指定有り/無しを判別可能にしてみた
	//	Mar. 7, 2002 genta FileInfoの初期化はコンストラクタで行う.
	bReadOnly = false;					/* 読み取り専用か */

	//	May 30, 2000 genta
	//	実行ファイル名をもとに漢字コードを固定する.
	{
		char	exename[512];
		::GetModuleFileName( NULL, exename, 512 );

		int		len = strlen( exename );

		for( char *p = exename + len - 1; p > exename; p-- ){
			if( *p == '.' ){
				if( '0' <= p[-1] && p[-1] <= '6' )
					fi.m_nCharCode = p[-1] - '0';
				break;
			}
		}
	}



	bFind = false;
	if( pszCmdLineSrc[0] != '-' ){
		memset( (char*)szPath, 0, sizeof( szPath ) );
		i = 0;
		j = 0;
		for( ; i < sizeof( szPath ) - 1 && i <= (int)lstrlen(pszCmdLineSrc); ++i ){
			if( pszCmdLineSrc[i] != ' ' && pszCmdLineSrc[i] != '\0' ){
				szPath[j] = pszCmdLineSrc[i];
				++j;
				continue;
			}
			/* ファイルの存在と、ファイルかどうかをチェック */
			if( -1 != _access( szPath, 0 ) ){
//? 2000.01.18 システム属性のファイルが開けない問題
//?				hFind = ::FindFirstFile( szPath, &w32fd );
//?				::FindClose( hFind );
//?				if( w32fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ||
//?					w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ){
//?				}else{
					bFind = true;
					break;
//?				}
			}
			szPath[j] = pszCmdLineSrc[i];
			++j;
		}
	}
	if( bFind ){
		strcpy( fi.m_szPath, szPath );	/* ファイル名 */
		nPos = j + 1;
	}else{
		nPos = 0;
	}
	pszCmdLineWork = new char[lstrlen( pszCmdLineSrc ) + 1];
	strcpy( pszCmdLineWork, pszCmdLineSrc );
	nCmdLineWorkLen = lstrlen( pszCmdLineWork );
	pszToken = my_strtok( pszCmdLineWork, nCmdLineWorkLen, &nPos, " " );
	while( pszToken != NULL ){
		if( !bFind && pszToken[0] != '-' ){
			if( pszToken[0] == '\"' ){
				cmWork.SetData( &pszToken[1],  lstrlen( pszToken ) - 2 );
				cmWork.Replace( "\"\"", "\"" );
				strcpy( fi.m_szPath, cmWork.GetPtr() );	/* ファイル名 */
			}else{
				strcpy( fi.m_szPath, pszToken );							/* ファイル名 */
			}
		}else{
			++pszToken;	//	先頭の'-'はskip
			char *arg;
			switch( CheckCommandLine( pszToken, &arg ) ){
			case CMDLINEOPT_X: //	X
				/* 行桁指定を1開始にした */
				fi.m_nX = AtoiOptionInt( arg ) - 1;
				break;
			case CMDLINEOPT_Y:	//	Y
				fi.m_nY = AtoiOptionInt( arg ) - 1;
				break;
			case CMDLINEOPT_VX:	// VX
				/* 行桁指定を1開始にした */
				fi.m_nViewLeftCol = AtoiOptionInt( arg ) - 1;
				break;
			case CMDLINEOPT_VY:	//	VY
				/* 行桁指定を1開始にした */
				fi.m_nViewTopLine = AtoiOptionInt( arg ) - 1;
				break;
			case CMDLINEOPT_SX: //	SX
				fi.m_nWindowSizeX = AtoiOptionInt( arg ) - 1;
				break;
			case CMDLINEOPT_SY:	//	SY
				fi.m_nWindowSizeY = AtoiOptionInt( arg ) - 1;
				break;
			case CMDLINEOPT_WX: //	WX
				fi.m_nWindowOriginX = AtoiOptionInt( arg );
				break;
			case CMDLINEOPT_WY:	//	WY
				fi.m_nWindowOriginY = AtoiOptionInt( arg );
				break;
			case CMDLINEOPT_TYPE:	//	TYPE
				//	Mar. 7, 2002 genta
				//	ファイルタイプの強制指定
				strncpy( fi.m_szDocType, arg, MAX_DOCTYPE_LEN );
				fi.m_szDocType[ MAX_DOCTYPE_LEN ]= '\0';
				break;
			case CMDLINEOPT_CODE:	//	CODE
				fi.m_nCharCode = AtoiOptionInt( arg );
				break;
			case CMDLINEOPT_R:	//	R
				bReadOnly = true;
				break;
			case CMDLINEOPT_NOWIN:	//	NOWIN
				bNoWindow = true;
				break;
			case CMDLINEOPT_GREPMODE:	//	GREPMODE
				bGrepMode = true;
				break;
			case CMDLINEOPT_GREPDLG:	//	GREPDLG
				bGrepDlg = true;
				break;
			case CMDLINEOPT_GKEY:	//	GKEY
				//	前後の""を取り除く
				cmGrepKey.SetData( arg + 1,  lstrlen( arg ) - 2 );
				cmGrepKey.Replace( "\"\"", "\"" );
				break;
			case CMDLINEOPT_GFILE:	//	GFILE
				//	前後の""を取り除く
				cmGrepFile.SetData( arg + 1,  lstrlen( arg ) - 2 );
				cmGrepFile.Replace( "\"\"", "\"" );
				break;
			case CMDLINEOPT_GFOLDER:	//	GFOLDER
				cmGrepFolder.SetData( arg + 1,  lstrlen( arg ) - 2 );
				cmGrepFolder.Replace( "\"\"", "\"" );
				break;
			case CMDLINEOPT_GOPT:	//	GOPT
				for( ; *arg != '\0' ; ++arg ){
					switch( *arg ){
					case 'S':	/* サブフォルダからも検索する */
						bGrepSubFolder = true;	break;
					case 'L':	/* 英大文字と英小文字を区別する */
						bGrepLoHiCase = true;	break;
					case 'R':	/* 正規表現 */
						bGrepRegularExp = true;	break;
					case 'K':	/* 文字コード自動判別 */
						// 2002/09/21 Moca 互換性保持のための処理
						nGrepCharSet = CODE_AUTODETECT;	break;
					case 'P':	/* 行を出力するか該当部分だけ出力するか */
						bGrepOutputLine = true;	break;
					case 'W':	/* 単語単位で探す */
						bGrepWordOnly = true;	break;
					case '1':	/* Grep: 出力形式 */
						nGrepOutputStyle = 1;	break;
					case '2':	/* Grep: 出力形式 */
						nGrepOutputStyle = 2;	break;
					}
				}
				break;
			// 2002/09/21 Moca Grepでの文字コードセット 追加
			case CMDLINEOPT_GCODE:
				nGrepCharSet = AtoiOptionInt( arg );	break;
			case CMDLINEOPT_DEBUGMODE:
				bDebugMode = true;
				break;
			}
		}
		pszToken = my_strtok( pszCmdLineWork, nCmdLineWorkLen, &nPos, " " );
	}
	delete [] pszCmdLineWork;

	/* ファイル名 */
	if( '\0' != fi.m_szPath[0] ){
		/* ショートカット(.lnk)の解決 */
		if( TRUE == ResolveShortcutLink( NULL, fi.m_szPath, szPath ) ){
			strcpy( fi.m_szPath, szPath );
		}
		/* ロングファイル名を取得する */
		if( TRUE == ::GetLongFileName( fi.m_szPath, szPath ) ){
			strcpy( fi.m_szPath, szPath );
		}

		/* MRUから情報取得 */

	}

	/* 処理結果を格納 */
	*pbGrepMode					= bGrepMode;
	*pbGrepDlg					= bGrepDlg;
	*pcmGrepKey					= cmGrepKey;
	*pcmGrepFile				= cmGrepFile;
	*pcmGrepFolder				= cmGrepFolder;
	*pbGrepSubFolder			= bGrepSubFolder;
	*pbGrepLoHiCase				= bGrepLoHiCase;
	*pbGrepRegularExp			= bGrepRegularExp;
	*pnGrepCharSet				= nGrepCharSet;
	*pbGrepOutputLine			= bGrepOutputLine;
	*pbGrepWordOnly				= bGrepWordOnly;
	*pnGrepOutputStyle			= nGrepOutputStyle;

	*pbDebugMode				= bDebugMode;
	*pbNoWindow					= bNoWindow;
	*pfi						= fi;
	*pbReadOnly					= bReadOnly;
	return;
}

/*! 
	シングルトン:プロセスで唯一のインスタンス
*/
CCommandLine* CCommandLine::Instance(LPSTR cmd)
{
		if( !_instance ){
			_instance = new CCommandLine(cmd);
		}
		return _instance;
}

/*! 
	コンストラクタ
*/
CCommandLine::CCommandLine(LPSTR cmd) : 
	m_pszCmdLineSrc(cmd)
{
	ParseCommandLine(
		m_pszCmdLineSrc,
		&m_bGrepMode,
		&m_bGrepDlg,
		&m_gi.cmGrepKey,
		&m_gi.cmGrepFile,
		&m_gi.cmGrepFolder,
		&m_gi.bGrepSubFolder,
		&m_gi.bGrepNoIgnoreCase,
		&m_gi.bGrepRegularExp,
		&m_gi.nGrepCharSet,		//  2002/09/20 Moca
		&m_gi.bGrepOutputLine,
		&m_gi.bGrepWordOnly,	//	Jun. 25, 2001 genta
		&m_gi.nGrepOutputStyle,
		&m_bDebugMode,
		&m_bNoWindow,
		&m_fi,
		&m_bReadOnly
	);
}
/*[EOF]*/

⌨️ 快捷键说明

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