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

📄 ceditview_diff.cpp

📁 日本的开源编辑器源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//	$Id: CEditView_Diff.cpp,v 1.14 2004/08/06 15:39:55 genta Exp $
/*!	@file
	@brief DIFF差分表示

	@author MIK
	@date	2002/05/25 ExecCmd を参考にDIFF実行結果を取り込む処理作成
	$Revision: 1.14 $
*/
/*
	Copyright (C) 1998-2001, Norio Nakatani
	Copyright (C) 2001, GAE, YAZAKI, hor
	Copyright (C) 2002, hor, MIK
	Copyright (C) 2003, MIK

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

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include "sakura_rc.h"
#include "etc_uty.h"
#include "global.h"
#include "CDlgDiff.h"
#include "CEditDoc.h"
#include "CEditView.h"
#include "CDocLine.h"
#include "CDocLineMgr.h"
#include "CWaitCursor.h"
#include "COsVersionInfo.h"
#include "mymessage.h"
#include "debug.h"

#define	SAKURA_DIFF_TEMP_PREFIX	"sakura_diff_"

/*!	差分表示
	@note	HandleCommandからの呼び出し対応(ダイアログあり版)
	@author	MIK
	@date	2002/05/25
	@date	2002/11/09 編集中ファイルを許可
*/
void CEditView::Command_Diff_Dialog( void )
{
	CDlgDiff	cDlgDiff;
	bool	bTmpFile1, bTmpFile2;
	char	szTmpFile1[_MAX_PATH * 2];
	char	szTmpFile2[_MAX_PATH * 2];
	char	*pszTmpName;

	bTmpFile1 = false;
	bTmpFile2 = false;
	strcpy( szTmpFile1, "" );
	strcpy( szTmpFile2, "" );

	//DIFF差分表示ダイアログを表示する
	if( FALSE == cDlgDiff.DoModal( m_hInstance, m_hWnd, (LPARAM)m_pcEditDoc,
		m_pcEditDoc->GetFilePath(),
		m_pcEditDoc->IsModified() ) )
	{
		return;
	}

	//自ファイル
	if( m_pcEditDoc->IsModified() )
	{
		/*
		MessageBox( NULL,  
			"差分コマンド実行は失敗しました。\nファイルを保存してから行ってください。", 
			"DIFF差分表示",
			MB_OK | MB_ICONEXCLAMATION );
		return;
		*/

		pszTmpName = _tempnam( NULL, SAKURA_DIFF_TEMP_PREFIX );
		if( NULL == pszTmpName )
		{
			::MYMESSAGEBOX( NULL, MB_OK | MB_ICONEXCLAMATION, GSTR_APPNAME,
				"差分コマンド実行は失敗しました。" );
			return;
		}

		strcpy( szTmpFile1, pszTmpName );
		free( pszTmpName );
		bTmpFile1 = true;

		// 編集中ファイルを一時ファイルに保存する
		if( MakeDiffTmpFile( szTmpFile1, NULL ) == FALSE )
		{
			::MYMESSAGEBOX( NULL, MB_OK | MB_ICONEXCLAMATION, GSTR_APPNAME,
				"差分コマンド実行は失敗しました。\n\n一時ファイルを作成できないか、または行が長すぎます。" );
			goto finish;
		}
	}
	else
	{
		bTmpFile1 = false;
		strcpy( szTmpFile1, m_pcEditDoc->GetFilePath() );
		if( strlen( szTmpFile1 ) == 0 ) return;
	}

	//相手ファイル
	if( cDlgDiff.m_bIsModifiedDst )	/* 相手先ファイルは編集中か? */
	{
		/*
		MessageBox( NULL,  
			"差分コマンド実行は失敗しました。\nファイルを保存してから行ってください。", 
			"DIFF差分表示",
			MB_OK | MB_ICONEXCLAMATION );
		return;
		*/

		pszTmpName = _tempnam( NULL, SAKURA_DIFF_TEMP_PREFIX );
		if( NULL == pszTmpName )
		{
			::MYMESSAGEBOX( NULL, MB_OK | MB_ICONEXCLAMATION, GSTR_APPNAME,
				"差分コマンド実行は失敗しました。" );
			goto finish;
		}

		strcpy( szTmpFile2, pszTmpName );
		free( pszTmpName );
		bTmpFile2 = true;

		// 相手先編集中ファイルを一時ファイルに保存する
		if( MakeDiffTmpFile( szTmpFile2, cDlgDiff.m_hWnd_Dst ) == FALSE )
		{
			::MYMESSAGEBOX( NULL, MB_OK | MB_ICONEXCLAMATION, GSTR_APPNAME,
				"差分コマンド実行は失敗しました。\n\n一時ファイルを作成できないか、または行が長すぎます。" );
			goto finish;
		}
	}
	else
	{
		bTmpFile2 = false;
		strcpy( szTmpFile2, cDlgDiff.m_szFile2 );
		if( strlen( szTmpFile2 ) == 0 ) return;
	}

	/* 差分表示 */
	Command_Diff( szTmpFile1, szTmpFile2, cDlgDiff.m_nDiffFlgOpt );

finish:;
	//一時ファイルを削除する
	if( bTmpFile1 ) unlink( szTmpFile1 );
	if( bTmpFile2 ) unlink( szTmpFile2 );

	return;
}

/*!	差分表示
	@param	pszFile1	[in]	旧ファイル名
	@param	pszFile2	[in]	新ファイル名
    @param  nFlgOpt     [in]    0b000000000
                                    ||||||+--- -i ignore-case         大文字小文字同一視
                                    |||||+---- -w ignore-all-space    空白無視
                                    ||||+----- -b ignore-space-change 空白変更無視
                                    |||+------ -B ignore-blank-lines  空行無視
                                    ||+------- -t expand-tabs         TAB-SPACE変換
                                    |+--------    (編集中のファイルが旧ファイル)
                                    +---------    (DIFF差分がないときにメッセージ表示)
	@note	HandleCommandからの呼び出し対応(ダイアログなし版)
	@author	MIK
	@date	2002/05/25
*/
void CEditView::Command_Diff( 
	const char	*pszFile1,
	const char	*pszFile2,
	int			nFlgOpt )
/*
	bool	bFlgCase,		//大文字小文字同一視
	bool	bFlgBlank,		//空白無視
	bool	bFlgWhite,		//空白変更無視
	bool	bFlgBLine,		//空行無視
	bool	bFlgTabSpc,		//TAB-SPACE変換
	bool	bFlgFile12,		//編集中のファイルが旧ファイル
*/
{
	char	cmdline[1024];
	HANDLE	hStdOutWrite, hStdOutRead;
//	CDlgCancel	cDlgCancel;
	CWaitCursor	cWaitCursor( m_hWnd );
	int		nFlgFile12 = 1;

	/* exeのあるフォルダ */
	char	szPath[_MAX_PATH + 1];
	char	szExeFolder[_MAX_PATH + 1];
	::GetModuleFileName(
		::GetModuleHandle( NULL ),
		szPath, sizeof( szPath )
	);
	/* ファイルのフルパスを、フォルダとファイル名に分割 */
	/* [c:\work\test\aaa.txt] → [c:\work\test] + [aaa.txt] */
	::SplitPath_FolderAndFile( szPath, szExeFolder, NULL );

	//	From Here Dec. 28, 2002 MIK
	//	diff.exeの存在チェック
	wsprintf( cmdline, "%s\\%s", szExeFolder, "diff.exe" );
	if( -1 == ::GetFileAttributes( cmdline ) )
	{
		::MYMESSAGEBOX( m_hWnd,	MB_OK | MB_ICONEXCLAMATION, GSTR_APPNAME,
			_T( "差分コマンド実行は失敗しました。\n\nDIFF.EXE が見つかりません。" ) );
		return;
	}

	//今あるDIFF差分を消去する。
	if( m_pcEditDoc->m_cDocLineMgr.IsDiffUse() )
		Command_Diff_Reset();
		//m_pcEditDoc->m_cDocLineMgr.ResetAllDiffMark();

	PROCESS_INFORMATION	pi;
	ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );

	//子プロセスの標準出力と接続するパイプを作成
	SECURITY_ATTRIBUTES	sa;
	ZeroMemory( &sa, sizeof(SECURITY_ATTRIBUTES) );
	sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle       = TRUE;
	sa.lpSecurityDescriptor = NULL;
	hStdOutRead = hStdOutWrite = 0;
	if( CreatePipe( &hStdOutRead, &hStdOutWrite, &sa, 1000 ) == FALSE )
	{
		//エラー。対策無し
		return;
	}

	//継承不能にする
	DuplicateHandle( GetCurrentProcess(), hStdOutRead,
				GetCurrentProcess(), NULL,
				0, FALSE, DUPLICATE_SAME_ACCESS );

	//CreateProcessに渡すSTARTUPINFOを作成
	STARTUPINFO	sui;
	ZeroMemory( &sui, sizeof(STARTUPINFO) );
	sui.cb          = sizeof(STARTUPINFO);
	sui.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	sui.wShowWindow = SW_HIDE;
	sui.hStdInput   = GetStdHandle( STD_INPUT_HANDLE );
	sui.hStdOutput  = hStdOutWrite;
	sui.hStdError   = hStdOutWrite;

	//オプションを作成する
	char	szOption[16];	// "-cwbBt"
	strcpy( szOption, "-" );
	if( nFlgOpt & 0x0001 ) strcat( szOption, "i" );	//-i ignore-case         大文字小文字同一視
	if( nFlgOpt & 0x0002 ) strcat( szOption, "w" );	//-w ignore-all-space    空白無視
	if( nFlgOpt & 0x0004 ) strcat( szOption, "b" );	//-b ignore-space-change 空白変更無視
	if( nFlgOpt & 0x0008 ) strcat( szOption, "B" );	//-B ignore-blank-lines  空行無視
	if( nFlgOpt & 0x0010 ) strcat( szOption, "t" );	//-t expand-tabs         TAB-SPACE変換
	if( strcmp( szOption, "-" ) == 0 ) strcpy( szOption, "" );	//オプションなし
	if( nFlgOpt & 0x0020 ) nFlgFile12 = 0;
	else                   nFlgFile12 = 1;

	//	To Here Dec. 28, 2002 MIK

	//OSバージョン取得
	COsVersionInfo cOsVer;
	//コマンドライン文字列作成(MAX:1024)
	if (cOsVer.IsWin32NT()){
		wsprintf( cmdline, "cmd.exe /C \"\"%s\\%s\" %s \"%s\" \"%s\"\"",
				szExeFolder,	//sakura.exeパス
				"diff.exe",		//diff.exe
				szOption,		//diffオプション
				( nFlgFile12 ? pszFile2 : pszFile1 ),
				( nFlgFile12 ? pszFile1 : pszFile2 )
			);
	}
	else{
		wsprintf( cmdline, "command.com /C \"%s\\%s\" %s \"%s\" \"%s\"",
				szExeFolder,	//sakura.exeパス
				"diff.exe",		//diff.exe
				szOption,		//diffオプション
				( nFlgFile12 ? pszFile2 : pszFile1 ),
				( nFlgFile12 ? pszFile1 : pszFile2 )
			);
	}

	//コマンドライン実行
	if( CreateProcess( NULL, cmdline, NULL, NULL, TRUE,
			CREATE_NEW_CONSOLE, NULL, NULL, &sui, &pi ) == FALSE )
	{
			::MYMESSAGEBOX( NULL, MB_OK | MB_ICONEXCLAMATION, GSTR_APPNAME,
				"差分コマンド実行は失敗しました。\n\n%s", cmdline );
		goto finish;
	}

	{
		DWORD	read_cnt;
		DWORD	new_cnt;
		char	work[1024];
		int		j;
		bool	bLoopFlag = true;
		bool	bLineHead = true;	//行頭か
		bool	bDiffInfo = false;	//DIFF情報か
		int		nDiffLen = 0;		//DIFF情報長
		char	szDiffData[100];	//DIFF情報
		bool	bFirst = true;	//先頭か?	//@@@ 2003.05.31 MIK

		//中断ダイアログ表示
//		cDlgCancel.DoModeless( m_hInstance, m_hwndParent, IDD_EXECRUNNING );

		//実行結果の取り込み
		do {
			//処理中のユーザー操作を可能にする
//			if( !::BlockingHook( cDlgCancel.m_hWnd ) )
//			{
//				bDiffInfo = false;
//				break;
//			}

			//中断ボタン押下チェック
//			if( cDlgCancel.IsCanceled() )
//			{
				//指定されたプロセスと、そのプロセスが持つすべてのスレッドを終了させます。
//				::TerminateProcess( pi.hProcess, 0 );
//				bDiffInfo = false;
//				break;
//			}

			//プロセスが終了していないか確認
			// Jul. 04, 2003 genta CPUを100%使い果たすのを防ぐため 200msec休む
			// Jan. 23, 2004 genta
			// 子プロセスの出力をどんどん受け取らないと子プロセスが
			// 停止してしまうため,待ち時間を200msから20msに減らす
			if( WaitForSingleObject( pi.hProcess, 20 ) == WAIT_OBJECT_0 )
			{
				//終了していればループフラグをFALSEとする
				//ただしループの終了条件は プロセス終了 && パイプが空
				bLoopFlag = FALSE;
			}

			new_cnt = 0;
			if( PeekNamedPipe( hStdOutRead, NULL, 0, NULL, &new_cnt, NULL ) )
			{
				while( new_cnt > 0 )												//待機中のものがある
				{
					if( new_cnt >= sizeof(work) - 2 )							//パイプから読み出す量を調整
					{
						new_cnt = sizeof(work) - 2;
					}
					ReadFile( hStdOutRead, &work[0], new_cnt, &read_cnt, NULL );	//パイプから読み出し
					if( read_cnt == 0 )
					{
						// Jan. 23, 2004 genta while追加のため制御を変更
						break;
					}

					//@@@ 2003.05.31 MIK
					//	先頭がBinary filesならバイナリファイルのため意味のある差分が取られなかった
					if( bFirst )
					{
						bFirst = false;
						if( strncmp( work, "Binary files ", strlen( "Binary files " ) ) == 0 )
						{
							::MYMESSAGEBOX( NULL, MB_OK | MB_ICONEXCLAMATION, GSTR_APPNAME,
								"DIFF差分を行おうとしたファイルはバイナリファイルです。" );
							goto finish;
						}
					}

					//読み出した文字列をチェックする
					for( j = 0; j < (int)read_cnt/*-1*/; j++ )
					{
						if( bLineHead )
						{
							if( work[j] != '\n' && work[j] != '\r' )
							{
								bLineHead = false;
							
								//DIFF情報の始まりか?
								if( work[j] >= '0' && work[j] <= '9' )
								{
									bDiffInfo = true;
									nDiffLen = 0;
									szDiffData[nDiffLen++] = work[j];
								}
								/*
								else if( work[j] == '<' || work[j] == '>' || work[j] == '-' )
								{
									bDiffInfo = false;
									nDiffLen = 0;
								}
								*/
							}
						}
						else
						{
							//行末に達したか?
							if( work[j] == '\n' || work[j] == '\r' )
							{

⌨️ 快捷键说明

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