// AutoRichEditCtrl.cpp : implementation file
//

#include "stdafx.h"
//#include "TestRich.h"
#include "AutoRichEditCtrl.h"

#include "Richedit.h"
#include <afxtempl.h>


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAutoRichEditCtrl

//CList<CString , CString&> InMSGPiclist;

CAutoRichEditCtrl::CAutoRichEditCtrl()
{
	TotalAddMSG = "{\\rtf1\\ansi\\ansicpg950\\deff0\\deflang1033\\deflangfe1028{\\fonttbl{\\f0\\froman\\fprq2\\fcharset136 \\'b7\\'73\\'b2\\'d3\\'a9\\'fa\\'c5\\'e9;}}\n\\viewkind4\\uc1\\pard\\lang1028\\f0\\fs18 \n\\par }\n";
}

CAutoRichEditCtrl::~CAutoRichEditCtrl()
{
}


BEGIN_MESSAGE_MAP(CAutoRichEditCtrl, CRichEditCtrl)
	//{{AFX_MSG_MAP(CAutoRichEditCtrl)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAutoRichEditCtrl message handlers

CString CAutoRichEditCtrl::GetRTF()
{
	// Return the RTF string of the text in the control.
	
	// Stream out here.
	EDITSTREAM es;
	es.dwError = 0;
	es.pfnCallback = CBStreamOut;		// Set the callback

	CString sRTF = "";

	es.dwCookie = (DWORD) &sRTF;	// so sRTF receives the string
	
	StreamOut(SF_RTF, es);			// Call CRichEditCtrl::StreamOut to get the string.
	///

	return sRTF;

}

void CAutoRichEditCtrl::SetRTF(CString sRTF)
{
	// Put the RTF string sRTF into the rich edit control.

	// Read the text in
	EDITSTREAM es;
	es.dwError = 0;
	es.pfnCallback = CBStreamIn;
	//es.pfnCallback = EditStreamCallback;
	es.dwCookie = (DWORD) &sRTF;
	StreamIn(SF_RTF, es);	// Do it.
	
}
/*
	Callback function to stream an RTF string into the rich edit control.
*/
DWORD CALLBACK CAutoRichEditCtrl::CBStreamIn(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
	// We insert the rich text here.

/*	
	This function taken from CodeGuru.com
	http://www.codeguru.com/richedit/rtf_string_streamin.shtml
	Zafir Anjum
*/




	CString *pstr = (CString *) dwCookie;

	if (pstr->GetLength() < cb)
	{
		*pcb = pstr->GetLength();
		memcpy(pbBuff, (LPCSTR) *pstr, *pcb);
		pstr->Empty();
	}
	else
	{
		*pcb = cb;
//		*pcb = pstr->GetLength() cd;
		memcpy(pbBuff, (LPCSTR) *pstr, *pcb);
		*pstr = pstr->Right(pstr->GetLength() - cb);
	}
	///

	return 0;
}

/*
	Callback function to stream the RTF string out of the rich edit control.
*/
DWORD CALLBACK CAutoRichEditCtrl::CBStreamOut(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
	// Address of our string var is in psEntry
	CString *psEntry = (CString*) dwCookie;
	

	CString tmpEntry = "";
	tmpEntry = (CString) pbBuff;

	// And write it!!!
	*psEntry += tmpEntry.Left(cb);

	return 0;
}

bool CAutoRichEditCtrl::SelectionIsBold()
{
	CHARFORMAT cf = GetCharFormat();	
	
	if (cf.dwEffects & CFM_BOLD)
		return true;
	else
		return false;
}

bool CAutoRichEditCtrl::SelectionIsItalic()
{
	CHARFORMAT cf = GetCharFormat();	
	
	if (cf.dwEffects & CFM_ITALIC)
		return true;
	else
		return false;
}

bool CAutoRichEditCtrl::SelectionIsUnderlined()
{
	CHARFORMAT cf = GetCharFormat();	
	
	if (cf.dwEffects & CFM_UNDERLINE)
		return true;
	else
		return false;
}

CHARFORMAT CAutoRichEditCtrl::GetCharFormat(DWORD dwMask)
{
	CHARFORMAT cf;
	cf.cbSize = sizeof(CHARFORMAT);

	cf.dwMask = dwMask;

	GetSelectionCharFormat(cf);

	return cf;
}

void CAutoRichEditCtrl::SetCharStyle(int MASK, int STYLE, int nStart, int nEnd)
{
	CHARFORMAT cf;
	cf.cbSize = sizeof(CHARFORMAT);
	//cf.dwMask = MASK;
	
	GetSelectionCharFormat(cf);
	
	if (cf.dwMask & MASK)	// selection is all the same
	{
		cf.dwEffects ^= STYLE; 
	}
	else
	{
		cf.dwEffects |= STYLE;
	}
	
	cf.dwMask = MASK;

	SetSelectionCharFormat(cf);

}

void CAutoRichEditCtrl::SetSelectionBold()
{
	long start=0, end=0;
	GetSel(start, end);		// Get the current selection

	SetCharStyle(CFM_BOLD, CFE_BOLD, start, end);	// Make it bold
}

void CAutoRichEditCtrl::SetSelectionItalic()
{
	long start=0, end=0;
	GetSel(start, end);

	SetCharStyle(CFM_ITALIC, CFE_ITALIC, start, end);
}

void CAutoRichEditCtrl::SetSelectionUnderlined()
{
	long start=0, end=0;
	GetSel(start, end);

	SetCharStyle(CFM_UNDERLINE, CFE_UNDERLINE, start, end);
}

void CAutoRichEditCtrl::SetParagraphCenter()
{
	PARAFORMAT paraFormat;    
	paraFormat.cbSize = sizeof(PARAFORMAT);
	paraFormat.dwMask = PFM_ALIGNMENT;    
	paraFormat.wAlignment = PFA_CENTER;
	
	SetParaFormat(paraFormat);	// Set the paragraph.
}

void CAutoRichEditCtrl::SetParagraphLeft()
{
	PARAFORMAT paraFormat;
	paraFormat.cbSize = sizeof(PARAFORMAT);
	paraFormat.dwMask = PFM_ALIGNMENT;    
	paraFormat.wAlignment = PFA_LEFT;
	
	SetParaFormat(paraFormat);
}

void CAutoRichEditCtrl::SetParagraphRight()
{
	PARAFORMAT paraFormat;
	paraFormat.cbSize = sizeof(PARAFORMAT);
	paraFormat.dwMask = PFM_ALIGNMENT;    
	paraFormat.wAlignment = PFA_RIGHT;
	
	SetParaFormat(paraFormat);
}

bool CAutoRichEditCtrl::ParagraphIsCentered()
{
	PARAFORMAT pf = GetParagraphFormat();

	if (pf.wAlignment == PFA_CENTER)
		return true;
	else
		return false;
}

bool CAutoRichEditCtrl::ParagraphIsLeft()
{
	PARAFORMAT pf = GetParagraphFormat();

	if (pf.wAlignment == PFA_LEFT)
		return true;
	else
		return false;
}

bool CAutoRichEditCtrl::ParagraphIsRight()
{
	PARAFORMAT pf = GetParagraphFormat();

	if (pf.wAlignment == PFA_RIGHT)
		return true;
	else
		return false;
}

PARAFORMAT CAutoRichEditCtrl::GetParagraphFormat()
{
	PARAFORMAT pf;
	pf.cbSize = sizeof(PARAFORMAT);

	pf.dwMask = PFM_ALIGNMENT | PFM_NUMBERING;    	

	GetParaFormat(pf);

	return pf;
}

void CAutoRichEditCtrl::SetParagraphBulleted()
{
	PARAFORMAT paraformat = GetParagraphFormat();

	if ( (paraformat.dwMask & PFM_NUMBERING) && (paraformat.wNumbering == PFN_BULLET) )
	{
		paraformat.wNumbering = 0;
		paraformat.dxOffset = 0;
		paraformat.dxStartIndent = 0;
		paraformat.dwMask = PFM_NUMBERING | PFM_STARTINDENT | PFM_OFFSET;
	}
	else
	{
		paraformat.wNumbering = PFN_BULLET;
		paraformat.dwMask = PFM_NUMBERING;
		if (paraformat.dxOffset == 0)
		{
			paraformat.dxOffset = 4;
			paraformat.dwMask = PFM_NUMBERING | PFM_STARTINDENT | PFM_OFFSET;
		}
	}
	
	SetParaFormat(paraformat);

}

bool CAutoRichEditCtrl::ParagraphIsBulleted()
{
	PARAFORMAT pf = GetParagraphFormat();

	if (pf.wNumbering == PFN_BULLET)
		return true;
	else
		return false;
}

void CAutoRichEditCtrl::SelectColor()
{
	CColorDialog dlg;

	CHARFORMAT cf = GetCharFormat();

	if (cf.dwEffects & CFE_AUTOCOLOR) cf.dwEffects -= CFE_AUTOCOLOR;

	// Get a color from the common color dialog.
	if( dlg.DoModal() == IDOK )
	{	
		cf.crTextColor = dlg.GetColor();
	}

	cf.dwMask = CFM_COLOR;

	SetSelectionCharFormat(cf);
}

void CAutoRichEditCtrl::SetFontName(CString sFontName)
{
	CHARFORMAT cf = GetCharFormat();

	// Set the font name.
	for (int i = 0; i <= sFontName.GetLength()-1; i++)
		cf.szFaceName[i] = sFontName[i];


	cf.dwMask = CFM_FACE;

	SetSelectionCharFormat(cf);
}

void CAutoRichEditCtrl::SetFontSize(int nPointSize)
{
	CHARFORMAT cf = GetCharFormat();

	nPointSize *= 20;	// convert from to twips
	cf.yHeight = nPointSize;
	
	cf.dwMask = CFM_SIZE;

	SetSelectionCharFormat(cf);
}

void CAutoRichEditCtrl::GetSystemFonts(CStringArray &saFontList)
{
	CDC *pDC = GetDC ();

	EnumFonts (pDC->GetSafeHdc(),NULL,(FONTENUMPROC) CBEnumFonts,(LPARAM)&saFontList);//Enumerate

}

BOOL CALLBACK CAutoRichEditCtrl::CBEnumFonts(LPLOGFONT lplf, LPTEXTMETRIC lptm, DWORD dwType, LPARAM lpData)
{
	// This function was written with the help of CCustComboBox, by Girish Bharadwaj.
	// Available from Codeguru.

	if (dwType == TRUETYPE_FONTTYPE) 
	{
		((CStringArray *) lpData)->Add( lplf->lfFaceName );
	}

	return true;
}

CString CAutoRichEditCtrl::GetSelectionFontName()
{
	CHARFORMAT cf = GetCharFormat();

	CString sName = cf.szFaceName;

	return sName;
}

long CAutoRichEditCtrl::GetSelectionFontSize()
{
	CHARFORMAT cf = GetCharFormat();

	long nSize = cf.yHeight/20;

	return nSize;
}

//*********************************************************

CString CAutoRichEditCtrl::GetTEXT()
{
	// Return the RTF string of the text in the control.
	
	// Stream out here.
	EDITSTREAM es;
	es.dwError = 0;
	es.pfnCallback = CBStreamOut;		// Set the callback

	CString sRTF = "";

	es.dwCookie = (DWORD) &sRTF;	// so sRTF receives the string
	
	StreamOut(SF_TEXT, es);			// Call CRichEditCtrl::StreamOut to get the string.
	///

	return sRTF;

}

CString CAutoRichEditCtrl::GetMRTF()
{
	CString temp , tempout;
	UINT position_start = 0;
	UINT position_end = 0;
	temp  = GetRTF();
	CString replsym  = "OBJET200410OBJECT";
	CString startcommand = "<OBJECT>";
	CString endcommand = "</OBJECT>";
	bool first = true;
	do
	{
		if(  ( position_start = temp.Find( "{\\object\\objemb" , position_end ) )== -1 )
			break;
		if( first )
		{
			tempout += temp.Mid( 0 , position_start - position_end );
			first = false;
		}
		else
			tempout += temp.Mid( position_end + 3, position_start - position_end - 3 );
		position_end = temp.Find( "}}}" , position_start ) 	;

		tempout += replsym + startcommand + Pic_list.GetHead() + endcommand;
		Pic_list.RemoveHead( );
	}while(1);

	if( first )
	{
		//tempout += temp.Mid( 0 , position_start - position_end );
		//tempout += temp.Mid( 0 , temp.GetLength() - position_end );
		tempout = temp;
		first = false;
/*CString debug;
debug.Format("%d, %d", position_start, position_end);
AfxMessageBox(debug);
AfxMessageBox(temp);
AfxMessageBox(tempout);*/
	}
	else
		tempout += temp.Mid( position_end + 3, temp.GetLength() - position_end - 3);

	return tempout;
}



void CAutoRichEditCtrl::SetMRTF(CString sMRTF)
{
	CString temp ;
	UINT position_start = 0;
	UINT position_end = 0;
	CString replsym  = "OBJET200410OBJECT";
	CString startcommand = "<OBJECT>";
	CString endcommand = "</OBJECT>";
	bool first = true;

	do
	{
		if(  ( position_start = sMRTF.Find( startcommand , position_end ) )== -1 )
			break;
		position_end = sMRTF.Find( endcommand , position_start ) 	;

		temp = sMRTF.Mid( position_start  +  startcommand.GetLength() ,  position_end - position_start - startcommand.GetLength() );
		
		//In_MSGPic_list.AddTail( temp );
		InMSGPiclist.AddTail( temp );

	}while(1);
	SetRTF( sMRTF );

}

void CAutoRichEditCtrl::AddMRTF( CString PriFormat , CString sMRTF)
{
	long header_end_position = 0;
	long end_position = 0;
	CString end_sym = "\\par }";
	CString real_msg ;

	header_end_position = sMRTF.Find( '\n' ) + 1 ;
	sMRTF.Left( header_end_position );
	end_position = sMRTF.Find( end_sym , sMRTF.GetLength() - end_sym.GetLength() - 5 ) ;

	real_msg = sMRTF.Mid( header_end_position - 1 , end_position - header_end_position );

	real_msg = PriFormat + real_msg;

	end_position = TotalAddMSG.Find( end_sym , TotalAddMSG.GetLength() - end_sym.GetLength() - 2 ) ;

	TotalAddMSG.Insert( end_position  ,  real_msg ) ;

//	SetMRTF(sMRTF);
	SetMRTF(TotalAddMSG);
}

void CAutoRichEditCtrl::ModifyColor(CString &sMRTF)
{
	long header_end_position = 0;
	long colorcmd_end_position = 0;
	header_end_position = sMRTF.Find( '\n' )  ;
	CString colorcmd_header = "{\\colortbl ;\\" , colorcmd , colorcmd_total;
	long position_in = 0 , position_all = 0 , header_end_position_in = 0 , colorcmd_end_position_in = 0;
	position_in = sMRTF.Find( colorcmd_header  );
	if( position_in == -1 )
	{
		position_all = TotalAddMSG.Find(colorcmd_header );
		if( position_all == -1 )
		{
			return;
		}
		else
		{
			header_end_position_in = sMRTF.Find( '\n'  )+1;
			sMRTF.Insert( header_end_position  ,  "\\cf0" ) ;
			return ;
		}
	}
	else
	{
		position_all = TotalAddMSG.Find(colorcmd_header );
		if( position_all == -1 )
		{
			header_end_position_in = sMRTF.Find( '\n'  ) + 1;
			colorcmd_end_position_in = sMRTF.Find( '\n' , header_end_position_in + 5 ) - 1;
			colorcmd = sMRTF.Mid( header_end_position_in  , colorcmd_end_position_in - header_end_position_in);
			sMRTF.Delete(header_end_position_in  , colorcmd_end_position_in - header_end_position_in + 2 );

			TotalAddMSG.Insert(  header_end_position  ,  colorcmd + " \n" ) ;

			return;
		}
		else
		{
			header_end_position_in = sMRTF.Find( '\n'  ) + 1 ;
			colorcmd_end_position_in = sMRTF.Find( '\n' , header_end_position_in + 5 ) - 1;
			colorcmd = sMRTF.Mid( header_end_position_in  , colorcmd_end_position_in - header_end_position_in);

			sMRTF.Delete(header_end_position_in  , colorcmd_end_position_in - header_end_position_in + 2 );


			header_end_position = TotalAddMSG.Find( '\n'  ) + 1 ;
			colorcmd_end_position = TotalAddMSG.Find( '\n' , header_end_position )  - 1;
			colorcmd_total = TotalAddMSG.Mid( header_end_position  , colorcmd_end_position - header_end_position );

			TotalAddMSG.Delete(header_end_position  , colorcmd_end_position - header_end_position + 2 );


			CList< CString , CString&> incolordef;
			CList< CString , CString&> totalcolordef;
			long parsetemp1 = 0 , parsetemp2 = 0 , endsym = 0;
			CString temp;

//strech input msg coloer defination.
			endsym = colorcmd.Find( "}" );
			parsetemp1 = colorcmd.Find( ";" , 0 );
			do{
				parsetemp2 = colorcmd.Find( ";" , parsetemp1 + 1 );
				if( parsetemp2 == endsym - 1 )
					break;				
				temp = colorcmd.Mid( parsetemp1 + 1 ,  parsetemp2 - parsetemp1 - 1);
				incolordef.AddTail( temp );
				parsetemp1 = parsetemp2 ;
			}while(1);
			temp = colorcmd.Mid( parsetemp1 + 1 ,  parsetemp2 - parsetemp1 - 1 );
			incolordef.AddTail( temp );
//strech inner msg coloer defination.
			endsym = colorcmd_total.Find( "}" );
			parsetemp1 = colorcmd_total.Find( ";" , 0 );
			do{
				parsetemp2 = colorcmd_total.Find( ";" , parsetemp1 + 1);
				if( parsetemp2 == endsym - 1 )
					break;				
				temp = colorcmd_total.Mid( parsetemp1 + 1,  parsetemp2 - parsetemp1 - 1);
				totalcolordef.AddTail( temp );
				parsetemp1 = parsetemp2 ;
			}while(1);
			temp = colorcmd_total.Mid( parsetemp1 + 1,  parsetemp2 - parsetemp1 - 1 );
			totalcolordef.AddTail( temp );
// compare two color defination
			CList< CString , CString&> finaltotal;
			bool IsFind = false;
			int input , total ;
			int map[26] = {-1};
			int map_count = 0;
			int map_no[26] = {-1};
			int map_no_count = 0;

			int input_color_number = incolordef.GetCount();
			int total_color_number = totalcolordef.GetCount();
			for( input = 0  ; input < input_color_number ; input++)
			{
				temp = incolordef.GetHead();
				incolordef.RemoveHead();
				for( total = 0  ; total < total_color_number ; total++)
				{
					POSITION a;
					a = totalcolordef.GetHeadPosition();
					if( temp == totalcolordef.GetNext( a ) )
					{
						IsFind = true;
						break;
					}
					else
					{
						continue;
					}
				}
				if( IsFind )
				{
/*					if( input == total )
					{
						IsFind = false;
						continue;
					}
*/					char buffer[20];
					CString ttt = "\\cf";
					map_count++;
					map[map_count-1] = total + 1;
					do{

						_itoa( input + 1 , buffer , 10 );
						ttt = "\\cf";
						ttt += buffer ;
						long ttt_numb = sMRTF.Find( ttt );
						if( ttt_numb == -1 )
							break;
						sMRTF.Delete( ttt_numb , ttt.GetLength() );

						ttt = "\\cf";
						ttt += (char)(map_count + 64 ) ;
						sMRTF.Insert( ttt_numb , ttt );
					}while(1);
				}
				else
				{
	
//******************************************					
					char buffer[20];
					CString ttt = "\\cf";
/*					if( total_color_number + map_no_count  == input )
					{
						IsFind = false;
						finaltotal.AddHead(temp);
						continue;
					}
*/					map_no_count++;
					map_no[map_no_count-1] = total_color_number + map_no_count ;
					do{
						_itoa( input + 1 , buffer , 10 );
						ttt = "\\cf";
						ttt += buffer ;
						long ttt_numb = sMRTF.Find( ttt );
						if( ttt_numb == -1 )
							break;
						sMRTF.Delete( ttt_numb , ttt.GetLength() );

						ttt = "\\cf";
						//_itoa( total_color_number + map_count + 1 , buffer , 10 );
						//ttt += buffer;
						ttt += (char)(map_no_count + 96 ) ;

						sMRTF.Insert( ttt_numb , ttt );
					}while(1);
					finaltotal.AddTail(temp);
//**************************************************
				}
				IsFind = false;
			}
// add totalMSG's color defination
			CString newcolordef = "{\\colortbl ;";
			POSITION a;
			a = totalcolordef.GetHeadPosition();
			for( int i = 0 ; i <  totalcolordef.GetCount() ; i++ )
			{
				newcolordef += totalcolordef.GetNext( a ) + ";" ;				 
			}
			a = finaltotal.GetHeadPosition();
			for( i = 0 ; i < finaltotal.GetCount() ; i++ )
			{
				newcolordef += finaltotal.GetNext( a ) + ";" ;				 
			}
			newcolordef += "} \n";
			TotalAddMSG.Insert(header_end_position  , newcolordef );
// change repeat color defination
			char buffer[20];
			CString ttt = "\\cf";
//			map_count++;
//			map[map_count-1] = total + 1;
			for( int j = 0 ; j < map_count ; j++ )
			{
				do{
					ttt = "\\cf";
					ttt += (char)( j + 65 ) ;
					long ttt_numb = sMRTF.Find( ttt );
					if( ttt_numb == -1 )
						break;
					sMRTF.Delete( ttt_numb , ttt.GetLength() );
					_itoa( map[j] , buffer , 10 );
					ttt = "\\cf";
					ttt += buffer ;
					sMRTF.Insert( ttt_numb , ttt );
				}while(1);
			}
// change not repeat color defination
			ttt = "\\cf";
//			map_count++;
//			map[map_count-1] = total + 1;
			for(  j = 0 ; j < map_no_count ; j++ )
			{
				do{
					ttt = "\\cf";
					ttt += (char)( j + 97 ) ;
					long ttt_numb = sMRTF.Find( ttt );
					if( ttt_numb == -1 )
						break;
					sMRTF.Delete( ttt_numb , ttt.GetLength() );
					_itoa( map_no[j] , buffer , 10 );
					ttt = "\\cf";
					ttt += buffer ;
					sMRTF.Insert( ttt_numb , ttt );
				}while(1);
			}
			return;
		}
	}
}
//***************************************************************

