//////////////////////////////////////////////////////////////////////
//
// Разработчик: Алексей Фёдоров aka АЛьФ, mailto: alf@dorex.ru
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "addin.h"

#include "MethodsWrapper.h" // artbear

extern CDWordArray glColContArray;
extern CBkEndUI * pBkEndUI;

static bool pWrappedFN = false;

typedef LRESULT (CGetDlgWrapped::*PM_WP)(UINT, WPARAM, LPARAM);
static PM_WP pWrappedFNGetDlg = NULL;

extern BOOL m_bLocalColor;

static bool BrColWraped = false;
static bool BrColEditWraped = true;//false;

static DWORD* glFonts = NULL;
static char* glColor = NULL;
static COLORREF* glColorFont = NULL;
static COLORREF* glColorBrush = NULL;
static long glNumCol = 0;
static int curDimArray = 0;

typedef int(CColumn::*PF_DI)(class CDC &,class CRect &,class CString &,int);
/*static BYTE* adrWrapDrawItem;
static PF_DI jmpWrapDrawItem;
static BYTE  origWrapDrawItem[6];
static BYTE  wrapWrapDrawItem[6];*/
CDllMethodWrapper<PF_DI> wrapperDrawItem;

typedef CWnd* (CColumn::*PF_EDIT)(class CRect & ,class CBrowse *);
/*static BYTE* adrEdit;
static PF_EDIT jmpEdit;
static BYTE  origEdit[6];
static BYTE  wrapEdit[6];*/
CDllMethodWrapper<PF_EDIT> wrapperEdit;

typedef void (CBrowse::*PF_ONPAINT)(void);
/*static BYTE* adrOnPaint;
static PF_ONPAINT jmpOnPaint;
static BYTE  origOnPaint[6];
static BYTE  wrapOnPaint[6];*/
CDllMethodWrapper<PF_ONPAINT> wrapperOnPaint;

typedef int (CBrowse::*PF_STABLE)(void);
typedef void (CBrowse::*PF_REFRESH)(void);
typedef int (CColumn::*PF_DRAWITEM)(class CDC &,class CRect &,class CString &,int);
static HINSTANCE hBr32 = NULL;
static BYTE* adrStable;
static BYTE* adrRefresh;
//static BYTE* adrDrawItem;

static union PtrConv{
	void* pV;
	//PF_ONPAINT pOnPaint;
	PF_STABLE pstable;
	PF_REFRESH prefresh;
	//PF_DRAWITEM pDrawItem;
} prtconv;
//______________________________________________________________________________
//
CBrowseParser CBrowseWrapper::m_parser;

CBrowseParser::CBrowseParser()
{
	m_map = new CIStringMap<S_par*, S_par*>(true);

	m_map->SetAt("FONT",		m_par + e_FONT);
	m_map->SetAt("BRUSH",		m_par + e_BRUSH);
	m_map->SetAt("FONT_S",		m_par + e_FONT_S);
	m_map->SetAt("BRUSH_S",		m_par + e_BRUSH_S);
	m_map->SetAt("COUNT",		m_par + e_COUNT);
	m_map->SetAt("INDENT",		m_par + e_INDENT);
	m_map->SetAt("FONTSET",		m_par + e_FONTSET);
	m_map->SetAt("FONTSET_S",	m_par + e_FONTSET_S);
}

CBrowseParser::~CBrowseParser()
{
	delete m_map;
}

CBrowseParser::Parse(LPCSTR lpsz)
{
	int i, lim = 128;
	char buf[132], *pc;
	char ** endptr = NULL;

	// сброс параметров
	for (i =0; i <e_LAST__; ++i)
	{
		// только bFound, остальные параметры не определены
		m_par[i].bFound = FALSE;
	}

	// здесь отслеживается конец строки
	char ch = 1;
	while (ch && (ch =*lpsz++))
	{
		// пропуск пробелов
		if ((ch == 0x20) || (ch == 0x09))
			continue;

		// запомним ключ
		pc = buf;
		for (i =0; (i < lim) && ch; ++i)
		{
			*pc++ = ch;
			ch = *lpsz++;
			if (ch == '[')
			{
				*pc = 0;

				// получим указатель на ассоциированную структуру
				S_par *ppar;
				if (m_map->Lookup(buf, ppar))
				{
					// ключ найден
					ppar->bFound = TRUE;
					ppar->lpsz = lpsz;

					// сохраняем значение
					pc = buf;
					for (i = 0; (i < lim) && ch; ++i)
					{
						ch = *lpsz++;
						if (ch == ']')
							break;

						*pc++ = ch;
					}
					*pc = 0;

					if (m_map->Compare(buf, "NONE"))
					{
						// задан параметр
						ppar->bNone = FALSE;
						ppar->len = i;
						//ppar->num = atoi(buf);
						endptr = (char**)&buf;
						ppar->num = strtol(buf,endptr,0);
					}
					else
					{
						// задан "NONE"
						ppar->bNone = TRUE;
						ppar->len = i;
					}
				}
				else
				{
					// ключ не найден (некорректная строка)
					while ((ch = *lpsz++) && ch != ']');
				}
				break;
			}
		}
	}
}
//______________________________________________________________________________
//
void CBrowseWrapper::OnPaintWrap()
{
	CBrowse* This = (CBrowse*)this;
	if(This->IsWindowVisible() == FALSE)
	{
		// --- вызов штатной отрисовки таблицы ---
//		if(pWrappedFN)
//		{
//			memcpy(adrOnPaint, origOnPaint, 6);
//			prtconv.pV = adrOnPaint;
//			(This->*(prtconv.pOnPaint))();
//			memcpy(adrOnPaint, wrapOnPaint, 6);
//		};
		// ---------------------------------------
		return;
	}

	CColumn* pTestCol = &(This->GetColumnN(0));

	curDimArray = 0;
	glNumCol = 0;
	glFonts = NULL;
	glColor = NULL;
	glColorFont = NULL;
	glColorBrush = NULL;
	CSkipper* pDoc = This->pDoc;

	if(m_bLocalColor)
	{
		CWnd* pParentWnd = This->GetParent();
		bool f = false;

		if(pDoc != NULL)
		{
			int szContAr = glColContArray.GetSize();
			for(int iContAr = 0; (iContAr < szContAr) && (f == false); iContAr++)
				f = glColContArray.GetAt(iContAr) == (DWORD)pDoc;
		}

		if(!f)
		{
			// --- вызов штатной отрисовки таблицы ---
			if(pWrappedFN)
			{
				/*memcpy(adrOnPaint, origOnPaint, 6);
				prtconv.pV = adrOnPaint;
				(This->*(prtconv.pOnPaint))();
				memcpy(adrOnPaint, wrapOnPaint, 6);*/
				wrapperOnPaint.RestoreOrigAddress();

				(This->*(wrapperOnPaint.GetOrigMethod()))();

				wrapperOnPaint.RestoreWrapAddress();
			};
			// ---------------------------------------
			return;
		}
	}
	CValueTable* pTable = NULL;
	//CSkipper /*CDocument*/ * pDoc = (CSkipper*)*((int*)this+0x10);//(CDocument*)GetDocument();

	if(pDoc != NULL)
	{
		if(!strcmp(pDoc->GetRuntimeClass()->m_lpszClassName,"CTableSkipper"))
		{
			CBLContext* pTblCont = (CBLContext*)pDoc->m_Flag;
			if(pTblCont)
				pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();
		}
	}

	prtconv.pV = adrStable;
	if(!((This->*(prtconv.pstable))()))
	{
		prtconv.pV = adrRefresh;
		(This->*(prtconv.prefresh))();
		This->Invalidate();
	}

	int curCol = This->m_SelCol;//(int)*((int*)this+0x31);//
	int fixedCol = This->m_FixCol;//(int)*((int*)this+0x32);//
	int fixedRow = This->m_FixRow;//(int)*((int*)this+0x34);//
	long NumRow = This->m_numRow;//(long)*((int*)this+0x1C);//

	int curRow = This->m_SelRow;//(int)*((int*)this+0x30);//
//	if((*((int*)this+0x23) == 0) && (*((int*)this+0x2A) >= 0))
//		curRow =  (int)*((int*)this+0x2A);

	int y;
	int x;
	int vx;
	int dy = 0;
	int NumCol;
	int TableRowCount = 0;
	if(pTable != NULL)
	{
		dy = (*((int*)*((int*)this+0x10)+4)) - curRow - 1;
		NumCol = pTable->GetColumnCount();
		TableRowCount = pTable->GetRowCount();
	}
	else NumCol = This->GetColumnNum();
	if(dy<0)  dy=0;

	/*
	int bufFontSet;
	int bufFont;
	int bufBrush;
	int bufCount;
	int bufIndent;
	*/
	COLORREF st_fontCol = ::GetSysColor(COLOR_WINDOWTEXT); //RGB(0,0,0);
	COLORREF st_brushCol = (COLORREF)*(((UINT*)this)+0x36); //::GetSysColor(COLOR_WINDOW);//RGB(0xFF,0xFF,0xFF);

	if(st_brushCol == 0xFFFFFFFF)
		st_brushCol = ::GetSysColor(COLOR_WINDOW);
	COLORREF fontCol;
	COLORREF brushCol;
	DWORD fontSet;
	int CountCol = -1;
	int IndentCol = 0;
	BOOL Invis = FALSE;
	CString st_buf;

// ---
/*
	size_t size1 = NumCol*NumRow*sizeof(char);
	size_t size2 = NumCol*NumRow*sizeof(COLORREF);
	size_t size3 = NumCol*NumRow*sizeof(HFONT);
	glColor = (char*)malloc(size1);
	::memset(glColor,0,size1);
	glColorFont = (COLORREF*)malloc(size2);
	::memset(glColorFont,0,size2);
	glColorBrush = (COLORREF*)malloc(size2);
	::memset(glColorBrush,0,size2);
	glFonts = (HFONT*)malloc(size3);
	::memset(glFonts,0,size3);
*/
	curDimArray = NumCol*(NumRow+dy);

	glColor = new char[curDimArray];
	glFonts = new DWORD[curDimArray];
	glColorFont = new COLORREF[curDimArray];
	glColorBrush = new COLORREF[curDimArray];

	size_t size1 = curDimArray*sizeof(char);
	size_t size2 = curDimArray*sizeof(COLORREF);
	size_t size3 = curDimArray*sizeof(DWORD);

//	glColor = (char*)malloc(size1);
//	glColorFont = (COLORREF*)malloc(size2);
//	glColorBrush = (COLORREF*)malloc(size2);
//	glFonts = (DWORD*)malloc(size3);

	::memset(glColor,0,size1);
	::memset(glColorFont,0,size2);
	::memset(glColorBrush,0,size2);
	::memset(glFonts,0,size3);

	glNumCol = NumCol;

	int curPosArray = 0;
	int i;
	char ** endptr = NULL;
	const char * ptr = NULL;

	for(y=fixedRow; y < NumRow;y++)
	{
		if(pTable != NULL)
			if((y+dy) >= TableRowCount) break;

		fontCol = st_fontCol;
		brushCol = st_brushCol;
		fontSet = 0;
		vx = 0;
		Invis = FALSE;
		for(x = 0; x < NumCol; x++)
		{
			st_buf.Empty();
			if(pTable != NULL)
			{
				CVTColumn* pVTCol = pTable->GetColumn(x);

				if(pVTCol->GetVisible())
				{
					vx++;
					Invis = FALSE;
				}
				else
					Invis = TRUE;

				CValue val = pTable->GetValue(x, y+dy);
				st_buf = CString(val.Format());
			}
			else
			{
				Invis = (*((int*)&This->GetColumnN(x)+0x0F) & 0x1000000);
				vx = x+1;
				st_buf = ((CStringArray*)This->m_strArray[x])->GetAt(y);
			};

			// kms++: предлагаемый вариант парсинга
			if(!st_buf.IsEmpty())
			{
				CBrowseParser::S_par *ppar;
				m_parser.Parse((LPCSTR)st_buf);

				if(y == curRow)
				{
					// FONTSET
					ppar = &m_parser.m_par[CBrowseParser::e_FONTSET_S];
					if (!ppar->bFound)
						ppar = &m_parser.m_par[CBrowseParser::e_FONTSET];

					if (ppar->bFound)
					{
						if (!ppar->bNone)
							fontSet = ppar->num;

						CountCol = -1;
						IndentCol = 0;
					}

					// FONT
					ppar = &m_parser.m_par[CBrowseParser::e_FONT_S];
					if (!ppar->bFound)
						ppar = &m_parser.m_par[CBrowseParser::e_FONT];

					if (ppar->bFound)
					{
						if (ppar->bNone)
							fontCol = st_fontCol;
						else
							fontCol = ppar->num;

						CountCol = -1;
						IndentCol = 0;
					}

					// BRUSH
					ppar = &m_parser.m_par[CBrowseParser::e_BRUSH_S];
					if (!ppar->bFound)
						ppar = &m_parser.m_par[CBrowseParser::e_BRUSH];

					if (ppar->bFound)
					{
						if (ppar->bNone)
							brushCol = st_brushCol;
						else
							brushCol = ppar->num;

						CountCol = -1;
						IndentCol = 0;
					}
				}
				else
				{
					// FONTSET
					ppar = &m_parser.m_par[CBrowseParser::e_FONTSET];
					if (ppar->bFound)
					{
						if (ppar->bNone)
							fontSet = 0;
						else
							fontSet = ppar->num;

						CountCol = -1;
						IndentCol = 0;
					}

					// FONT
					ppar = &m_parser.m_par[CBrowseParser::e_FONT];
					if (ppar->bFound)
					{
						if (ppar->bNone)
							fontCol = st_fontCol;
						else
							fontCol = ppar->num;

						CountCol = -1;
						IndentCol = 0;
					}

					// BRUSH
					ppar = &m_parser.m_par[CBrowseParser::e_BRUSH];
					if (ppar->bFound)
					{
						if (ppar->bNone)
							brushCol = st_brushCol;
						else
							brushCol = ppar->num;

						CountCol = -1;
						IndentCol = 0;
					}
				}

				// COUNT
				ppar = &m_parser.m_par[CBrowseParser::e_COUNT];
				if (ppar->bFound)
				{
					if (ppar->bNone)
						CountCol = -1;
					else
						CountCol = ppar->num + 1;
					
					IndentCol = 0;
				}

				// INDENT
				ppar = &m_parser.m_par[CBrowseParser::e_INDENT];
				if (ppar->bFound)
				{
					if (ppar->bNone)
						IndentCol = 0;
					else
						IndentCol = ppar->num;
				}
			}
/*
			if(!st_buf.IsEmpty())
			{
				st_buf.MakeUpper();

				if(y == curRow)
				{
					bufFontSet = st_buf.Find("FONTSET_S[",0);
					if(bufFontSet >= 0)
						bufFontSet += 10;
					else
					{
						bufFontSet = st_buf.Find("FONTSET[",0);
						if(bufFontSet >= 0)
							bufFontSet += 8;
					}
					if(bufFontSet >= 0)
					{
						if(st_buf.Mid(bufFontSet, 4) =="NONE")
							fontSet = 0;
						else
							fontSet = (DWORD)atol(st_buf.Mid(bufFontSet));
						CountCol = -1;
						IndentCol = 0;
					}

					bufFont = st_buf.Find("FONT_S[",0);
					if(bufFont >= 0)
						bufFont += 7;
					else
					{
						bufFont = st_buf.Find("FONT[",0);
						if(bufFont >= 0)
							bufFont += 5;
					}
					if(bufFont >= 0)
					{
						if(st_buf.Mid(bufFont, 4) =="NONE")
							fontCol = st_fontCol;
						else
						{
							ptr = st_buf.Mid(bufFont);
							endptr = (char**)&ptr;
							fontCol = strtol(ptr,endptr,0);
						}
						CountCol = -1;
						IndentCol = 0;
					}

					bufBrush = st_buf.Find("BRUSH_S[",0);
					if(bufBrush >= 0)
						bufBrush += 8;
					else
					{
						bufBrush = st_buf.Find("BRUSH[",0);
						if(bufBrush >= 0)
							bufBrush += 6;
					}
					if(bufBrush >= 0)
					{
						if(st_buf.Mid(bufBrush, 4) =="NONE")
							brushCol = st_brushCol;
						else
						{
							ptr = st_buf.Mid(bufBrush);
							endptr = (char**)&ptr;
							brushCol = strtol(ptr,endptr,0); //atoi
						}
						CountCol = -1;
						IndentCol = 0;
					}
				}
				else
				{
					bufFontSet = st_buf.Find("FONTSET[",0);
					if(bufFontSet >= 0)
					{
						bufFontSet += 8;
						if(st_buf.Mid(bufFontSet, 4) =="NONE")
							fontSet = 0;
						else
							fontSet = (DWORD)atol(st_buf.Mid(bufFontSet));
						CountCol = -1;
						IndentCol = 0;
					}

					bufFont = st_buf.Find("FONT[",0);
					if(bufFont >= 0)
					{
						bufFont += 5;
						if(st_buf.Mid(bufFont, 4) =="NONE")
							fontCol = st_fontCol;
						else
						{
							ptr = st_buf.Mid(bufFont);
							endptr = (char**)&ptr;
							fontCol = strtol(ptr,endptr,0);
						}
						CountCol = -1;
						IndentCol = 0;
					}

					bufBrush = st_buf.Find("BRUSH[",0);
					if(bufBrush >= 0)
					{
						bufBrush += 6;
						if(st_buf.Mid(bufBrush, 4) =="NONE")
							brushCol = st_brushCol;
						else
						{
							ptr = st_buf.Mid(bufBrush);
							endptr = (char**)&ptr;
							brushCol = strtol(ptr,endptr,0); //atoi
						}
						CountCol = -1;
						IndentCol = 0;
					}
				}

				bufCount = st_buf.Find("COUNT[",0);
				if(bufCount >= 0)
				{
					bufCount += 6;
					if(st_buf.Mid(bufCount, 4) =="NONE")
						CountCol = -1;
					else
						CountCol = atoi(st_buf.Mid(bufCount))+1;
					IndentCol = 0;
				}

				bufIndent = st_buf.Find("INDENT[",0);
				if(bufIndent >= 0)
				{
					bufIndent += 7;
					if(st_buf.Mid(bufIndent, 4) =="NONE")
						IndentCol = 0;
					else
						IndentCol = atoi(st_buf.Mid(bufIndent));
				}
			}
*/
			curPosArray = vx+y*NumCol-1;

			if(IndentCol>0)
			{
				IndentCol--;
				continue;
			}
			else if(IndentCol<0)
			{
				if((brushCol != st_brushCol) || (fontCol != st_fontCol))
				{
//					if(-IndentCol >= vx)
//						IndentCol = 1-vx;
					if(CountCol>0)
					{
						if(vx+IndentCol <= fixedCol)
						{
							CountCol -= (fixedCol+1-vx)-IndentCol;
							if(CountCol <=0) CountCol = 1;
							else IndentCol = fixedCol+1-vx;
						}
						CountCol--;
						for(i = IndentCol; i < 0 && CountCol > 0; i++)
						{
							if((y != curRow) || (curPosArray+i != curCol+y*NumCol))
							{
								glColor[curPosArray+i] = char(1);
								glColorBrush[curPosArray+i] = brushCol;
								glColorFont[curPosArray+i] = fontCol;
							}
							glFonts[curPosArray+i] = fontSet;
							CountCol--;
						}
						if(CountCol>0) CountCol++;
						if(CountCol<0) CountCol = -1;
					}
					else
					{
						if(vx+IndentCol <= fixedCol)
							IndentCol = fixedCol+1-vx;
						for(i = IndentCol; i < 0; i++)
						{
							glColor[curPosArray+i] = char(1);
							glColorBrush[curPosArray+i] = brushCol;
							glColorFont[curPosArray+i] = fontCol;
							glFonts[curPosArray+i] = fontSet;
						}
					}
				}
				IndentCol = 0;
			}

			if(CountCol>0) CountCol--;
			if(CountCol == 0)
			{
				fontCol = st_fontCol;
				brushCol = st_brushCol;
				fontSet = 0;
				CountCol--;// надо это или нет?!
				continue;
			}

			if(Invis)
				continue;

			glFonts[curPosArray] = fontSet;

			if((vx>fixedCol) &&
				((y != curRow) || ((vx-1) != curCol)) &&
				((brushCol != st_brushCol) || (fontCol != st_fontCol)))
			{
				glColor[curPosArray] = char(1);
				glColorBrush[curPosArray] = brushCol;
				glColorFont[curPosArray] = fontCol;
			}

		};
	};
// --- вызов штатной отрисовки таблицы ---
//*/
	if(pWrappedFN)
	{
		/*memcpy(adrOnPaint, origOnPaint, 6);
		prtconv.pV = adrOnPaint;
		(This->*(prtconv.pOnPaint))();
		memcpy(adrOnPaint, wrapOnPaint, 6);*/
		wrapperOnPaint.RestoreOrigAddress();

		(This->*(wrapperOnPaint.GetOrigMethod()))();

		wrapperOnPaint.RestoreWrapAddress();
	};
//*/
// ---------------------------------------
/*/
	free(glColor);
	free(glColorBrush);
	free(glColorFont);
	free(glFonts);
/*/
	delete[] glColorFont;
	glColorFont = NULL;
	delete[] glColor;
	glColor = NULL;
	delete[] glColorBrush;
	glColorBrush = NULL;
	delete[] glFonts;
	glFonts = NULL;
//*/

	glNumCol = 0;
	curDimArray = 0;

};

static int glDrawItem(class CDC & mDC,class CRect & rect, int x, int y,CColumn* This,class CString & st)
{
	int ret = 0;
	int curPosArray = x+y*glNumCol;
	try
	{
		CBrowse* pBrowse = This->m_Browse;
		HFONT hFont = (HFONT)pBrowse->m_br_Font;
		COLORREF crOldText = mDC.GetTextColor();
		COLORREF crOldBk = mDC.GetBkColor();
		if((glNumCol > 0) && (curPosArray < curDimArray))
		{
			if(glColor[curPosArray] == 1)
			{
				mDC.SetTextColor(glColorFont[curPosArray]);
				mDC.SetBkColor(glColorBrush[curPosArray]);
				CRect cellrect(rect);
				cellrect.InflateRect(2,0);
				mDC.FillSolidRect(cellrect,glColorBrush[curPosArray]);
			}

			if(glFonts[curPosArray])
				hFont = (HFONT)glFonts[curPosArray];
		}

		::SelectObject(HDC(mDC),hFont);
		UINT alg = mDC.GetTextAlign();

		CString stTemp = st;
		int h = 0;
		int hi = 0;
		int dh = pBrowse->m_param13-2;
		int rectHi = rect.Height();
		do{
			CString stOutput = stTemp;
			int n = stTemp.Find("\r\n");
			if(n >= 0)
			{
				stOutput = stTemp.Left(n);
				n+=2;
				stTemp = stTemp.Mid(n);
			}
			else
				stTemp.Empty();
			h++;
			hi = h*dh;

			if(alg & TA_RIGHT)
				mDC.ExtTextOut(rect.right,hi+rect.top,ETO_CLIPPED,&rect,stOutput,NULL);
			else
				mDC.ExtTextOut(rect.left,hi+rect.top,ETO_CLIPPED,&rect,stOutput,NULL);
		} while((!stTemp.IsEmpty()) && (hi < rectHi));

		::SelectObject(HDC(mDC),(HFONT)pBrowse->m_br_Font);
		mDC.SetTextColor(crOldText);
		mDC.SetBkColor(crOldBk);
		ret = 1;
	}catch(...) {
	};

	return ret;	
}

int CBrowseWrapper::WrapDrawItem(class CDC & DC,class CRect & Rect,class CString & st,int flag)
{
	__asm{
		pop edi
		pop esi
		pop ebx
		mov esp,ebp
		pop ebp

		mov eax, ebx
		mov edx, ebp

		push        ebp
		mov         ebp,esp
		sub         esp,0x50
		push        ebx
		push        esi
		push        edi
		mov         dword ptr [ebp-0x04],ecx
	}
	int _y;
	int _x;

	__asm{
		mov [_x],eax
		mov [_y],edx
	}

	int ret = 0;

	//memcpy(adrWrapDrawItem, origWrapDrawItem, 6);
	wrapperDrawItem.RestoreOrigAddress();

	//prtconv.pV = adrWrapDrawItem; //adrDrawItem;
	//ret = (((CColumn*)this)->*(prtconv.pDrawItem))(DC,Rect,st,flag);
	ret = (((CColumn*)this)->*(wrapperDrawItem.GetOrigMethod()))(DC,Rect,st,flag);

	if(ret == 0)
		ret = glDrawItem(DC,Rect, _x, _y,(CColumn*)this,st);

	//memcpy(adrWrapDrawItem, wrapWrapDrawItem, 6);
	wrapperDrawItem.RestoreWrapAddress();

	return ret;
}

CWnd* CBrowseWrapper::WrapEdit(class CRect & a_Rect,class CBrowse * a_pBrowse)
{
	/*BYTE* adr1 = adrEdit;
	for(int i = 0; i<6;i++) *adr1++ = origEdit[i];*/
	wrapperEdit.RestoreOrigAddress();

	CColumn* This = (CColumn*)this;
	
	// artbear TODO зачем нужны следующие две строчки ?? // kms: не нужны имхо
//	PF_EDIT real = NULL;
	//memcpy(&real,&adrEdit,4);
//	memcpy( &real, &wrapperEdit.adr, 4);

//	CWnd * wndRet = (This->*real)(a_Rect,a_pBrowse);
	CWnd * wndRet = (This->*wrapperEdit.GetOrigMethod())(a_Rect, a_pBrowse);

	/*adr1 = adrEdit;
	for(i = 0; i<6;i++) *adr1++ = wrapEdit[i];*/
	wrapperEdit.RestoreWrapAddress();

	if(wndRet == NULL)
	{
		CValueTable* pTable = NULL;

		if(a_pBrowse->pDoc != NULL)
		{
			if(CString("CTableSkipper") == a_pBrowse->pDoc->GetRuntimeClass()->m_lpszClassName)
			{
				CBLContext* pTblCont = (CBLContext*)a_pBrowse->pDoc->m_Flag;
				if(pTblCont)
					pTable = ((CValueTableContextData*)pTblCont->GetInternalData())->GetValueTable();
			}
		}
		if(pTable)
		{
			CWnd* pParent = a_pBrowse->GetParent();
			CGetDoc7* pGetDoc = NULL;
			if(pParent->GetRuntimeClass()->IsDerivedFrom(RUNTIME_CLASS(CView)))
			{
				pGetDoc = (CGetDoc7*)((CView*)pParent)->GetDocument();
				((CBrowseView7*)pParent)->hBrowse = a_pBrowse->GetSafeHwnd();
				((CBrowseView7*)pParent)->m_pBrowse = a_pBrowse;
			}
			else
				pGetDoc = CGetDlg::GetTopmostDocunent();
			if(pGetDoc)
			{
				UINT id = This->m_ID;
				id &= 0x1FFF;
				id |= 0x0800;
				This->m_ID = id;
				CGetField* pGetField = pGetDoc->GetField(id);
				CCellGet* pGetCtrl = NULL;

				if(pGetField == NULL)
				{
					CGetFieldsArray* pGetFieldsArray = (CGetFieldsArray*)&pGetDoc->m_cGetFieldsArray1;
					pGetField = pGetFieldsArray->NewItem();
					CControlID* pControlID;
					pControlID = new CControlID;
					CType type(3);

					pControlID->SetPlace(CRect(0,0,0,0));
					pControlID->SetCtrlID(id);
					pControlID->SetCtrlType(5);
					pControlID->SetValType(type);
					pControlID->SetStyle(WS_VISIBLE | WS_CHILD);// | WS_GROUP | WS_BORDER);
					pControlID->SetExStyle(0);
					pControlID->SetBkColor(RGB(0xFF,0xFF,0xFF));
					pControlID->SetFontColor(RGB(0x00,0x00,0x00));
					pControlID->SetLongID(0x20);//-1);
					pControlID->SetLayerName("Основной");
					pControlID->SetToolTip("Проверка подсказки");
					pControlID->SetDependParam(0x20);

					pGetField->SetInTable(TRUE);
					pGetField->SetCtrlID(id);
					pGetField->SetCtrlType(type);
					pGetField->SetDoc(pGetDoc);
					pGetField->SetInternalValue(type);
					pGetField->SetBrOldStateEnable(FALSE);
					pGetField->SetFixKind(TRUE);

					pGetField->ReCreateValue(type);
					pGetField->WhantCheckLinkValue();
					pGetField->SetDef(NULL);
					pGetField->SetEnableChoiseFolder(TRUE);
					pGetField->SetParamNo(1);
					pGetField->SetQuickChoice(FALSE);
					pGetField->SetReadOnly(FALSE);
					pGetField->SetFlagSkipping(FALSE);
					pGetField->SetHideStateEnable(TRUE);
					pGetField->SetBrOldStateEnable(TRUE);
					pGetField->m_Flag0D = 0;
					pGetField->m_Flag10 = 2;
					pGetField->m_RefFlag = 0;



					CDate* date;
					date = new CDate(0,0,0);
					date->m_DateNum = CDate::GetCurrentDate().m_DateNum;

					pGetField->SetPDate(date);
					pGetField->m_Flag14 = 1;
					pGetField->m_Flag16 = 1;

					pGetField->SetCtrlInfo(pControlID);
					pGetField->TranslateType();
					pGetField->UpdateMask();
					pGetField->UpdateState();

					pGetCtrl = new CCellGet(a_pBrowse,id,pGetField->m_strWindowName,0xFF);
					//pGetCtrl->m_pGetDoc = pGetDoc; CControlList

					pGetDoc->m_cControlList.AddTail(pControlID);
					pGetDoc->AddGet((CGetCtrl*)pGetCtrl);
					pGetDoc->SetBrowseID(a_pBrowse->GetDlgCtrlID());
					
					
				}
				else
				{
					//pGetField->AvtoActivate();

					int n = pGetDoc->m_CtrlArray.GetSize();
					for(int i = 0; i < n; i++)
					{
						CCellGet* pGetCtrl = (CCellGet*)pGetDoc->m_CtrlArray[i];
						if(pGetCtrl && (pGetCtrl->m_uiID == id))
						{
							//pGetCtrl->SetActive();
							break;
						}
					}
				}

				CWnd* pWnd = pGetDoc->CreateControl(pGetField,id,a_Rect,a_pBrowse,0,0);
				if(pWnd)
				{//CMaskEdit WM_CLOSE CBtnEdit
					wndRet = pWnd;
					if(::GetFocus() == a_pBrowse->m_hWnd) pWnd->SetFocus();
				}
			}
		}
	}

	return wndRet;
}

void CBrowseWrapper::SetWrap()
{
	if(!pWrappedFN)
	{
		/*
		AFX_MSGMAP* msgMap = *(AFX_MSGMAP**)((BYTE*)(*(AFX_MSGMAP**)((BYTE*)(&messageMap)+2)));
		int i = 0;
		AFX_MSGMAP_ENTRY* msgMapEnt = NULL;
		do
		{
			msgMapEnt =  (AFX_MSGMAP_ENTRY*)&(msgMap->lpEntries[i++]);
		}while((msgMapEnt->nMessage != WM_PAINT) && (msgMapEnt->nMessage != 0));

		if(msgMapEnt->nMessage)
		{
			DWORD old = 0;

			pWrappedFN = msgMapEnt->pfn;

			AFX_PMSG pOnPaintWrap = (AFX_PMSG)&(CBrowse::OnPaintWrap);
			BYTE ** pb0 = (BYTE **)&(msgMapEnt->pfn);
			BYTE ** pb1 = (BYTE **)&(pOnPaintWrap);
			// меняем разрешения на доступ к памяти, чтобы изменить значение константы
			if(VirtualProtect(pb0, 4, PAGE_READWRITE, &old))
			{
				// опля! теперь можем спокойно перенаправить событие в свою функцию
				*pb0 = *pb1;
				// приберем за собой
				VirtualProtect(pb0, 4, old, &old);
			}
			msgMapEnt = NULL;
		};
		*/
		//DWORD old;
		HINSTANCE hBr32=GetModuleHandle("br32.dll");
		BYTE* adr1;
		/*int i;
		//?OnPaint@CBrowse@@IAEXXZ
		adr1=(BYTE*)GetProcAddress(hBr32,"?OnPaint@CBrowse@@IAEXXZ");
		VirtualProtect(adr1,6,PAGE_EXECUTE_READWRITE,&old);

		jmpOnPaint=(PF_ONPAINT)OnPaintWrap;
		adrOnPaint = adr1;
		for(i = 0; i<6;i++) origOnPaint[i] = *adr1++;
		adr1 = adrOnPaint;
		*adr1++=0xFF;
		*adr1++=0x25;
		*(DWORD*)adr1=(DWORD)&jmpOnPaint;
		adr1 = adrOnPaint;
		for(i = 0; i<6;i++) wrapOnPaint[i] = *adr1++;*/
		wrapperOnPaint.DoWrap(hBr32, "?OnPaint@CBrowse@@IAEXXZ", (PF_ONPAINT)OnPaintWrap);

		pWrappedFN = true;
		adr1=(BYTE*)GetProcAddress(hBr32,"?stable@CBrowse@@IAEHXZ");
		adrStable = adr1;
		adr1=(BYTE*)GetProcAddress(hBr32,"?refresh@CBrowse@@IAEXXZ");
		adrRefresh = adr1;

		if(!BrColWraped)
		{
			//?DrawItem@CColumn@@MAEHAAVCDC@@AAVCRect@@AAVCString@@H@Z
			/*adr1=(BYTE*)GetProcAddress(hBr32,"?DrawItem@CColumn@@MAEHAAVCDC@@AAVCRect@@AAVCString@@H@Z");
			VirtualProtect(adr1,6,PAGE_EXECUTE_READWRITE,&old);

			jmpWrapDrawItem=(PF_DI)WrapDrawItem;
			adrWrapDrawItem = adr1;
			for(i = 0; i<6;i++) origWrapDrawItem[i] = *adr1++;
			adr1 = adrWrapDrawItem;
			*adr1++=0xFF;
			*adr1++=0x25;
			*(DWORD*)adr1=(DWORD)&jmpWrapDrawItem;
			adr1 = adrWrapDrawItem;
			for(i = 0; i<6;i++) wrapWrapDrawItem[i] = *adr1++;*/
			wrapperDrawItem.DoWrap(hBr32, "?DrawItem@CColumn@@MAEHAAVCDC@@AAVCRect@@AAVCString@@H@Z", (PF_DI)WrapDrawItem);

			BrColWraped = true;
		}
		if(!BrColEditWraped)
		{
			/*//?Edit@CColumn@@MAEPAVCWnd@@AAVCRect@@PAVCBrowse@@@Z
			adr1=(BYTE*)GetProcAddress(hBr32,"?Edit@CColumn@@MAEPAVCWnd@@AAVCRect@@PAVCBrowse@@@Z");
			VirtualProtect(adr1,6,PAGE_EXECUTE_READWRITE,&old);

			jmpEdit=(PF_EDIT)WrapEdit;
			adrEdit = adr1;
			for(i = 0; i<6;i++) origEdit[i] = *adr1++;
			adr1 = adrEdit;
			*adr1++=0xFF;
			*adr1++=0x25;
			*(DWORD*)adr1=(DWORD)&jmpEdit;
			adr1 = adrEdit;
			for(i = 0; i<6;i++) wrapEdit[i] = *adr1++;*/
			wrapperEdit.DoWrap(hBr32, "?Edit@CColumn@@MAEPAVCWnd@@AAVCRect@@PAVCBrowse@@@Z", (PF_EDIT)WrapEdit);

			BrColEditWraped = true;
		}

		CMDIFrameWnd* pWnd = GetMainFrame();
		if(pWnd)
		{
			CWnd* pMDIWnd = CWnd::FromHandle(pWnd->m_hWndMDIClient);
			if(pMDIWnd)
			{
				CWnd* pMDIWndCh = pMDIWnd->GetNextWindow(GW_CHILD);
				while(pMDIWndCh)
				{
					pMDIWndCh->RedrawWindow();
					pMDIWndCh = pMDIWndCh->GetNextWindow();
				}
			}
		}
	}
}

void CBrowseWrapper::OffWrap()
{
	if(pWrappedFN)
	{
		/*BYTE* adr1 = adrOnPaint;
		for(int i = 0; i<6;i++) *adr1++ = origOnPaint[i];*/
		wrapperOnPaint.RestoreOrigAddress();

		pWrappedFN = false;

		CMDIFrameWnd* pWnd = GetMainFrame();
		if(pWnd)
		{
			CWnd* pMDIWnd = CWnd::FromHandle(pWnd->m_hWndMDIClient);
			if(pMDIWnd)
			{
				CWnd* pMDIWndCh = pMDIWnd->GetNextWindow(GW_CHILD);
				while(pMDIWndCh)
				{
					pMDIWndCh->RedrawWindow();
					pMDIWndCh = pMDIWndCh->GetNextWindow();
				}
			}
		}
	}
}

void  CGetDlgWrapped::SetWrap(void)
{
	CGetDlg testDlg(0,0);
	CGetDlg* ptestDlg = &testDlg;
	DWORD* pVTable = *(DWORD**)ptestDlg;
	PM_WP adr = myWindowProc;
	DWORD* pdw_adr = (DWORD*)&adr;
	DWORD dw_adr = *pdw_adr;

	memcpy(&pWrappedFNGetDlg,pVTable+0x28,4);
//	pWrappedFNGetDlg = (PM_WP)pVTable[0x28];
	DWORD old;
	VirtualProtect(pVTable,0xA4,PAGE_EXECUTE_READWRITE,&old);
	pVTable[0x28] = dw_adr;
}

LRESULT CGetDlgWrapped::myWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	LRESULT ret = 0;
	if(message == WM_SETCURSOR)
		ret = FormEx_OnSetCursor(LOWORD(lParam));
	else
		ret = (this->*pWrappedFNGetDlg)(message, wParam, lParam);

	return ret;
}
