// HTMLControl
// Provides a scrollable Window to CHTMLViewer and an implementation of
// CHTMLProgress
//
// ?2004 Karl Runmo ,runmo@hotmail.com
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.

#include "htmlcontrol.h"
//#include "..\..\common\HTTP.H"

struct _SCROLLWINDOW{
	int nXMax;
	int nYMax;
	int nXPos;
	int nYPos;
	int nXSize;
	int nYSize;
	int nXLine;
	int nYLine;
	SIZE s;
	BOOL bChanging;
	HWND hWnd;
	BOOL bCapture;
};

#define SM_SETSIZE		WM_USER+1	// wParam=x, lParam=y
#define SM_SETXPOS		WM_USER+2	// lParam=xPos
#define SM_SETYPOS		WM_USER+3	// lParam=yPos
#define SM_GETXPOS		WM_USER+4	// returns xPos
#define SM_GETYPOS		WM_USER+5	// returns yPos
#define SM_GETXSIZE		WM_USER+6	// returns xPos
#define SM_GETYSIZE		WM_USER+7	// returns yPos
#define SM_LINSESIZE	WM_USER+8	// wParam=x, lParam=y
#define SN_SCROLLED		WM_USER+9	// Sent when windo is scrolled, wParam=x, lParam=y

int SetScrollSize(HWND hWnd, int nBar, int nSize)
{
	SCROLLINFO si = {sizeof(si),SIF_PAGE };
	if(nSize>=100)
		nSize=99;
	else if(nSize<1)
		nSize=1;
	si.nPage=nSize;
	SetScrollInfo(hWnd,nBar,&si,FALSE);
	return 100-nSize;
}

_SCROLLWINDOW **g_ppScrolls=0;
int g_nScrolls=0;

int WINAPI ScrollProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	_SCROLLWINDOW *sw;
	SIZE ss, si;
	RECT r;
	int i=-1, offs, x, y;
	static POINT pStart;

	if(!hWnd && !uMsg && !wParam && !lParam){
		for(i=0;i<g_nScrolls;i++)
			delete g_ppScrolls[i];
		free(g_ppScrolls);
		return 0;
	}

	while(uMsg!=WM_CREATE && uMsg!=WM_DESTROY && uMsg!=WM_NCDESTROY){
		for(i=0;i<g_nScrolls;i++)
			if(g_ppScrolls[i]->hWnd==hWnd){
				sw = g_ppScrolls[i];
				break;
			}
		if(i==g_nScrolls && uMsg!=WM_DESTROY && uMsg!=WM_NCDESTROY)
			ScrollProc(hWnd,WM_CREATE,0,0);
		else
			break;
	}
	if((i==-1 || i==g_nScrolls) && uMsg!=WM_CREATE)
		return 0;
	switch(uMsg){
	case WM_CREATE:
		i = g_nScrolls++;
		g_ppScrolls = (_SCROLLWINDOW **)realloc(g_ppScrolls,sizeof(_SCROLLWINDOW*)*g_nScrolls);
		g_ppScrolls[i] = new _SCROLLWINDOW;
		memset(g_ppScrolls[i],0,sizeof(_SCROLLWINDOW));
		g_ppScrolls[i]->hWnd = hWnd;
//		SetWindowLong(hWnd,0,(LPARAM)sw);
		g_ppScrolls[i]->nXLine=g_ppScrolls[i]->nYLine=10;
		break;
	case WM_SIZE:
		if(sw->bChanging)
			break;
		sw->bChanging=TRUE;
		si.cx = sw->nXMax;
		si.cy = sw->nYMax;
		ss.cx = LOWORD(lParam);
		ss.cy = HIWORD(lParam);
		ss.cx = LOWORD(lParam) + (sw->nYMax?GetSystemMetrics(SM_CXHTHUMB):0);
		ss.cy = HIWORD(lParam) + (sw->nXMax?GetSystemMetrics(SM_CYVTHUMB):0);
		x=y=1;
		for(i=0;i<2;i++){
			if(sw->s.cx > ss.cx){
				sw->nXMax = sw->s.cx - ss.cx;
				if(x){
					ss.cy -= GetSystemMetrics(SM_CXHTHUMB);
					x=0;
				}
			}
			else{
				sw->nXMax = 0;
			}
			if(sw->s.cy > ss.cy){
				sw->nYMax = sw->s.cy - ss.cy;
				if(y){
					ss.cx -= GetSystemMetrics(SM_CYVTHUMB);
					y=0;
				}
			}
			else{
				sw->nYMax = 0;
			}
		}
		if(sw->nXPos > sw->nXMax){
			SendMessage(hWnd,WM_HSCROLL,SB_LINEDOWN,0);
			sw->nXPos = sw->nXMax;
		}
		if(sw->nYPos > sw->nYMax){
			SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
			sw->nYPos = sw->nYMax;
		}
		if((si.cx && !sw->nXMax) || (!si.cx && sw->nXMax)){
			SetScrollPos(hWnd,SB_HORZ,0,TRUE);
			ShowScrollBar(hWnd,SB_HORZ,sw->nXMax);
		}
		if((si.cy && !sw->nYMax) || (!si.cy && sw->nYMax)){
			SetScrollPos(hWnd,SB_VERT,0,TRUE);
			ShowScrollBar(hWnd,SB_VERT,sw->nYMax);
		}
		if(sw->s.cx && sw->nXMax){
			sw->nXSize = SetScrollSize(hWnd,SB_HORZ,(100*ss.cx)/sw->s.cx);
		}
		if(sw->s.cy && sw->nYMax){
			sw->nYSize = SetScrollSize(hWnd,SB_VERT,(100*ss.cy)/sw->s.cy);
		}
		sw->bChanging=FALSE;
		break;
	case SM_SETSIZE:
		sw->s.cx = (int)wParam;
		sw->s.cy = (int)lParam;
		GetClientRect(hWnd,&r);
		ScrollProc(hWnd,WM_SIZE,0,MAKELONG(r.right,r.bottom));
		break;
	case SM_GETXSIZE:
		return sw->nYMax;
	case SM_GETYSIZE:
		return sw->nYMax;
	case WM_HSCROLL:
		if(LOWORD(wParam)==SB_ENDSCROLL || lParam)
			break;
		GetClientRect(hWnd,&r);
		switch(LOWORD(wParam)){
		case SB_LINEDOWN:
			offs=-sw->nXLine;
			break;
		case SB_LINEUP:
			offs=sw->nXLine;
			break;
		case SB_PAGEDOWN:
			offs=-r.right;
			break;
		case SB_PAGEUP:
			offs=r.right;
			break;
		case SB_THUMBTRACK:
		case SB_THUMBPOSITION:
			offs=(int)(sw->nXPos - (sw->nXMax*HIWORD(wParam))/sw->nXSize);
			break;
		}
		if(sw->nXPos-offs<0)
			offs = sw->nXPos;
		if(sw->nXPos-offs>sw->nXMax)
			offs = sw->nXPos-sw->nXMax;
		sw->nXPos-=offs;
		SendMessage(hWnd,SN_SCROLLED,(int)offs,0);
		ScrollWindow(hWnd,(int)offs,0,NULL,NULL);
		if(sw->nXMax)
			SetScrollPos(hWnd,SB_HORZ,(int)(sw->nXPos*sw->nXSize/sw->nXMax)+(sw->nXPos>0),TRUE);
		break;
	case WM_VSCROLL:
		if(LOWORD(wParam)==SB_ENDSCROLL || lParam)
			break;
		GetClientRect(hWnd,&r);
		switch(LOWORD(wParam)){
		case SB_LINEDOWN:
			offs=-sw->nYLine;
			break;
		case SB_LINEUP:
			offs=sw->nYLine;
			break;
		case SB_PAGEDOWN:
			offs=-r.bottom;
			break;
		case SB_PAGEUP:
			offs=r.bottom;
			break;
		case SB_THUMBTRACK:
		case SB_THUMBPOSITION:
			offs=(int)(sw->nYPos - (sw->nYMax*HIWORD(wParam))/sw->nYSize);
			break;
		}
		if(sw->nYPos-offs<0)
			offs = sw->nYPos;
		if(sw->nYPos-offs>sw->nYMax)
			offs = sw->nYPos-sw->nYMax;
		sw->nYPos-=offs;
		SendMessage(hWnd,SN_SCROLLED,0,offs);
		ScrollWindow(hWnd,0,offs,NULL,NULL);
		if(sw->nYMax)
			SetScrollPos(hWnd,SB_VERT,(int)(sw->nYPos*sw->nYSize/sw->nYMax)+(sw->nYPos>0),TRUE);
		break;
	case WM_LBUTTONDOWN:
		pStart.x=(short)LOWORD(lParam);
		pStart.y=(short)HIWORD(lParam);
		SetCapture(hWnd);
		sw->bCapture=TRUE;
		break;
	case WM_MOUSEMOVE:
		if(GetCapture()!=hWnd)
			break;
		if(!sw->bCapture)
			break;
		x = pStart.x-(short)LOWORD(lParam);
		y = pStart.y-(short)HIWORD(lParam);
		if(sw->nXPos+x>sw->nXMax)
			x=sw->nXMax-sw->nXPos;
		else if(sw->nXPos+x<0)
			x=-sw->nXPos;
		if(sw->nYPos+y>sw->nYMax)
			y=sw->nYMax-sw->nYPos;
		else if(sw->nYPos+y<0)
			y=-sw->nYPos;
		sw->nXPos+=x;
		sw->nYPos+=y;
		SendMessage(hWnd,SN_SCROLLED,-x,-y);
		ScrollWindow(hWnd,-x,-y,NULL,NULL);
		if(sw->nXMax)
			SetScrollPos(hWnd,SB_HORZ,(int)(sw->nXPos*sw->nXSize/sw->nXMax)+(sw->nXPos>0),TRUE);
		if(sw->nYMax)
			SetScrollPos(hWnd,SB_VERT,(int)(sw->nYPos*sw->nYSize/sw->nYMax)+(sw->nYPos>0),TRUE);
		pStart.x-=x;
		pStart.y-=y;
		SendMessage(hWnd,WM_VSCROLL,SB_ENDSCROLL,0);
		break;
	case WM_LBUTTONUP:
		ReleaseCapture();
	case WM_CAPTURECHANGED:
		sw->bCapture=FALSE;
		break;
	case WM_DESTROY:
		delete sw;
		break;
	case 0x020A://WM_MOUSEWHEEL:
		if((short)HIWORD(wParam)<0){
			SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
			SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
			SendMessage(hWnd,WM_VSCROLL,SB_LINEDOWN,0);
		}
		else{
			SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);
			SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);
			SendMessage(hWnd,WM_VSCROLL,SB_LINEUP,0);
		}
		SendMessage(hWnd,WM_VSCROLL,SB_ENDSCROLL,0);
		break;
	case SM_GETXPOS:
		if(lParam)
			*((int*)lParam)=sw->nXPos;
		return sw->nXPos;
	case SM_GETYPOS:
		if(lParam)
			*((int*)lParam)=sw->nYPos;
		return sw->nYPos;
	case SM_SETXPOS:
		if(sw->nXSize && sw->nXMax){
			int nPrev=sw->nXPos;
			sw->nXPos=lParam;
			if(sw->nXPos<0)
				sw->nXPos=0;
			if(sw->nXPos>sw->nXMax)
				sw->nXPos=sw->nXMax;
			SetScrollPos(hWnd,SB_HORZ,(int)(sw->nXPos*sw->nXSize/sw->nXMax)+(sw->nXPos>0),TRUE);
			SendMessage(hWnd,SN_SCROLLED,nPrev-sw->nXPos,0);
			ScrollWindow(hWnd,nPrev-sw->nXPos,0,NULL,NULL);
			SendMessage(hWnd,WM_VSCROLL,SB_ENDSCROLL,0);
		}
		break;
	case SM_SETYPOS: 
		if(sw->nYSize && sw->nYMax){
			int nPrev=sw->nYPos;
			sw->nYPos=lParam;
			if(sw->nYPos<0)
				sw->nYPos=0;
			if(sw->nYPos>sw->nYMax)
				sw->nYPos=sw->nYMax;
			SetScrollPos(hWnd,SB_VERT,(int)(sw->nYPos*sw->nYSize/sw->nYMax)+(sw->nYPos>0),TRUE);
			SendMessage(hWnd,SN_SCROLLED,0,nPrev-sw->nYPos);
			ScrollWindow(hWnd,0,nPrev-sw->nYPos,NULL,NULL);
			SendMessage(hWnd,WM_VSCROLL,SB_ENDSCROLL,0);
		}
		break;
	}
	return 0;
}

int DataTick(int nRead, int nSize,LPARAM lParam)
{
	((CHTMLControl*)lParam)->Tick(nRead,nSize);
	return 1;
}

CHTMLControl::CHTMLControl(HWND hWnd,HWND hwParent,HWND hwStatus,HWND hwLink,HWND hwHistory)
{
	m_hWnd = hWnd;
	*m_szCurrUrl=*m_szCurrStatus=0;
	m_szActiveUrl=NULL;
	m_hwParent = hwParent;
	m_hwStatus = hwStatus;
	m_hwLink = hwLink;
	m_hwHistory = hwHistory;
	m_pViewer = new CHTMLViewer(this);
	m_bmBmp=NULL;
	m_bMainRequest=0;
	m_nFontSize = 15;
	strcpy(m_szFontName,"Arial");
}
CHTMLControl::~CHTMLControl()
{
	RemoveControls();
	if(m_bmBmp)
		DeleteObject(m_bmBmp);
	delete m_pViewer;
	if(m_szActiveUrl)
		delete m_szActiveUrl;
	ScrollProc(0,0,0,0);
}
void CHTMLControl::Reading(BOOL bImage,int nPos, int nSize)
{
	if(bImage)
		return;
	RECT r;
	GetClientRect(m_hWnd,&r);
	char szTmp[256];
	wsprintf(szTmp,"%s %d of %d",bImage?"Image":"Parsing",nPos,nSize);
	SetWindowText(m_hwStatus,szTmp);
}
void CHTMLControl::LinkClicked(char *szLink)
{
	RECT r;
	GetClientRect(m_hWnd,&r);
	::SetCursor(LoadCursor(NULL,IDC_WAIT));
	*m_szCurrStatus = 0;

	if(!strnicmp(szLink,"Submit(",7)){
		Submit(atoi(&szLink[7]));
		return ;
	}

	if(m_History.GetCount()){
		char szYPos[25];
		itoa(ScrollProc(m_hWnd,SM_GETYPOS,0,0),szYPos,10);
		if(m_History[m_History.GetCount()-1].GetCount()==2)
			m_History.AddString(m_History.GetCount()-1,szYPos);
		else
			m_History.SetString(m_History.GetCount()-1,2,szYPos);
	}
	if(strrchr(szLink,'.') && (!stricmp(strrchr(szLink,'.')+1,"jpg") || !stricmp(strrchr(szLink,'.')+1,"gif") || !stricmp(strrchr(szLink,'.')+1,"png"))){
		SetWindowText(m_hwLink,szLink);
		char *szTmp = new char[strlen(szLink)+100];
		strcpy(szTmp,"<body bgcolor=ffff00><img src=\"");
		strcat(szTmp,szLink);
		strcat(szTmp,"\"></body>");
		m_History.AddRow();
		m_History.AddString(m_History.GetCount()-1,szLink);
		m_History.AddString(m_History.GetCount()-1,szTmp);
		RemoveControls();
		m_pViewer->SetHTML(szTmp,m_szFontName,m_nFontSize,RGB(0,0,0),"");
		delete szTmp;
	}
	else{
		int nSize;
		char *szData;
		char *szUrl = new char[strlen(szLink)+1];
		strcpy(szUrl,szLink);
		SetWindowText(m_hwStatus,"From Internet");
		m_bMainRequest=1;
		szData = ReadHTTPData(szUrl,&nSize);
		m_bMainRequest=0;
		if(!szData){
			delete szUrl;
			return;
		}
		m_History.AddRow();
		m_History.AddString(m_History.GetCount()-1,m_szCurrUrl);
		m_History.AddString(m_History.GetCount()-1,szData);

		EnableWindow(m_hwHistory,m_History.GetCount()>1);
		static int nIndex=0;
		char szFileName[256];
		GetModuleFileName(GetModuleHandle(NULL),szFileName,sizeof(szFileName));
		*strrchr(szFileName,'.') = 0;
		strcat(szFileName,".txt");
		HANDLE hFile = CreateFile(szFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
		DWORD dw;
		WriteFile(hFile,szData,nSize,&dw,NULL);
		CloseHandle(hFile);

		RemoveControls();
		m_pViewer->SetHTML(szData,m_szFontName,m_nFontSize,RGB(0,0,0),m_szCurrUrl);
		SetWindowText(m_hwLink,m_szCurrUrl);
		delete szUrl;
		delete szData;
	}
	CalcPos();
	ScrollProc(m_hWnd,SM_SETXPOS,0,0);
	ScrollProc(m_hWnd,SM_SETYPOS,0,0);
	InvalidateRect(m_hWnd,NULL,FALSE);
	UpdateWindow(m_hWnd);

	::SetCursor(LoadCursor(NULL,IDC_ARROW));
}
void CHTMLControl::SetCursor(BOOL bLink,char *szLink)
{
	if(!m_szActiveUrl || strcmp(m_szActiveUrl,szLink)){
		if(m_szActiveUrl)
			m_pViewer->UpdateLink(m_szActiveUrl);
		delete m_szActiveUrl;
		m_szActiveUrl=new char[strlen(szLink)+1];
		strcpy(m_szActiveUrl,szLink);
	}
	if(bLink){
		::SetCursor(LoadCursor(NULL,MAKEINTRESOURCE(32649)));
		m_pViewer->UpdateLink(szLink);
		SetWindowText(m_hwStatus,szLink);
	}
	else{
		::SetCursor(LoadCursor(NULL,IDC_ARROW));
		SetWindowText(m_hwStatus,m_szCurrStatus);
	}
}
void CHTMLControl::SetTitle(char *szTitle)
{
	SetWindowText(m_hwParent,szTitle);
}
char *CHTMLControl::ReadHTTPData(char *szUrl, int *pnSize)
{
	if(!strnicmp(szUrl,"res://",6)){
		HRSRC hr;
		HGLOBAL hg;
		char *lpv;
		char *szData;
		if(!(hr = FindResource(GetModuleHandle(NULL), &szUrl[6],RT_HTML)) ||
				!(hg = LoadResource(GetModuleHandle(NULL),hr)) ||
				!(lpv = (char*)LockResource(hg))){

			if(!(hr = FindResource(GetModuleHandle(NULL), strrchr(szUrl,'/')+1,RT_HTML)) ||
					!(hg = LoadResource(GetModuleHandle(NULL),hr)) ||
					!(lpv = (char*)LockResource(hg))){
				return NULL;
			}
		}
		*pnSize = SizeofResource(GetModuleHandle(NULL),hr);
		szData = new char[*pnSize+1];
		memcpy(szData,lpv,*pnSize);
		szData[*pnSize] = 0;
		if(m_bMainRequest)
			strcpy(m_szCurrUrl,szUrl);
		return szData;
	}
#ifdef __HTTP_H__
	char *szHeader=NULL;
	char *szData = HTTP_Get(szUrl,pnSize,DataTick,(LPARAM)this,&szHeader,NULL,NULL,m_szCurrUrl);
	if(m_bMainRequest && szHeader){
		CHTMLStringTable st;
		st.SplitString(szHeader,": ","\r\n");
		delete szHeader;
		int i;
		for(i=0;i<st.GetCount();i++)
			if(!strcmp(st[i][0],"Location"))
				break;
		if(i==st.GetCount())
			return szData;
		delete szData;
		m_pViewer->AddBaseToUrl(st[i][1],m_szCurrUrl,szUrl);
		return ReadHTTPData(m_szCurrUrl,pnSize);
	}
	else
		return szData;
#else
	HINTERNET hSession=NULL, hURL=NULL;
	int k, len;
	char *szData=NULL;
	DWORD dwRead;
	char szSize[25]={0};
	char szLocation[2048];

	hSession = InternetOpen("Kalles Browser",INTERNET_OPEN_TYPE_DIRECT ,NULL,NULL,0);
	if(!hSession)
		return NULL;
	strcpy(szLocation,"Referer: ");
	strcat(szLocation,m_szCurrUrl);
	if(m_bMainRequest)
		strcpy(m_szCurrUrl,szUrl);
	if(!(hURL = InternetOpenUrl(hSession,szUrl,szLocation,-1,INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_NO_COOKIES|INTERNET_FLAG_NO_AUTO_REDIRECT ,0)))
		return NULL;

	len = sizeof(szSize);
	k = 0;
	HttpQueryInfo(hURL,HTTP_QUERY_CONTENT_LENGTH ,szSize,(ULONG*)&len,(ULONG*)&k);
	len = sizeof(szLocation);
	k = 0;
	*szLocation = 0;
	HttpQueryInfo(hURL,HTTP_QUERY_LOCATION,szLocation,(ULONG*)&len,(ULONG*)&k);
	
	for(len=0,k=0,len=1000;;len+=1000){
		szData = (char*)realloc(szData,len);
		if(!InternetReadFile(hURL,&szData[k],len-k,&dwRead) || !dwRead)
			break;
		k+=dwRead;
		Tick(k,atoi(szSize));
	}

	szData = (char*)realloc(szData,len+1);
	*pnSize = k+dwRead;
	szData[k+dwRead]=0;
	if(m_bMainRequest)
		for(k=0;k<*pnSize;k++)
			if(!szData[k])
				szData[k]=' ';
	InternetCloseHandle(hURL);
	InternetCloseHandle(hSession);

	if(m_bMainRequest && *szLocation){
		m_pViewer->AddBaseToUrl(szLocation,m_szCurrUrl,szUrl);
		return ReadHTTPData(m_szCurrUrl,pnSize);
	}
	else
		return szData;
#endif
}
char *CHTMLControl::PostHTTPData(char *szUrl,char *szPostData, int *pnSize)
{
#ifdef __HTTP_H__
	return HTTP_Post(szUrl,szPostData,strlen(szPostData),pnSize,DataTick,(LPARAM)this);
#else
	*m_szCurrStatus = 0;
	char szHeader[] = "Content-Type: application/x-www-form-urlencoded";
    char szAccept[] = "Accept: */*";
	HINTERNET hSession, hConnect, hRequest;
	char szHost[256];
	char szStatus[100];
	char *szData=NULL;
	DWORD dwRead;
	char szSize[25]={0};
	int i, j, len, k;
	for(i=0;szUrl[i] && strnicmp(&szUrl[i],"://",3);i++);
	if(szUrl[i])
		i+=3;
	for(j=0;szUrl[i] && szUrl[i]!='/';i++)
		szHost[j++] = szUrl[i];
	szHost[j]=0;
	if(
	   (hSession = InternetOpen("Kalles Browser",
								INTERNET_OPEN_TYPE_PRECONFIG, 
								NULL, 
								NULL, 
								0)) &&
	   // Connect to Internet server
	   (hConnect = InternetConnect(hSession, 
								   szHost,
								   INTERNET_DEFAULT_HTTP_PORT, 
								   NULL, 
								   NULL, 
								   INTERNET_SERVICE_HTTP, 
								   0, 
								   1)) &&
	   // Open POST-request to the web-page
	   (hRequest = HttpOpenRequest(hConnect, 
								   "POST",
								   &szUrl[i], 
								   NULL, 
								   NULL, 
								   (const char**)&szAccept, 
								   INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_RELOAD, 
								   1)) &&
	   // Send Request with postfields
	   HttpSendRequest(hRequest, 
					   szHeader, 
					   strlen(szHeader), 
					   szPostData, 
					   strlen(szPostData))){

		len = sizeof(szSize);
		k = 0;
		HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH ,szSize,(ULONG*)&len,(ULONG*)&k);
		
		for(len=0,k=0,len=1000;;len+=1000){
			szData = (char*)realloc(szData,len);
			if(!InternetReadFile(hRequest,&szData[k],len-k,&dwRead) || !dwRead)
				break;
			k+=dwRead;
			wsprintf(szStatus,"Reading %d of %s",k,szSize);
			SetWindowText(m_hwStatus,szStatus);
		}

		szData = (char*)realloc(szData,len+1);
		*pnSize = k+dwRead;
		szData[k+dwRead]=0;
		InternetCloseHandle(hRequest);
		InternetCloseHandle(hConnect);
		InternetCloseHandle(hSession);
		return szData;
	}
	return NULL;
#endif
}
int CHTMLControl::CreateForm(char *szAction, char *szMethod)
{
	int nIndex = m_Forms.AddRow()-1;
	m_Forms.AddString(nIndex,szAction);
	m_Forms.AddString(nIndex,szMethod);
	return nIndex;
}
int CHTMLControl::CreateTextBox(int nSize, int nMaxChar,SIZE scSize,char *szText,BOOL bMultiline,char *szName,int nForm,BOOL bPassword)
{
	m_Controls.AddRow();
	char szControl[25];
	HWND hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,"edit",szText,WS_CHILD|WS_TABSTOP|
		(bMultiline?ES_MULTILINE|WS_VSCROLL:ES_AUTOHSCROLL)|(bPassword?ES_PASSWORD:0),0,0,scSize.cx,scSize.cy,m_hWnd,(HMENU)m_Controls.GetCount(),GetModuleHandle(NULL),0);
	itoa((int)hWnd,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,szName);
	itoa(nForm,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,"0");
	if(nSize)
		SendMessage(hWnd,EM_SETLIMITTEXT,nMaxChar,0);
	SendMessage(hWnd,WM_SETFONT,(int)(bMultiline?GetStockObject(ANSI_FIXED_FONT):GetStockObject(ANSI_VAR_FONT)),0);
	return (int)hWnd;
}
int CHTMLControl::CreateButton(SIZE scSize,char *szText,char *szName,int nForm)
{
	m_Controls.AddRow();
	char szControl[25];
	HWND hWnd = CreateWindow("button",szText,WS_CHILD|WS_TABSTOP,
		0,0,scSize.cx,scSize.cy,m_hWnd,(HMENU)m_Controls.GetCount(),GetModuleHandle(NULL),0);
	itoa((int)hWnd,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,szName);
	itoa(nForm,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,"1");
	SendMessage(hWnd,WM_SETFONT,(int)GetStockObject(ANSI_VAR_FONT),0);
	return (int)hWnd;
}
int CHTMLControl::CreateRadio(SIZE scSize,char *szValue,char *szName,int nForm)
{
	m_Controls.AddRow();
	char szControl[25];
	HWND hWnd = CreateWindow("button",szValue,WS_CHILD|WS_TABSTOP|
		BS_AUTORADIOBUTTON,
		0,0,scSize.cx,scSize.cy,m_hWnd,(HMENU)m_Controls.GetCount(),GetModuleHandle(NULL),0);
	itoa((int)hWnd,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,szName);
	itoa(nForm,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,"2");
	m_Controls.AddString(m_Controls.GetCount()-1,szValue);
	SendMessage(hWnd,WM_SETFONT,(int)GetStockObject(ANSI_VAR_FONT),0);
	return (int)hWnd;
}
int CHTMLControl::CreateCheckbox(SIZE scSize,char *szValue,char *szName,int nForm)
{
	m_Controls.AddRow();
	char szControl[25];
	HWND hWnd = CreateWindow("button",szValue,WS_CHILD|WS_TABSTOP|
		BS_AUTOCHECKBOX,
		0,0,scSize.cx,scSize.cy,m_hWnd,(HMENU)m_Controls.GetCount(),GetModuleHandle(NULL),0);
	itoa((int)hWnd,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,szName);
	itoa(nForm,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,"3");
	m_Controls.AddString(m_Controls.GetCount()-1,szValue);
	SendMessage(hWnd,WM_SETFONT,(int)GetStockObject(ANSI_VAR_FONT),0);
	return (int)hWnd;
}
int CHTMLControl::CreateListbox(SIZE scSize,CHTMLStringTable &stOptions,int nSelected,char *szName,int nForm)
{
	m_Controls.AddRow();
	char szControl[25];
	HWND hWnd = CreateWindow("combobox","",WS_CHILD|WS_TABSTOP|
		CBS_DROPDOWNLIST|WS_VSCROLL,
		0,0,scSize.cx,scSize.cy+200,m_hWnd,(HMENU)m_Controls.GetCount(),GetModuleHandle(NULL),0);
	itoa((int)hWnd,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,szName);
	itoa(nForm,szControl,10);
	m_Controls.AddString(m_Controls.GetCount()-1,szControl);
	m_Controls.AddString(m_Controls.GetCount()-1,"4");
	SendMessage(hWnd,WM_SETFONT,(int)GetStockObject(ANSI_VAR_FONT),0);
	int i;
	for(i=0;i<stOptions.GetCount();i++){
		int nItem = SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM)stOptions[i][0]);
		char *szTmp = new char[strlen(stOptions[i][1])+1];
		strcpy(szTmp,stOptions[i][1]);
		SendMessage(hWnd,CB_SETITEMDATA,nItem,(LPARAM)szTmp);
	}
	SendMessage(hWnd,CB_SETCURSEL,nSelected,0);
	return (int)hWnd;
}

void CHTMLControl::MoveControl(int nControlID, POINT pPos)
{
	RECT r;
	GetWindowRect((HWND)nControlID,&r);
	r.right-=r.left;
	r.bottom-=r.top;
	MoveWindow((HWND)nControlID,pPos.x-ScrollProc(m_hWnd,SM_GETXPOS,0,0),pPos.y-ScrollProc(m_hWnd,SM_GETYPOS,0,0),r.right,r.bottom,TRUE);
	ShowWindow((HWND)nControlID,SW_SHOWNA);
	InvalidateRect((HWND)nControlID,NULL,FALSE);
	UpdateWindow((HWND)nControlID);
}
void CHTMLControl::RemoveControls()
{
	int i;
	for(i=0;i<m_Controls.GetCount();i++){
		if(atoi(m_Controls[i][3])==4){
			int j, nNum=SendMessage((HWND)atoi(m_Controls[i][0]),CB_GETCOUNT,0,0);
			for(j=0;j<nNum;j++){
				char *szTmp = (char*)SendMessage((HWND)atoi(m_Controls[i][0]),CB_GETITEMDATA,j,0);
				delete szTmp;
			}
		}
		DestroyWindow((HWND)atoi(m_Controls[i][0]));
	}
	m_Controls.Reset();
	m_Forms.Reset();
}

int CHTMLControl::ProcessMessage(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	if(uMsg==WM_CTLCOLORDLG)
		return (int)GetStockObject(NULL_BRUSH);
	else if(uMsg==WM_CTLCOLORBTN || uMsg==WM_CTLCOLORSTATIC){
		int nStyle = GetWindowLong((HWND)lParam,GWL_STYLE);
		if((nStyle & BS_AUTORADIOBUTTON) || (nStyle & BS_AUTO3STATE)){
			SetBkMode((HDC)wParam,TRANSPARENT);
			return (int)GetStockObject(NULL_BRUSH);
		}
	}
	else if(uMsg==WM_GETDLGCODE){
		return DLGC_WANTALLKEYS;
	}
	else if(uMsg==WM_PAINT && m_pViewer){
		RECT r;
		GetClientRect(hWnd,&r);
		PAINTSTRUCT ps;
		BeginPaint(hWnd,&ps);
#ifndef _DEBUG
		if(!m_bmBmp)
			m_bmBmp = CreateCompatibleBitmap(ps.hdc,r.right,r.bottom);
		HDC dcBmp = CreateCompatibleDC(ps.hdc);
		HBITMAP bmOld = (HBITMAP)SelectObject(dcBmp,m_bmBmp);
		m_pViewer->Draw(dcBmp,r,ScrollProc(hWnd,SM_GETXPOS,0,0),ScrollProc(hWnd,SM_GETYPOS,0,0));
		BitBlt(ps.hdc,0,0,r.right,r.bottom,dcBmp,0,0,SRCCOPY);
		SelectObject(dcBmp,bmOld);
		DeleteDC(dcBmp);
#else
		m_pViewer->Draw(ps.hdc,r,ScrollProc(hWnd,SM_GETXPOS,0,0),ScrollProc(hWnd,SM_GETYPOS,0,0));
#endif
		EndPaint(hWnd,&ps);
		return 1;
	}
	else if((uMsg==WM_USER+22 || uMsg==WM_SIZE) && m_pViewer){
		RECT r;
		GetClientRect(hWnd,&r);
		if(m_bmBmp)
			DeleteObject(m_bmBmp);
		HDC hDC = GetDC(hWnd);
		m_bmBmp = CreateCompatibleBitmap(hDC,r.right,r.bottom);
		ReleaseDC(hWnd,hDC);
		
		CalcPos();
		InvalidateRect(hWnd,NULL,FALSE);
		UpdateWindow(hWnd);
		GetClientRect(hWnd,&r);
	}
	else if(uMsg==WM_MOUSEMOVE && m_pViewer){
		POINT p = {(short)LOWORD(lParam),(short)HIWORD(lParam)};
		m_pViewer->OnMouseOver(p.x + ScrollProc(hWnd,SM_GETXPOS,0,0),p.y + ScrollProc(hWnd,SM_GETYPOS,0,0));

		if(GetCapture()==hWnd){
			RECT r;
			m_pSelectStop.x = (short)LOWORD(lParam);
			m_pSelectStop.y = (short)HIWORD(lParam);
			if(m_pSelectStart.x<m_pSelectStop.x){
				r.left = m_pSelectStart.x + ScrollProc(hWnd,SM_GETXPOS,0,0);
				r.right = m_pSelectStop.x + ScrollProc(hWnd,SM_GETXPOS,0,0);
			}
			else{
				r.left = m_pSelectStop.x + ScrollProc(hWnd,SM_GETXPOS,0,0);
				r.right = m_pSelectStart.x + ScrollProc(hWnd,SM_GETXPOS,0,0);
			}
			if(m_pSelectStart.y<m_pSelectStop.y){
				r.top = m_pSelectStart.y + ScrollProc(hWnd,SM_GETYPOS,0,0);
				r.bottom = m_pSelectStop.y + ScrollProc(hWnd,SM_GETYPOS,0,0);
			}
			else{
				r.top = m_pSelectStop.y + ScrollProc(hWnd,SM_GETYPOS,0,0);
				r.bottom = m_pSelectStart.y + ScrollProc(hWnd,SM_GETYPOS,0,0);
			}
			m_pViewer->Select(r);
			InvalidateRect(hWnd,NULL,FALSE);

			GetClientRect(hWnd,&r);
			if(m_pSelectStop.x<r.left){
				int nOffs = r.left-m_pSelectStop.x;
				if(nOffs>ScrollProc(hWnd,SM_GETXPOS,0,0))
					nOffs=ScrollProc(hWnd,SM_GETXPOS,0,0);
				ScrollProc(hWnd,SM_SETXPOS,0,ScrollProc(hWnd,SM_GETXPOS,0,0)-nOffs);
				m_pSelectStart.x+=nOffs;
			}
			else if(m_pSelectStop.x>r.right){
				int nOffs = m_pSelectStop.x-r.right;
				if(ScrollProc(hWnd,SM_GETXPOS,0,0)+nOffs>ScrollProc(hWnd,SM_GETXSIZE,0,0))
					nOffs=ScrollProc(hWnd,SM_GETXSIZE,0,0)-ScrollProc(hWnd,SM_GETXPOS,0,0);
				ScrollProc(hWnd,SM_SETXPOS,0,ScrollProc(hWnd,SM_GETXPOS,0,0)+nOffs);
				m_pSelectStart.x-=nOffs;
			}
			if(m_pSelectStop.y<r.top){
				int nOffs = r.top-m_pSelectStop.y;
				if(nOffs>ScrollProc(hWnd,SM_GETYPOS,0,0))
					nOffs=ScrollProc(hWnd,SM_GETYPOS,0,0);
				ScrollProc(hWnd,SM_SETYPOS,0,ScrollProc(hWnd,SM_GETYPOS,0,0)-nOffs);
				m_pSelectStart.y+=nOffs;
			}
			else if(m_pSelectStop.y>r.bottom){
				int nOffs = m_pSelectStop.y-r.bottom;
				if(ScrollProc(hWnd,SM_GETYPOS,0,0)+nOffs>ScrollProc(hWnd,SM_GETYSIZE,0,0))
					nOffs=ScrollProc(hWnd,SM_GETYSIZE,0,0)-ScrollProc(hWnd,SM_GETYPOS,0,0);
				ScrollProc(hWnd,SM_SETYPOS,0,ScrollProc(hWnd,SM_GETYPOS,0,0)+nOffs);
				m_pSelectStart.y-=nOffs;
			}
		}
		return 0;
	}
	else if(uMsg==WM_LBUTTONDOWN && m_pViewer){
		POINT p = {(short)LOWORD(lParam),(short)HIWORD(lParam)};
		m_pViewer->OnMouseClick(p.x + ScrollProc(hWnd,SM_GETXPOS,0,0),p.y + ScrollProc(hWnd,SM_GETYPOS,0,0));
		m_pSelectStart = p;
		RECT r={m_pSelectStart.x+ScrollProc(hWnd,SM_GETXPOS,0,0),m_pSelectStart.y+ScrollProc(hWnd,SM_GETYPOS,0,0),m_pSelectStart.x+ScrollProc(hWnd,SM_GETXPOS,0,0),m_pSelectStart.y+ScrollProc(hWnd,SM_GETYPOS,0,0)};
		m_pViewer->Select(r);
		InvalidateRect(hWnd,NULL,FALSE);
		if(GetParent(GetFocus())==hWnd)
			SetFocus(GetDlgItem(GetParent(m_hwLink),IDOK));
		SetCapture(hWnd);
		return 0;
	}
	else if(uMsg==WM_LBUTTONUP && GetCapture()==hWnd)
		ReleaseCapture();
	else if(uMsg==WM_RBUTTONDOWN && m_pViewer){
		HMENU hMen = CreatePopupMenu();
		AppendMenu(hMen,MF_STRING,1,"Copy Selection");
		POINT p = {(short)LOWORD(lParam),(short)HIWORD(lParam)};
		ClientToScreen(hWnd,&p);
		int nRet = TrackPopupMenu(hMen,TPM_RETURNCMD|TPM_LEFTALIGN|TPM_TOPALIGN,
			p.x,p.y,0,hWnd,NULL);
		if(nRet==1)
			m_pViewer->CopySelected();
		DestroyMenu(hMen);
	}
	else if(uMsg==WM_COMMAND && HIWORD(wParam)==0){
		Submit(-1,(HWND)lParam,LOWORD(wParam));
	}
	return ScrollProc(hWnd,uMsg,wParam,lParam);
}

void CHTMLControl::SetHTML(char *szHTMLData,char *szBaseUrl)
{
	RemoveControls();
	m_pViewer->SetHTML(szHTMLData,m_szFontName,m_nFontSize,RGB(0,0,0),szBaseUrl);
	CalcPos();
}
int CHTMLControl::EnableHistory()
{
	return m_History.GetCount()-1;
}
void CHTMLControl::GoBack()
{
	int nHistory = m_History.GetCount()-2;
	if(nHistory<0)
		return;
	::SetCursor(LoadCursor(NULL,IDC_WAIT));
	char *szData = new char[strlen(m_History[nHistory][1])+1];
	strcpy(szData,m_History[nHistory][1]);
	RemoveControls();
	m_pViewer->SetHTML(szData,m_szFontName,m_nFontSize,RGB(0,0,0),m_History[nHistory][0]);
	SetWindowText(m_hwLink,m_History[nHistory][0]);
	CalcPos();
	ScrollProc(m_hWnd,SM_SETYPOS,0,atoi(m_History[nHistory][2]));
	m_History.DeleteRow(m_History.GetCount()-1);
	InvalidateRect(m_hWnd,NULL,FALSE);
	UpdateWindow(m_hWnd);
	::SetCursor(LoadCursor(NULL,IDC_ARROW));
}


void CHTMLControl::CalcPos()
{
	RECT r, r2;
	GetClientRect(m_hWnd,&r);
	m_pViewer->CalcPositions(r);
	ScrollProc(m_hWnd,SM_SETSIZE,r.right,r.bottom);
/*	GetClientRect(m_hWnd,&r2);
	if(r2.right!=r.right || r2.bottom!=r.bottom){
		m_pViewer->CalcPositions(r2);
		ScrollProc(m_hWnd,SM_SETSIZE,r.right,r.bottom);
	}
*/
}

void CHTMLControl::Copy()
{
	m_pViewer->CopySelected();
}

char *CHTMLControl::UrlEncode(char *szStr)
{
	int i, j;
	int nLen=0;
	for(i=0;szStr[i];i++){
		if((szStr[i]>='a' && szStr[i]<='z') || (szStr[i]>='A' && szStr[i]<='Z') || (szStr[i]>='0' && szStr[i]<='9') || szStr[i]==' ')
			nLen++;
		else
			nLen+=3;
	}
	char *szRet = new char[nLen+1];
	for(i=j=0;szStr[i];i++){
		if((szStr[i]>='a' && szStr[i]<='z') || (szStr[i]>='A' && szStr[i]<='Z') || (szStr[i]>='0' && szStr[i]<='9'))
			szRet[j++] = szStr[i];
		else if(szStr[i]==' ')
			szRet[j++] = '+';
		else{
			szRet[j++] = '%';
			wsprintf(&szRet[j],"%02x",(unsigned char)szStr[i]);
			j+=2;
		}
	}
	szRet[j]=0;
	return szRet;
}

void CHTMLControl::Submit(int nForm,HWND hWnd,int nControlID)
{
	int i;
	if(nForm==-1)
		for(i=0;i<m_Controls.GetCount();i++)
			if((HWND)atoi(m_Controls[i][0])==hWnd && GetDlgCtrlID(hWnd)==nControlID && atoi(m_Controls[i][3])==1){
				nForm = atoi(m_Controls[i][2]);
				break;
			}
	if(nForm==-1)
		return;
	char *szPostData=NULL;
	int nPostData=0;
	int nPos=0;
	for(i=0;i<m_Controls.GetCount();i++){
		HWND hwControl = (HWND)atoi(m_Controls[i][0]);
		if(atoi(m_Controls[i][2])!=nForm || atoi(m_Controls[i][3])==1)
			continue;
		if((atoi(m_Controls[i][3])==2 || atoi(m_Controls[i][3])==3) && !SendMessage(hwControl,BM_GETCHECK,0,0))
			continue;
		//Add name
		nPostData+=strlen(m_Controls[i][1])+2;
		szPostData = (char*)realloc(szPostData,nPostData+1);
		strcpy(&szPostData[nPos],nPos?"&":"?");
		strcat(&szPostData[nPos],m_Controls[i][1]);
		strcat(&szPostData[nPos],"=");
		nPos=nPostData;
		// Add value
		if(atoi(m_Controls[i][3])==4){ // Listcontrol
			int nSelected = SendMessage(hwControl,CB_GETCURSEL,0,0);
			char *szTmp = (char*)SendMessage(hwControl,CB_GETITEMDATA,0,0);
			if(szTmp){
				char *szValue = UrlEncode(szTmp);
				nPostData+=strlen(szValue);
				szPostData = (char*)realloc(szPostData,nPostData+1);
				strcpy(&szPostData[nPos],szValue);
				nPos=nPostData;
				delete szValue;
			}
			else{
				int nDataLen = SendMessage(hwControl,CB_GETLBTEXTLEN,nSelected,0);
				char *szTmp = new char[nDataLen+1];
				SendMessage(hwControl,CB_GETLBTEXT,nSelected,(LPARAM)szTmp);
				char *szValue = UrlEncode(szTmp);
				nPostData+=strlen(szValue);
				szPostData = (char*)realloc(szPostData,nPostData+1);
				strcpy(&szPostData[nPos],szValue);
				nPos=nPostData;
				delete szValue;
				delete szTmp;
			}
			
		}
		else{
			int nDataLen = GetWindowTextLength(hwControl);
			char *szTmp = new char[nDataLen+1];
			GetWindowText(hwControl,szTmp,nDataLen+1);
			char *szValue = UrlEncode(szTmp);
			nPostData+=strlen(szValue);
			szPostData = (char*)realloc(szPostData,nPostData+1);
			strcpy(&szPostData[nPos],szValue);
			nPos=nPostData;
			delete szValue;
			delete szTmp;
		}
	}
	if(!stricmp(m_Forms[nForm][1],"get")){
		char *szUrl = new char[strlen(m_Forms[nForm][0])+nPostData+1];
		strcpy(szUrl,m_Forms[nForm][0]);
		if(strchr(szUrl,'?'))
			*szPostData = '&';
		strcat(szUrl,szPostData);
		LinkClicked(szUrl);
		delete szUrl;
	}
	else{
		int nSize;
		char szUrl[1024];
		strcpy(szUrl,m_Forms[nForm][0]);
		char *szTmp = PostHTTPData(szUrl,&szPostData[1],&nSize);
		if(szTmp){
			m_History.AddRow();
			m_History.AddString(m_History.GetCount()-1,szUrl);
			m_History.AddString(m_History.GetCount()-1,szTmp);
			RemoveControls();
			m_pViewer->SetHTML(szTmp,m_szFontName,m_nFontSize,RGB(0,0,0),szUrl);
			CalcPos();
		}
	}
	free(szPostData);
}
void CHTMLControl::Tick(int nPos,int nSize)
{
//	if(!m_bMainRequest)
//		return;
	char szStatus[80];
	if(nPos<0)
		return;
	if(nSize>0)
		wsprintf(szStatus,"Reading %d of %d",nPos,nSize);
	else
		wsprintf(szStatus,"Reading %d",nPos);
	SetWindowText(m_hwStatus,szStatus);
}

void CHTMLControl::ImageLoaded(int nDone, int nCount)
{
	int nAntal=10;
	while(nAntal<nCount)
		nAntal*=10;
	nAntal/=10;
	if(nDone==nCount || nDone%nAntal==0)
		PostMessage(m_hWnd,WM_USER+22,0,0);
	else
		InvalidateRect(m_hWnd,NULL,FALSE);
	if(nDone==nCount){
		int nItems,nImages,nLinks,nLevel;
		m_pViewer->Statistics(nItems,nImages,nLinks,nLevel);
		wsprintf(m_szCurrStatus,"Ready, items:%d, images:%d, links:%d, level:%d",nItems,nImages,nLinks,nLevel);
		SetWindowText(m_hwStatus,m_szCurrStatus);
	}
	else{
		char szStatus[50];
		wsprintf(szStatus,"Loaded Image %d of %d",nDone,nCount);
	}
}

void CHTMLControl::UpdateScreen(RECT &r)
{
	RECT rI = {r.left-ScrollProc(m_hWnd,SM_GETXPOS,0,0),r.top-ScrollProc(m_hWnd,SM_GETYPOS,0,0),
		r.right-ScrollProc(m_hWnd,SM_GETXPOS,0,0),r.bottom-ScrollProc(m_hWnd,SM_GETYPOS,0,0)};
	InvalidateRect(m_hWnd,&rI,FALSE);
}
