www.pudn.com > BBS_Program.rar > CTelnetView.cpp


// CTelnetView.cpp : implementation of the CTelnetView class 
// 
 
#include "stdafx.h" 
#include "CTelnet.h" 
 
#include "CTelnetDoc.h" 
#include "CTelnetView.h" 
#include "MainFrm.h" 
#include "ClientSocket.h" 
#include "Process.h" 
 
#include "HostDialog.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
extern CMultiDocTemplate * pDocTemplate; 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CTelnetView 
 
IMPLEMENT_DYNCREATE(CTelnetView, CScrollView) 
 
BEGIN_MESSAGE_MAP(CTelnetView, CScrollView) 
	//{{AFX_MSG_MAP(CTelnetView) 
	ON_WM_CHAR() 
	ON_WM_SIZE() 
	ON_WM_ERASEBKGND() 
	ON_WM_KEYDOWN() 
 
	//}}AFX_MSG_MAP 
	// Standard printing commands 
	ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview) 
	ON_COMMAND(ID_FILE_NEW, OnFileNew) 
 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CTelnetView construction/destruction 
 
CTelnetView::CTelnetView() 
{ 
	cTextColor = RGB(0,200,000); 
	cBackgroundColor = RGB(000,000,000); 
	cSock = NULL; 
	bOptionsSent = FALSE; 
	TempCounter = 0; 
	cCursX = 0; 
	CurrentXX=0; 
	CurrentYY=0; 
 
	IfOutput=false; 
	dtX=8; 
	dtY=20; 
 
//	OffsetNum=0; 
	for(int x = 0; x < 80; x++) 
	{ 
		for(int y = 0; y < bufferLines; y++) 
		{ 
			cText[x][y] = ' '; 
		} 
	} 
} 
 
CTelnetView::~CTelnetView() 
{ 
	if(cSock != NULL) 
		delete cSock; 
	cSock = NULL; 
} 
 
BOOL CTelnetView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
 
	return CScrollView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CTelnetView drawing 
 
void CTelnetView::OnDraw(CDC* pDC) 
{ 
	CTelnetDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
 
//	pDC->SelectObject(GetStockObject(ANSI_FIXED_FONT)); 
	/* 
	for(int x = 0; x < 80; x++) 
	{ 
		for(int y = 0; y < bufferLines; y++) 
		{ 
			cText[x][y] = ' '; 
		} 
		pDC->TextOut(0,Text); 
	} 
	*/ 
//	OnEraseBkgnd(pDC); 
	CRect rect; 
	GetClientRect(&rect); 
	pDC->FillSolidRect(rect, cBackgroundColor); 
//	ClearWindows(pDC); 
	DrawCursor(pDC,FALSE); 
	DoDraw(pDC); 
	DrawCursor(pDC,TRUE); 
} 
 
void CTelnetView::DoDraw(CDC* pDC) 
{ 
	CString strLine; 
	BOOL bSkip = FALSE; 
	CRect clip; 
	pDC->GetClipBox(clip); 
	clip.top -= dtY; 
 
	pDC->SetTextColor(cTextColor); 
	CFont font; 
 
	static BOOL isinit=TRUE; 
	if(isinit==TRUE) 
	{ 
		CFont * t=pDC->GetCurrentFont(); 
		t->GetLogFont(&m_lplf); 
		isinit=FALSE; 
	} 
	font.CreateFontIndirect(&m_lplf); 
	pDC->SelectObject(&font); 
 
 
//	CurrentXX=0; 
	char text[2] = {0x00, 0x00}; 
 
	for(int y = 0; y < bufferLines; y++) 
	{ 
		//if(y * dtY >= clip.top) 
		//{ 
			for(int x = 0; x < 80; x++) 
			{ 
				text[0] = cText[x][y]; 
				if(text[0] == 27) 
					bSkip = TRUE; 
				if(!bSkip) 
					strLine += text[0]; 
				if(text[0] == 'm' && bSkip) 
					bSkip = FALSE; 
			} 
			pDC->TextOut(0, y * dtY, strLine); 
			strLine.Empty(); 
		//} 
	} 
} 
 
void CTelnetView::OnInitialUpdate() 
{ 
	CSize sizeTotal; 
	 
 
	// TODO: calculate the total size of this view 
	sizeTotal.cx = dtX * 80 + 3; 
	sizeTotal.cy = dtY * bufferLines + 3; 
	SetScrollSizes(MM_TEXT, sizeTotal); 
	//SetWindowPos(NULL,0,0,sizeTotal.cx,sizeTotal.cy,SWP_NOMOVE); 
 
//	ScrollToPosition(CPoint(0, bufferLines * 1000)); //go way past the end 
 
 
	CScrollView::OnInitialUpdate(); 
 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CTelnetView printing 
 
BOOL CTelnetView::OnPreparePrinting(CPrintInfo* pInfo) 
{ 
	// default preparation 
	return DoPreparePrinting(pInfo); 
} 
 
void CTelnetView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add extra initialization before printing 
} 
 
void CTelnetView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add cleanup after printing 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CTelnetView diagnostics 
 
#ifdef _DEBUG 
void CTelnetView::AssertValid() const 
{ 
	CScrollView::AssertValid(); 
} 
 
void CTelnetView::Dump(CDumpContext& dc) const 
{ 
	CScrollView::Dump(dc); 
} 
 
CTelnetDoc* CTelnetView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTelnetDoc))); 
	return (CTelnetDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CTelnetView message handlers 
 
 
//接收分析数据 
void CTelnetView::ProcessMessage(CClientSocket * pSock) 
{ 
	if(!IsWindow(m_hWnd)) return; 
	if(!IsWindowVisible()) return; 
	//保存数据到m_bBuf 
	int nBytes = pSock->Receive(m_bBuf ,ioBuffSize ); 
	if(nBytes != SOCKET_ERROR) 
	{ 
		int ndx = 0; 
		//每次读入一行数据 
		while(GetLine(m_bBuf, nBytes, ndx) != TRUE); 
		//进行协商 
		ProcessOptions(); 
		MessageReceived(m_strNormalText); 
	} 
	m_strLine.Empty(); 
	m_strResp.Empty(); 
} 
 
//进行协商 
void CTelnetView::ProcessOptions() 
{ 
	CString m_strTemp; 
	CString m_strOption; 
	unsigned char ch; 
	int ndx; 
	int ldx; 
	BOOL bScanDone = FALSE; 
 
	m_strTemp = m_strLine; 
 
	while(!m_strTemp.IsEmpty() && bScanDone != TRUE) 
	{ 
		ndx = m_strTemp.Find(IAC); 
		if(ndx != -1) 
		{ 
			m_strNormalText += m_strTemp.Left(ndx); 
			ch = m_strTemp.GetAt(ndx + 1); 
			switch(ch) 
			{ 
			case DO: 
			case DONT: 
			case WILL: 
			case WONT: 
				m_strOption		= m_strTemp.Mid(ndx, 3); 
				m_strTemp		= m_strTemp.Mid(ndx + 3); 
				m_strNormalText	= m_strTemp.Left(ndx); 
				m_ListOptions.AddTail(m_strOption); 
				break; 
			case IAC: 
				m_strNormalText	= m_strTemp.Left(ndx); 
				m_strTemp		= m_strTemp.Mid(ndx + 1); 
				break; 
			case SB: 
				m_strNormalText = m_strTemp.Left(ndx); 
				ldx = Find(m_strTemp, SE); 
				m_strOption		= m_strTemp.Mid(ndx, ldx); 
				m_ListOptions.AddTail(m_strOption); 
				m_strTemp		= m_strTemp.Mid(ldx); 
				//AfxMessageBox(m_strOption,MB_OK); 
				break; 
			default: 
				bScanDone = TRUE; 
			} 
		} 
		else 
		{ 
			m_strNormalText = m_strTemp; 
			bScanDone = TRUE; 
		} 
	}  
	 
	RespondToOptions(); 
} 
 
 
void CTelnetView::RespondToOptions() 
{ 
	CString strOption; 
	 
	while(!m_ListOptions.IsEmpty()) 
	{ 
		strOption = m_ListOptions.RemoveHead(); 
 
		ArrangeReply(strOption); 
	} 
 
	DispatchMessage(m_strResp); 
	m_strResp.Empty(); 
} 
 
void CTelnetView::ArrangeReply(CString strOption) 
{ 
 
	unsigned char Verb; 
	unsigned char Option; 
	unsigned char Modifier; 
	unsigned char ch; 
	BOOL bDefined = FALSE; 
 
	if(strOption.GetLength() < 3) return; 
 
	Verb = strOption.GetAt(1); 
	Option = strOption.GetAt(2); 
 
	switch(Option) 
	{ 
	case 1:	//回显 
	case 3: // Suppress Go-Ahead 
		bDefined = TRUE; 
		break; 
	} 
 
	m_strResp += IAC; 
 
	if(bDefined == TRUE) 
	{ 
		switch(Verb) 
		{ 
		case DO: 
			ch = WILL; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		case DONT: 
			ch = WONT; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		case WILL: 
			ch = DO; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		case WONT: 
			ch = DONT; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		case SB: 
			Modifier = strOption.GetAt(3); 
			if(Modifier == SEND) 
			{ 
				ch = SB; 
				m_strResp += ch; 
				m_strResp += Option; 
				m_strResp += IS; 
				m_strResp += IAC; 
				m_strResp += SE; 
			} 
			break; 
		} 
	} 
 
	else 
	{ 
		switch(Verb) 
		{ 
		case DO: 
			ch = WONT; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		case DONT: 
			ch = WONT; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		case WILL: 
			ch = DONT; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		case WONT: 
			ch = DONT; 
			m_strResp += ch; 
			m_strResp += Option; 
			break; 
		} 
	} 
} 
 
//发送数据 
void CTelnetView::DispatchMessage(CString strText) 
{ 
	if(cSock!=NULL) 
		cSock->Send(strText, strText.GetLength()); 
} 
 
//获得一行数据 
BOOL CTelnetView::GetLine( unsigned char * bytes, int nBytes, int& ndx ) 
{ 
	BOOL bLine = FALSE; 
	while ( bLine == FALSE && ndx < nBytes ) 
	{ 
		unsigned char ch = bytes[ndx]; 
		//原来设计的时候要去掉回车换行的,但是后来发现不能去掉 
		switch( ch ) 
		{ 
		case '\r': //  
			m_strLine += "\r"; //回车 
			break; 
		case '\n': // 行结尾 
			m_strLine += "\n"; 
			break; 
		default:   // 其他数据 
			m_strLine += ch; 
			break; 
		}  
 
		ndx ++; 
 
 
		if (ndx == nBytes) 
		{ 
			bLine = TRUE; 
		} 
	} 
	return bLine; 
} 
 
//数据处理 
void CTelnetView::MessageReceived(LPCSTR pText) 
{ 
	BOOL bSkip = FALSE; 
	int loop=0; 
	CString tempStr="0123456789;"; 
	CString tempStr2; 
	int ColorVal; 
	int tempY=0; 
 
	CDC * pDC = GetDC(); 
	OnPrepareDC(pDC); 
	DrawCursor(pDC,FALSE); 
 
	CMainFrame * frm = (CMainFrame*)GetTopLevelFrame(); 
	//设置颜色 
	pDC->SetTextColor(cTextColor); 
	pDC->SetBkColor(cBackgroundColor); 
 
	CFont font; 
	font.CreateFontIndirect(&m_lplf); 
	pDC->SelectObject(&font); 
 
//	pDC->SelectObject(GetStockObject(ANSI_FIXED_FONT)); 
	int length = strlen(pText); 
	char text[2] = {0x00, 0x00}; 
	while(loop < length) 
	{ 
		switch(pText[loop]) 
		{ 
		case 8: //删除 
			CurrentXX--; 
			if(CurrentXX < 0) CurrentXX = 0; 
			loop++; 
			break; 
		case 9: //TAB键 
			CurrentXX++; //TBD make this smarter 
			loop++; 
			break; 
		case 13: //换行CR 
			m_strline.Empty(); 
			CurrentXX = 0; 
			loop++; 
			break; 
		case 27: 
			loop++; 
			//分析紧接着27的字符是否是91,如果不是91,则这两个字符都不作处理了,直接跳出 
			if (pText[loop]!=91)  
			{ 
				loop++; 
				break; 
			} 
			//如果是91,则接下来的数据则是系统相关数据 
			else 
			{ 
				loop++; 
				while (tempStr.Find(pText[loop])!=-1)  
				{ 
					tempStr2+=pText[loop]; 
					loop++; 
				} 
				if (pText[loop]=='m')//如果接下来的数据是m,则分析前面获得的字符串 
				{ 
 
					//循环获得字符串中的值,其中字符串中的值都是以分号隔开的 
					while (tempStr2!="") 
					{ 
						if (tempStr2.Find(";")!=-1) 
						{ 
							ColorVal=atoi(tempStr2.Mid(0,tempStr2.Find(";"))); 
							tempStr2=tempStr2.Mid(tempStr2.Find(";")+1); 
 
						} 
						else 
						{ 
							ColorVal=atoi(tempStr2); 
							tempStr2.Empty(); 
						} 
 
						//获得一个值 
						//改变前景颜色,这个颜色可以按照一定的规则来自定义 
						 
						if (ColorVal>29 && ColorVal<38) 
							//cTextColor=RGB(0,0,255); 
						//设置背景颜色 
						if (ColorVal>39 && ColorVal<48) 
							//cBackgroundColor=RGB(0,255,ColorVal); 
						//恢复基本设置 
						if (ColorVal==0) 
						{ 
							//cBackgroundColor=RGB(0,0,0); 
							//cTextColor=RGB(255,255,255); 
						} 
						//如果为1,则设置前景色 
						//if ColorVal==1 
						//表示要反色 
						//if ColorVal==7 
 
					} 
				} 
				//如果为字符K,表示要画一条以背景色的矩形区域 
				if (pText[loop]=='K') 
				{ 
 
					int x,y; 
					CString myStr; 
					//保持原来的坐标 
 
					//画出矩形区域,因为以背景色画,所以相当于移动光标 
					//将坐标变量改变到目前的位置 
					x=CurrentXX; 
					y=CurrentYY; 
					for (int l=CurrentXX;l<80;l++) 
					{ 
						cText[l][CurrentYY]=' '; 
						myStr+=' '; 
					} 
					pDC->TextOut(x*dtX, y * dtY, myStr); 
 
					CurrentXX=x; 
					CurrentYY=y; 
 
				} 
	            //如果字符为C,表示要改变当前的横坐标 
				if (pText[loop]=='C') 
				{ 
	            //获得横坐标的改变量 
					if (tempStr2.Find(";")!=-1) 
					{ 
						ColorVal=atoi(tempStr2.Mid(0,tempStr2.Find(";"))); 
						tempStr2=tempStr2.Mid(tempStr2.Find(";")+1); 
					} 
					else 
					{ 
						ColorVal=atoi(tempStr2); 
						tempStr2.Empty(); 
					} 
					//然后增建坐标值,注意这里要加上字符宽度 
					CurrentXX=CurrentXX+ColorVal; 
				} 
				//如果字符为H,表示重新设置横坐标和纵坐标 
				if (pText[loop]=='H') 
				{ 
                //获得纵坐标值,在服务器发送的过程中,先发送纵坐标值 
				TRACE0("H"); 
 
				int tX=0,tY=0; 
				//char buffer3[20]; 
					tY=atoi(tempStr2.Mid(0,tempStr2.Find(";"))); 
					tempStr2=tempStr2.Mid(tempStr2.Find(";")+1); 
					//获得横坐标值,注意这里获得值是没有加字符宽度的 
					tX=atoi(tempStr2); 
					if (tX>0 && tY>0) 
					{ 
						CurrentYY=tY-1; 
						CurrentXX=tX-1; 
					} 
				} 
 
				//如果为字符J,表示要清除整个屏幕 
				if (pText[loop]=='J') 
				{ 
					ClearWindows(pDC); 
				} 
			} 
			loop++; 
			IfOutput=false; 
			break; 
		case 0: 
			loop++; 
		case 10: //换行 
			{ 
				 
				CurrentYY=CurrentYY+1; 
				if (CurrentYY>=bufferLines) 
				{ 
					for(int row = 0; row < bufferLines; row++) 
					{ 
						for(int  col = 0; col < 80; col++) 
						{ 
							cText[col][row] = cText[col][row+1]; 
						} 
					} 
					for(int  col = 0; col < 80; col++) 
					{ 
						cText[col][bufferLines-1] = ' '; 
					} 
					CurrentYY=CurrentYY-1; 
					DoDraw(pDC); 
				} 
			} 
			loop++; 
			break; 
 
		default://输出数据 
			{ 
				cText[CurrentXX][CurrentYY] = pText[loop]; 
				m_strline.Empty(); 
				for (int i=0;i<80;i++) 
				{ 
					if (cText[i][CurrentYY]!=27) 
						m_strline += cText[i][CurrentYY]; 
					else 
						break; 
				} 
				pDC->TextOut(0, CurrentYY * dtY, m_strline); 
				CurrentXX++; 
			} 
			tempStr2.Empty(); 
			loop++; 
 
			break; 
		} 
	} 
	DrawCursor(pDC,TRUE); 
	ReleaseDC(pDC); 
} 
 
//按键处理 
void CTelnetView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	//发出回车键 
	if (nChar == VK_RETURN) 
	{ 
//		CClientDC dc(this); 
//		OnEraseBkgnd(&dc); 
//		Invalidate(); 
		DispatchMessage("\r\n"); 
	} 
	else 
	{ 
		DispatchMessage(nChar); 
	} 
} 
 
//画光标 
void CTelnetView::DrawCursor(CDC * pDC, BOOL pDraw) 
{ 
	COLORREF color; 
	CMainFrame * frm = (CMainFrame*)GetTopLevelFrame(); 
	if(pDraw) //draw 
	{ 
		color = cTextColor; 
	} 
	else //erase 
	{ 
		color = cBackgroundColor; 
	} 
	CRect rect(CurrentXX * dtX + 2, CurrentYY * dtY + 1,  
		CurrentXX * dtX + dtX - 2, CurrentYY * dtY + dtY -1); 
	pDC->FillSolidRect(rect, color); 
} 
 
void CTelnetView::OnSize(UINT nType, int cx, int cy)  
{ 
	CScrollView::OnSize(nType, cx, cy); 
	if(IsWindow(m_hWnd)) 
	{ 
		if(IsWindowVisible()) 
		{ 
			//ScrollToPosition(CPoint(0, bufferLines * 1000)); //go way past the end 
		} 
	} 
} 
 
BOOL CTelnetView::OnEraseBkgnd(CDC* pDC)  
{ 
	CRect clip; 
	GetClientRect(&clip); 
	CMainFrame * frm = (CMainFrame*)GetTopLevelFrame(); 
	pDC->FillSolidRect(clip,cBackgroundColor); 
	return TRUE; 
} 
 
//查找字符 
int CTelnetView::Find(CString str, char ch) 
{ 
	char* data = str.GetBuffer(0); 
	int len = str.GetLength(); 
	int i = 0; 
	for(i = 0; i < len; i++) 
	{ 
		if(data[i] == ch) 
			break; 
	} 
	str.ReleaseBuffer(); 
	return i; 
} 
 
//方向键处理 
void CTelnetView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	unsigned char myChar[3]; 
 
	// TODO: Add your message handler code here and/or call default 
	//左方向键 
	if (nChar==37) 
	{ 
		myChar[0]=27; 
		myChar[1]=91; 
		myChar[2]=68; 
 
		DispatchMessage(myChar); 
	} 
	//右方向键 
	else if (nChar==39) 
	{ 
		myChar[0]=27; 
		myChar[1]=91; 
		myChar[2]=67; 
 
		DispatchMessage(myChar); 
	} 
	//上方向键 
	else if (nChar==38) 
	{ 
		myChar[0]=27; 
		myChar[1]=91; 
		myChar[2]=65; 
 
		DispatchMessage(myChar); 
	} 
	//下方向键 
	else if (nChar==40) 
	{ 
		myChar[0]=27; 
		myChar[1]=91; 
		myChar[2]=66; 
 
		DispatchMessage(myChar); 
	} 
	CView::OnKeyDown(nChar, nRepCnt, nFlags); 
	//MessageBox((char*)nChar); 
} 
 
//清除屏幕 
void CTelnetView::ClearWindows(CDC *pDc) 
{ 
	for(int x = 0; x < 80; x++) 
	{ 
		for(int y = 0; y < bufferLines; y++) 
		{ 
			cText[x][y] = ' '; 
		} 
	} 
	DoDraw(pDc); 
	CurrentYY=0; 
	CurrentXX=0; 
} 
 
void CTelnetView::OnFileNew()  
{ 
	BOOL bOK; 
 
	// TODO: Add your command handler code here 
	//弹出设定服务器对话框 
	CHostDialog host; 
	if(host.DoModal()!=IDOK) 
		return; 
	cHostName = host.m_HostName; 
 
	//创建socket 
	if(cSock!=NULL) 
	{ 
		delete cSock; 
	} 
 
	cSock = new CClientSocket(this); 
	if(cSock != NULL) 
	{ 
		bOK = cSock->Create(); 
		if(bOK == TRUE) 
		{ 
			//连接服务器 
			cSock->Connect(cHostName, host.m_port); 
			//设定标题 
			GetDocument()->SetTitle(cHostName); 
			Sleep(90); 
		} 
		else 
		{ 
			AfxMessageBox("不能创建socket!"); 
		} 
	} 
	else 
	{ 
		AfxMessageBox("不能创建socket!"); 
	} 
}