////////////////////////////////////////////////
//特殊リッチエディットクラスCREDITEX定義ファイル
////////////////////////////////////////////////
#define	RGB_DEFAULT	RGB(0, 0, 0)

class CREDITEX : public CREDIT {
public:		//メンバー変数
	long m_sp;						//カラーリング検索範囲の先頭文字位置
	long m_ep;						//カラーリング検索範囲の末尾文字位置
	CHARRANGE m_cRange;				//カラーリング範囲用（LONG cpMin, cpMax）
	COLORREF m_BackGround;
	COLORREF m_Directive;
	COLORREF m_Constant;
	COLORREF m_Reserve;
	COLORREF m_Comment;
	COLORREF m_String;
	COLORREF m_BCCSkelton;
	char* strConst[6];				//定数のトークン
	char* strReserve[88];			//予約語のトークン
	char* strBCCClass[31];			//BCCSkeltonクラスのトークン
public:		//メンバー関数
	CREDITEX();						//コンストラクター
	void Init();					//トークンの設定
	void ColorNum(long, long);		//10進法と16進法定数の色付け
	bool ColorWords(bool);			//メンバー諸変数の設定
	void UndoClear();				//Rich Edit ControlのUNDOバッファ空にする
};

//コンストラクター
CREDITEX::CREDITEX() {

	Init();
}

//トークンの設定
void  CREDITEX::Init() {

	strConst[0] = "NULL";
	strConst[1] = "TRUE";
	strConst[2] = "FALSE";
	strConst[3] = "null";
	strConst[4] = "true";
	strConst[5] = "false";

	strReserve[0] = "__asm";
	strReserve[1] = "__cdecl";
	strReserve[2] = "__classid";
	strReserve[3] = "__declspec";
	strReserve[4] = "__dispid";
	strReserve[5] = "__except";
	strReserve[6] = "__export";
	strReserve[7] = "__fastcall";
	strReserve[8] = "__finally";
	strReserve[9] = "__import";
	strReserve[10] = "__int16";
	strReserve[11] = "__int32";
	strReserve[12] = "__int64";
	strReserve[13] = "__int8";
	strReserve[14] = "__pascal";
	strReserve[15] = "__rtti";
	strReserve[16] = "__stdcall";
	strReserve[17] = "__try";
	strReserve[18] = "_asm";
	strReserve[19] = "_cdecl";
	strReserve[20] = "_export";
	strReserve[21] = "_fastcall";
	strReserve[22] = "_import";
	strReserve[23] = "_pascal";
	strReserve[24] = "_stdcall";
	strReserve[25] = "asm";
	strReserve[26] = "auto";
	strReserve[27] = "bool";
	strReserve[28] = "break";
	strReserve[29] = "case";
	strReserve[30] = "catch";
	strReserve[31] = "cdecl";
	strReserve[32] = "char";
	strReserve[33] = "class";
	strReserve[34] = "const";
	strReserve[35] = "const_cast";
	strReserve[36] = "continue";
	strReserve[37] = "default";
	strReserve[38] = "delete";
	strReserve[39] = "do";
	strReserve[40] = "double";
	strReserve[41] = "dynamic_cast";
	strReserve[42] = "else";
	strReserve[43] = "enum";
	strReserve[44] = "explicit";
	strReserve[45] = "extern";
	strReserve[46] = "float";
	strReserve[47] = "for";
	strReserve[48] = "friend";
	strReserve[49] = "goto";
	strReserve[50] = "if";
	strReserve[51] = "inline";
	strReserve[52] = "int";
	strReserve[53] = "long";
	strReserve[54] = "mu";
	strReserve[55] = "table";
	strReserve[56] = "namespace";
	strReserve[57] = "new";
	strReserve[58] = "operator";
	strReserve[59] = "pascal";
	strReserve[60] = "private";
	strReserve[61] = "protected";
	strReserve[62] = "public";
	strReserve[63] = "register";
	strReserve[64] = "reinterpret_cast";
	strReserve[65] = "return";
	strReserve[66] = "short";
	strReserve[67] = "signed";
	strReserve[68] = "sizeof";
	strReserve[69] = "static";
	strReserve[70] = "static_cast";
	strReserve[71] = "struct";
	strReserve[72] = "switch";
	strReserve[73] = "template";
	strReserve[74] = "this";
	strReserve[75] = "throw";
	strReserve[76] = "try";
	strReserve[77] = "typedef";
	strReserve[78] = "typeid";
	strReserve[79] = "typename";
	strReserve[80] = "union";
	strReserve[81] = "unsigned";
	strReserve[82] = "using";
	strReserve[83] = "virtual";
	strReserve[84] = "void";
	strReserve[85] = "volatile";
	strReserve[86] = "wchar_t";
	strReserve[87] = "while";

	strBCCClass[0] = "CANVAS";
	strBCCClass[1] = "CARG";
	strBCCClass[2] = "CBMP";
	strBCCClass[3] = "CCLIPBOARD";
	strBCCClass[4] = "CCMDEDIT";
	strBCCClass[5] = "CCTRL";
	strBCCClass[6] = "CDLG";
	strBCCClass[7] = "CFILE";
	strBCCClass[8] = "CFONT";
	strBCCClass[9] = "CHISTORY";
	strBCCClass[10] = "CHSPLIT";
	strBCCClass[11] = "CIMGLIST";
	strBCCClass[12] = "CINI";
	strBCCClass[13] = "CLISTBOX";
	strBCCClass[14] = "CLISTVIEW";
	strBCCClass[15] = "CMDI";
	strBCCClass[16] = "CMNDLG";
	strBCCClass[17] = "CPICBOX";
	strBCCClass[18] = "CRBAR";
	strBCCClass[19] = "CREDIT";
	strBCCClass[20] = "CSBAR";
	strBCCClass[21] = "CSDI";
	strBCCClass[22] = "CSTR";
	strBCCClass[23] = "CTAB";
	strBCCClass[24] = "CTBAR";
	strBCCClass[25] = "CTHREAD";
	strBCCClass[26] = "CTIMER";
	strBCCClass[27] = "CTREEVIEW";
	strBCCClass[28] = "CVOICE";
	strBCCClass[29] = "CVSPLIT";
	strBCCClass[30] = "CWND";
}

//10進法と16進法定数の色付け
void CREDITEX::ColorNum(long min, long max) {

	/* 10進法 */
	//検索文字の設定
	char* num[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
	//文字検索と色付け
	for(int i = 0; i < 10; i++)
		SetTokenColor(num[i], m_Constant, min, max, FR_DOWN);
	/* 16進法 */
	//FINDTEXT構造体
	FINDTEXT ft;
	//文字列取得用バッファ
	char buff[MAX_PATH];
	//検索範囲の設定
	ft.chrg.cpMin = min;
	ft.chrg.cpMax = max;
	//検索文字列へのポインターを設定
	ft.lpstrText = "0X";
	while(WasFound(ft, FR_DOWN)) {
		m_cRange.cpMin = ft.chrg.cpMin;			//始点を記録
		ft.chrg.cpMin +=  2;					//「0X」の次迄進める
		ft.lpstrText = "\n";					//改行文字検索
		if(WasFound(ft, FR_DOWN))
			m_cRange.cpMax = ft.chrg.cpMin;
		else
			m_cRange.cpMax = max;
		SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&m_cRange);
		SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)buff);
		for(int i = 2; buff[i]; i++) {	//「0X」の次からNULL終端まで
			if(!isxdigit(buff[i])) {
				m_cRange.cpMax = m_cRange.cpMin + i;
					break;
			}
		}
		SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&m_cRange);
		SetCol(m_Constant);
		ft.chrg.cpMin = m_cRange.cpMax;
		//検索文字列へのポインターを再設定
		ft.lpstrText = "0X";
	}
}

//メンバー諸変数の設定
bool CREDITEX::ColorWords(bool flag = FALSE) {

	/* ---------*/
	/* 変数宣言 */
	/*----------*/
	//FINDTEXT構造体
	FINDTEXT ft;
	//現在位置の記録用
	CHARRANGE PresentPos;
	/* ---------*/
	/* 初期設定 */
	/*----------*/
	//リッチエディットコントロールの停止
	EnableWindow(m_hWnd, FALSE);
	//リッチエディットコントロールの描画を停止
	SendMessage(m_hWnd, WM_SETREDRAW, FALSE, 0);
	//現在位置の記録
	SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&PresentPos);
	if(flag) {	//全文処理
		m_sp = 0;
		m_ep = -1;
	}
	else {		//最大化ウィンドウでの最大行数(45)
		long ln = SendMessage(m_hWnd, EM_GETFIRSTVISIBLELINE, 0, 0);
		m_sp = SendMessage(m_hWnd, EM_LINEINDEX, ln, 0);
		m_ep = SendMessage(m_hWnd, EM_LINEINDEX, ln + 30, 0);
	}
/*
	else {		//一行処理
		//キャレットのある行の先頭文字位置
		m_sp = SendMessage(m_hWnd, EM_LINEINDEX, -1, 0);
		//行末文字位置
		m_ep = m_sp + SendMessage(m_hWnd, EM_LINELENGTH, m_sp, 0);
	}
*/
	//色のリセット
//	SendMessage(m_hWnd, EM_SETSEL, m_sp, (LPARAM)m_ep);
//	SetCol(RGB_DEFAULT);
	/* -----------------*/
	/* トークンの色付け */
	/*----------------- */
	/* 予約語 */
	for(int i = 0; i < 88; i++)
		SetTokenColor(strReserve[i], m_Reserve, m_sp, m_ep);
	/* BCCSkeltonのクラス */
	for(int i = 0; i < 31; i++)
		SetTokenColor(strBCCClass[i], m_BCCSkelton, m_sp, m_ep);
	/* 定数 */
	for(int i = 0; i < 6; i++)
		SetTokenColor(strConst[i], m_Constant, m_sp, m_ep);
	/* -------------- */
	/* 10進数と16進数 */
	/* -------------- */
	ColorNum(m_sp, m_ep);
	/* ---------------------------*/
	/* 複数行コメント（全体処理） */
	/*----------------------------*/
	//検索範囲の設定（flag - TRUE = 文頭、FALSE = 表示画面の最初の行頭から常に最後まで）
	ft.chrg.cpMin = m_sp;
	ft.chrg.cpMax = -1;
	//検索文字列へのポインターを設定
	ft.lpstrText = "/*";
	while(WasFound(ft, FR_DOWN | FR_MATCHCASE)) {
/*
		//既に処理済の場合は飛ばす
		if(GetCol(ft.chrg.cpMin, ft.chrg.cpMin + 2) != RGB_DEFAULT) {
			ft.chrg.cpMin++;
			continue;
		}
*/
		m_cRange.cpMin = ft.chrg.cpMin;			//始点を記録
		ft.chrg.cpMin += 2;						//strlen("/*")
		ft.lpstrText = "*/";					//コメントの最後まで検索
		if(WasFound(ft, FR_DOWN | FR_MATCHCASE))
			m_cRange.cpMax = ft.chrg.cpMin + 2;	//2はstrlen("*/")
		else
			m_cRange.cpMax = -1;
		SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&m_cRange);
		SetCol(m_Comment);
		ft.chrg.cpMin = m_cRange.cpMax;
		//検索文字列へのポインターを再設定
		ft.lpstrText = "/*";
	}
	/* ---------*/
	/* 一行処理 */
	/*----------*/
	//一行コメント（「//」）の検索範囲の設定
	ft.chrg.cpMin = m_sp;
	ft.chrg.cpMax = m_ep;
	//検索文字列へのポインターを設定
	ft.lpstrText = "//";
	while(WasFound(ft, FR_DOWN | FR_MATCHCASE)) {
		m_cRange.cpMin = ft.chrg.cpMin;			//始点を記録
		ft.chrg.cpMin = ft.chrg.cpMin + 2;		//「//」の次迄進める
		ft.lpstrText = "\n";					//改行文字検索
		if(WasFound(ft, FR_DOWN | FR_MATCHCASE))
			m_cRange.cpMax = ft.chrg.cpMin;
		else
			m_cRange.cpMax = m_ep;
		SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&m_cRange);
		SetCol(m_Comment);
		ft.chrg.cpMin = m_cRange.cpMax;
		//検索文字列へのポインターを再設定
		ft.lpstrText = "//";
	}
	/* -----*/
	/* 定数 */
	/*------*/
	//「'〜'」で囲まれた定数の検索範囲の設定
	ft.chrg.cpMin = m_sp;
	ft.chrg.cpMax = m_ep;
	//検索文字列へのポインターを設定
	ft.lpstrText = "\'";
	bool finish = FALSE;	//1回目（FALSE）、2回目（TRUE）を識別するフラグ
	while(WasFound(ft, FR_DOWN | FR_MATCHCASE)) {
		//最初の「'」が既に処理済の場合は飛ばす
		if(!finish && GetCol(ft.chrg.cpMin, ft.chrg.cpMin + 1) != RGB_DEFAULT) {
			ft.chrg.cpMin++;
			continue;
		}
		//cpが指す「'」の直前の2文字を取得する（（「??'」）
		SendMessage(m_hWnd, EM_SETSEL, ft.chrg.cpMin - 2, (LPARAM)ft.chrg.cpMin);
		SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)m_FindWhat);
		switch(m_FindWhat[1]) {			//直前の文字を調べる
		case '\\':						//「\'」（「'」はデータ）の状態
			if(m_FindWhat[0] != '\\') {	//「\\'」（「\」がデータ）でなければ
				ft.chrg.cpMin++;		//スキップして検索を継続
				continue;
			}							//有効な「\\'」であればdefault処理へ進む
		default:
			if(finish) {
				m_cRange.cpMax = ft.chrg.cpMin;	//次の「'」の位置を記録
				m_cRange.cpMax++;				//「'」迄含める為
				SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&m_cRange);
				SetCol(m_Constant);
				finish = FALSE;
			}
			else {
				m_cRange.cpMin = ft.chrg.cpMin;	//最初の「'」の位置を記録
				finish = TRUE;
			}
			ft.chrg.cpMin++;					//ft.chrg.cpMinを一つ進める
			break;
		}
	}
	/* -------*/
	/* 文字列 */
	/*--------*/
	//検索範囲の設定
	ft.chrg.cpMin = m_sp;
	ft.chrg.cpMax = m_ep;
	//検索文字列へのポインターを設定
	ft.lpstrText = "\"";
	finish = FALSE;	//1回目（FALSE）、2回目（TRUE）を識別するフラグ
	while(WasFound(ft, FR_DOWN | FR_MATCHCASE)) {
		//最初の「"」が既に処理済の場合は飛ばす
		if(!finish && GetCol(ft.chrg.cpMin, ft.chrg.cpMin + 1) == m_String) {
			ft.chrg.cpMin++;
			continue;
		}
		//cpが指す"\""の直前の2文字を取得する（「??"」）
		SendMessage(m_hWnd, EM_SETSEL, ft.chrg.cpMin - 2, (LPARAM)ft.chrg.cpMin);
		SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)m_FindWhat);
		switch(m_FindWhat[1]) {			//直前の文字を調べる
		case '\\':						//「\"」（データ）の状態であって
			if(m_FindWhat[0] != '\\') {	//「\\"」の状態でなければ
				ft.chrg.cpMin++;		//スキップして検索を継続
				continue;
			}							//有効な「\\"」であればdefault処理へ進む
		default:
			if(finish) {
				m_cRange.cpMax = ft.chrg.cpMin;	//次の「"」の位置を記録
				m_cRange.cpMax++;				//「"」迄含める為
				SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&m_cRange);
				SetCol(m_String);
				finish = FALSE;
			}
			else {
				m_cRange.cpMin = ft.chrg.cpMin;	//最初の「"」の位置を記録
				finish = TRUE;
			}
			ft.chrg.cpMin++;					//ft.chrg.cpMinを一つ進める
			break;
		}
	}
	/* ---------------------------*/
	/* コンパイラーディレクティブ */
	/*----------------------------*/
	//検索範囲の設定
	ft.chrg.cpMin = m_sp;
	ft.chrg.cpMax = m_ep;
	//検索文字列へのポインターを設定
	ft.lpstrText = "#";
	while(WasFound(ft, FR_DOWN | FR_MATCHCASE)) {
		m_cRange.cpMin =  ft.chrg.cpMin;
		m_cRange.cpMax = m_cRange.cpMin + SendMessage(m_hWnd, EM_LINELENGTH, ft.chrg.cpMin, 0);
		SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&m_cRange);
		SetCol(m_Directive);
		ft.chrg.cpMin = m_cRange.cpMax;
	}
	/* ---------*/
	/* 終了処理 */
	/*----------*/
	//現在位置へ復帰し、色も初期色を選択
	PresentPos.cpMax =PresentPos.cpMin;
	SendMessage(m_hWnd, EM_EXSETSEL, 0, (LPARAM)&PresentPos);
	SetCol(RGB_DEFAULT);
	//リッチエディットコントロールの描画を再開
	SendMessage(m_hWnd, WM_SETREDRAW, TRUE, 0);
	//リッチエディットコントロールの再開
	EnableWindow(m_hWnd, TRUE);
	InvalidateRect(m_hWnd, 0, 0);
	//色付けによる変更状態の取り消し
	SendMsg(EM_SETMODIFY, FALSE, 0);
	return TRUE;
}

//Rich Edit ControlのUNDOバッファ空にする
void CREDITEX::UndoClear() {

	SendMessage(m_hWnd, EM_EMPTYUNDOBUFFER, 0, 0);
}
