// ReportElement.cpp: implementation of the CReportElement class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ReportDict.h"
#include "PropertyDlg.h"
#include "SelectTableDlg.h"
#include <math.h>
#include "Functions.h"

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

//#define GRPZ

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CReportElement::CReportElement(CaplReportMgr* ReportMgr, TReportElementType type)
{
	m_type = type;

	m_ReportMgr = ReportMgr;
//	m_rect.SetRectEmpty();
	m_org_pt = CPoint(0,0);
	m_size = CSize(0,0);

	m_line_width = AfxGetApp()->GetProfileInt(_T("DefaultSettings"),_T("LineWidth"),1);
	m_fixed = AfxGetApp()->GetProfileInt(_T("DefaultSettings"),_T("CreateFixed"),0);

	m_sel_pt_sz = CSize(20,20);
	m_sel_pt_color = ::GetSysColor(COLOR_WINDOWTEXT);//RGB(0,0,0);
	m_sel_pt_bg_color = ::GetSysColor(COLOR_WINDOW);//RGB (255,255,255); //RGB(0xff,0x99,00);

	m_select = 0;

	m_erase_color = RGB(255,255,255);
	m_sel_pt_width = 1;
	m_owner_sheet = NULL;
	m_inst = NULL;
	m_name = APL_T("Элемент");
	
	m_color = 0;
	m_background_color = RGB(255, 255, 255);

	m_bCreateTableContent = false;
	m_bNeedFillBackground = false;
}

CReportElement::~CReportElement()
{
}

CString	CReportElement::GetTypeName(TReportElementType type)
{
	switch(type)
	{
	case E_LINE					: return _T("LINE");break;
	case E_RECT					: return _T("RECT");break;
	case E_TABLE				: return _T("TABLE");break;
	case E_SHEET				: return _T("SHEET");break;
	case E_TABLE_MAP			: return _T("TABLE_MAP");break;
	case E_PICTURE				: return _T("PICTURE");break;
	case E_TABLE_CONTENT_TITLE	: return _T("TABLE_CONTENT_TITLE");break;
	case E_REFERENCE_ELEMENT	: return _T("REFERENCE_ELEMENT");break;
	}
	return _T("UNKNOW_TYPE");
}

BOOL CReportElement::Draw(CDC *pDC, double scale, int draw_mode, UINT flag)
{
	return true;
}

void CReportElement::DrawSelPoints(CDC* pDC, double scale)
{
	if(m_owner_sheet->m_sel_els.GetSize()==0) return;
	CPen sel_pen, *old_pen;
	CBrush sel_brush, *old_brush;
	sel_pen.CreatePen(PS_SOLID | PS_GEOMETRIC, 3, ::GetSysColor(COLOR_HIGHLIGHT));
	sel_brush.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
	CString str;
	PointArray sel_pts;
	GetSelPts( sel_pts,pDC,scale);
	if(m_type!=E_LINE)
	{
		CPen pen;
		pen.CreatePen(PS_SOLID, (int)((double)m_line_width*scale),::GetSysColor(COLOR_HIGHLIGHT));
		old_pen = pDC->SelectObject(&pen);
		CRect r;
		GetRect(r,scale);
		pDC->MoveTo(r.TopLeft());
		pDC->LineTo(r.right,r.top);
		pDC->LineTo(r.BottomRight());
		pDC->LineTo(r.left,r.bottom);
		pDC->LineTo(r.TopLeft());
		pDC->SelectObject(&sel_pen);
		pen.DeleteObject();
	}
	else
	{
		CPen pen;
		pen.CreatePen(PS_SOLID, (int)((double)m_line_width*scale),::GetSysColor(COLOR_HIGHLIGHT));
		old_pen = pDC->SelectObject(&pen);
		CRect r;
		GetRect(r,scale);
		pDC->MoveTo(r.TopLeft());
		pDC->LineTo(r.BottomRight());
		pDC->SelectObject(&sel_pen);
		pen.DeleteObject();
	}
	old_brush = pDC->SelectObject(&sel_brush);
	if(m_owner_sheet->m_sel_els.GetAt(0)==this)
	{
		for(int i=0; i < sel_pts.GetSize(); i++)
			pDC->Rectangle(GetSelPtRect(sel_pts[i]));
	}
	pDC->SelectObject(old_pen);
	pDC->SelectObject(old_brush);
	sel_pen.DeleteObject();
	sel_brush.DeleteObject();
}

int CReportElement::GetDragMode(CPoint pt, int &flag, double scale)
{
	int i;
	CRect rect, rect1;
	CRect sel_rect;
	GetRect(rect, scale);
	PointArray sel_pts;
	GetSelPts(sel_pts, NULL, scale); // получение точек выделения

	//Определяем по умолчанию как для прямоугольного элемента
	rect.NormalizeRect();
	rect1= rect;
	rect1.DeflateRect(5,5);
	
	if(m_select)
	{
		for(i=0; i<sel_pts.GetSize(); i++)
		{
			sel_rect = GetSelPtRect(sel_pts[i]);
			sel_rect.DeflateRect(-5, -5, -5, -5);
			if(sel_rect.PtInRect(pt))
			{
				if(m_fixed) return OBJ_FIXED;
				switch(i)
				{
				case 0: return TL_RESIZE;
				case 1: return T_RESIZE;
				case 2: return TR_RESIZE;;
				case 3: return R_RESIZE;
				case 4: return BR_RESIZE;
				case 5: return B_RESIZE;
				case 6: return BL_RESIZE;
				case 7: return L_RESIZE;
				}
			}
		}
	}
	if(rect.PtInRect(pt))
	{
		if(m_fixed) return OBJ_FIXED;
		return OBJ_MOVE;
	}
	
	return NONE;
}

CRect CReportElement::GetSelPtRect(CPoint pt)
{
	CRect r(pt,m_sel_pt_sz);
	r.OffsetRect(CSize(-m_sel_pt_sz.cx/2, -m_sel_pt_sz.cy/2));
	return r;
}

int CReportElement::ShowContextMenu(CPoint pt, CWnd * wnd, int mode)
{
	if(wnd == NULL) return false;
	
	HINSTANCE hInst = AfxGetResourceHandle();
	AfxSetResourceHandle(dllInst);
	wnd->ClientToScreen(&pt);
	
	CMenu menu;
	CMenu *pPopup;
	menu.LoadMenu(IDR_CONTEXT_MENU);
	pPopup = menu.GetSubMenu(5);
	
	if(m_fixed && mode==0)
		pPopup->ModifyMenu(ID_FIXED,MF_BYCOMMAND|MF_STRING, ID_FIXED,APL_T("Раcфиксировать"));
	
	BOOL res = pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD,pt.x, pt.y, wnd);
	
	AfxSetResourceHandle(hInst);
	if(res == 0) return false;
	
	switch(res)
	{
	case ID_FIXED :
		if(m_fixed>0) m_fixed = 0;
		else m_fixed = 1;
		break;
	case ID_ALIGN :
		Align();
		break;
	default : 
		return ExecuteCmd(res);
	}
	return 0;
}

void CReportElement::DrawLine(CDC * pDC, CPoint start, CPoint end)
{
	pDC->MoveTo(start);
	pDC->LineTo(end);
}

bool CReportElement::ElemProper(const int mode)
{
	HINSTANCE hInst = AfxGetResourceHandle();
	AfxSetResourceHandle(dllInst);
	bool res = false;
	RE_Array array;
	array.Add(this);
	CPropertyDlg dlg;
	dlg.m_elements = &array;
	dlg.mode = mode;
	if(dlg.DoModal()==IDOK) 
	{
		res =  true;
	}
	AfxSetResourceHandle(hInst);
	return res;
}

void CReportElement::SetRect(CRect r, double scale)
{
	r.top = (int)(r.top/scale);
	r.left = (int)(r.left/scale);
	r.bottom = (int)(r.bottom/scale);
	r.right = (int)(r.right/scale);
	m_org_pt = r.TopLeft();
	m_size = r.Size();

	if(m_size.cx>0)
	{
		if(m_owner_sheet)
			if(m_owner_sheet->m_size.cx<m_org_pt.x+m_size.cx) m_org_pt.x = m_owner_sheet->m_size.cx-m_size.cx;
		if(m_org_pt.x<0) m_org_pt.x=0;
	}
	else if(m_size.cx<0)
	{
		if(m_owner_sheet)
			if(m_owner_sheet->m_size.cx<m_org_pt.x) m_org_pt.x = m_owner_sheet->m_size.cx;
		if(m_org_pt.x+m_size.cx<0) m_org_pt.x=-m_size.cx;
	}
	if(m_size.cy>0)
	{
		if(m_owner_sheet)
			if(-m_owner_sheet->m_size.cy>m_org_pt.y) m_org_pt.y = -m_owner_sheet->m_size.cy;
		if(m_org_pt.y+m_size.cy>0) m_org_pt.y=-m_size.cy;
	}
	else if(m_size.cy<0)
	{
		if(m_owner_sheet)
			if(-m_owner_sheet->m_size.cy>m_org_pt.y+m_size.cy) m_org_pt.y = -m_owner_sheet->m_size.cy-m_size.cy;
		if(m_org_pt.y>0) m_org_pt.y=0;
	}
}

void CReportElement::GetRect(CRect &r, double scale, int mode)
{
	CString buf;
	CPoint pt;
	pt.x = int(m_org_pt.x*scale);//m_org_pt.x*scale;
	pt.y = int(m_org_pt.y*scale);
	CSize sz;
	sz.cx = int(m_size.cx*scale);
	sz.cy = int(m_size.cy*scale);
	if(mode==0 && m_owner_sheet)
		m_owner_sheet->PtSheetToLog(pt);
	r = CRect(pt,sz);
}

int CReportElement::GetSelPts(PointArray & pts, CDC *pDC, double scale)
{
	CPoint pt= m_org_pt;
	pt.x=(int)((double)pt.x*scale);
	pt.y=(int)((double)pt.y*scale);
	if(pDC)
	{
		if(pDC->IsPrinting()) pt= m_org_pt;
		else m_owner_sheet->PtSheetToLog(pt); // преобразум к координатам вида
	}
	else m_owner_sheet->PtSheetToLog(pt); // преобразум к координатам вида
	CRect r(pt,CSize((int)(m_size.cx*scale),(int)(m_size.cy*scale)));

	if(m_type == E_LINE)
	{
		// E_LINE
		// 0--
		// -1-
		// --2
		pts.Add(pt); //0
		pts.Add(pt + CSize(r.Width()/2, r.Height()/2)); //1
		pts.Add(r.BottomRight()); //3

	}
	else
	{
		//0-1-2
		//7   3
		//6-5-4
		pts.Add(pt); //0		
		pt = r.TopLeft() + CSize(r.Width() /2,0);
		pts.Add(pt);//1
		pt = CPoint(r.right,r.top);
		pts.Add(pt);//2
		pt += CSize(0,r.Height()/2);
		pts.Add(pt); //3
		pts.Add(r.BottomRight()); //4
		pt = CPoint(r.left,r.bottom);
		pts.Add(pt + CSize(r.Width()/2,0));//5
		pts.Add(pt); //6
		pt = r.TopLeft() + CSize(0,r.Height()/2);
		pts.Add(pt); // 7
	}

	return true;
}

void CReportElement::DrawRect(CDC *pDC, CRect r)
{
	pDC->MoveTo(r.left,r.top);
	pDC->LineTo(r.right,r.top);
	pDC->LineTo(r.right,r.bottom);
	pDC->LineTo(r.left,r.bottom);
	pDC->LineTo(r.left,r.top);
}

// возврашает возможные границы для потомка при изменении его размеров
int CReportElement::GetRange(CRect &r)
{
	r.SetRect(m_owner_sheet->GetOrgPt(), m_owner_sheet->GetOrgPt() + m_owner_sheet->m_size);
	return true;
}

void CTextValue::SetFont(LOGFONT &lf)
{
	m_font = lf;
}

CRect CReportElement::GetLeftRect(int size)
{
	CRect rect;
	GetRect(rect, 1, 1);
	rect.right = rect.left + size;
	rect.left = rect.left - size;
	rect.NormalizeRect();
	return rect;
}

CRect CReportElement::GetTopRect(int size)
{
	CRect rect;
	GetRect(rect, 1, 1);
	rect.bottom = rect.top + size;
	rect.top = rect.top - size;
	rect.NormalizeRect();
	return rect;
}

CRect CReportElement::GetRightRect(int size)
{
	CRect rect;
	GetRect(rect, 1, 1);
	rect.left = rect.right - size;
	rect.right = rect.right + size;
	rect.NormalizeRect();
	return rect;
}

CRect CReportElement::GetBottomRect(int size)
{
	CRect rect;
	GetRect(rect, 1, 1);	
	rect.top = rect.bottom - size;
	rect.bottom = rect.bottom + size;
	rect.NormalizeRect();
	return rect;
}

int CTextValue::BreakString(CStringArray *strs, int cx, CDC *pDC, CString* str)
{
	if(str==0)
		return BreakString(strs, cx, pDC, m_text);
	else
		return BreakString(strs, cx, pDC, *str);
}

int FindRazelitInSTR(CString &str) //писал ayatsk
{
	int i,l,pos=-1;
	CString buf;
	
	// 1. Находим ГОСТ или ОСТ.  Если есть - режем по нему.

	l=str.GetLength();
	i=l-1; 
	while(i>4)//Если ОСТ - первые символы - делить по ним смысла нет.
	{
		if(str[i]==_T('Т'))
		{
			if(str[i-1]==_T('С'))
			{
				if(str[i-2]==_T('О'))
				{
					pos=i-3;
					if(str[i-3]==_T('Г')) pos=i-4;
				}
				i--; // пред. символ проверять уже смысла нет.
			}
		}
		if(pos>0) return pos;
		i--;
	}

	// 2. Находим ТУ.  Если есть - режем по нему.
	i=l-1; 
	while(i>2)
	{
		if(str[i]==_T('У'))
		{
			if(str[i-1]==_T('Т'))
			{
				if(str[i-2]==_T(' '))
				{
					pos=i-2;
				}
				else
				{
					if(str[i+1]==_T(' ')) pos=i+1;
				}
			}
		}
		if((pos>0)&&(l-pos>3) ) return pos; // (l-pos>3) - 
		i--;
	}

	i=str.ReverseFind(_T(' '));
	if(i>0)
	{
		//нельзя отделять от Омов и Фарадов

		bool bNoRazd=false;
		buf=str.Mid(i+1,2);
		buf.MakeLower();
		if(buf==APL_T("ом") || buf==APL_T("пф") || buf==APL_T("мф") || buf==APL_T("нф") || buf==APL_T("фф") || buf==APL_T("ту")) 
			bNoRazd=true;

		if(!bNoRazd)
		{
			buf=str.Mid(i+1,3);
			buf.MakeLower();
			if(buf==APL_T("ком") || buf==APL_T("мом") || buf==APL_T("гом") || buf==APL_T("мкф") ) 
				bNoRazd=true;
		}
		if(!bNoRazd) return i;
	}

	i=str.ReverseFind(_T('№'));
	if(i>0) return i;

	i=str.ReverseFind(_T('#'));
	if(i>0) return i;

	i=str.ReverseFind(_T(':'));
	if(i>0) return i;

	i=str.ReverseFind(_T(';'));
	if(i>0) return i;

	i=str.ReverseFind(_T('!'));
	if(i>0) return i;

	i=str.ReverseFind(_T('('));
	if(i>1) return i-1;
	i=str.ReverseFind(_T('['));
	if(i>1) return i-1;
	i=str.ReverseFind(_T('{'));
	if(i>1) return i-1;

	i=str.ReverseFind(_T(')'));
	if(i>0) return i;
	i=str.ReverseFind(_T(']'));
	if(i>0) return i;
	i=str.ReverseFind(_T('}'));
	if(i>0) return i;

	i=str.ReverseFind(_T('/'));
	if(i>0) return i+1;

	i=str.ReverseFind(_T('\\'));
	if(i>0) return i+1;

	i=str.ReverseFind(_T('='));
	if(i>0) return i+1;

	i=str.ReverseFind(_T('*'));
	if(i>0) return i+1;	

	i=str.ReverseFind(_T('%'));
	if(i>0) return i+1;	

	i=str.ReverseFind(_T('-'));
	if(i>0)
	{
		if(str[i-1]==_T('+')) return i-2;	
		return i;		
	}

	i=str.ReverseFind(_T('+'));
	if(i>0) return i;	
	
	// ayatsk  по точке и запятой переносить нежелательно, т.к. это чила и получается фигня
	// поэтому рассматриваем как самые последние
	i=str.ReverseFind(_T(','));
	if(i>0) return i+1;	

	i=str.ReverseFind(_T('.'));
	if(i>0) return i+1;	

	return -1;
}



int ayatsk_ReverseFindChar(TCHAR c, CString &str, bool perenos,CDC *pDC, int cx, int last_pos, CString &rezult)
{
	// Если символ переносится на след. позицию, то perenos должен быть true, иначе false
	rezult=_T("");
	int i=last_pos; 
	CString tmp;
	CSize sz;

	while(i>0)
	{
		if(str[i]==c)
		{
			if(perenos) i--;
			tmp=str.Left(i+1);
			sz=pDC->GetTextExtent(tmp);
			if(sz.cx<=cx)
			{
				rezult=tmp;
				return i+1;
			}
		}
		i--;
	}
	return -1;
}

int FindRazelitInSTR2(CString &str, CDC *pDC, int cx, int last_pos, CString &result) //писал ayatsk
{
	result=_T("");
	int i,l,pos=-1;
	CSize sz;
	CString buf,tmp;
	if(0==pDC) return -1;
	if(cx<=0) return -1;
	l=str.GetLength();
	if(last_pos>l )last_pos=l;

	// 1. Находим ГОСТ или ОСТ.  Если есть - режем по нему.
	CString sGOST;
	int iGOST = -1;
	i=last_pos; 
	if(i>l )i=l;
	while(i>4)//Если ОСТ - первые символы - делить по ним смысла нет.
	{
		pos=-1;
		if(str[i]==_T('Т'))
		{
			if(str[i-1]==_T('С'))
			{
				if(str[i-2]==_T('О'))
				{
					pos=i-2;
					if(str[i-3]==_T('Г')) pos=i-3;
				}
				i--; // пред. символ проверять уже смысла нет.
			}
		}
		if(pos>0)
		{
			tmp=str.Left(pos);
			tmp.TrimRight();
			sz=pDC->GetTextExtent(tmp);
			if(sz.cx<=cx)
			{
//				result = tmp;
//				return pos;
				sGOST = tmp;
				iGOST = pos;
				break;
			}
		}
		i--;
	}

	// 2. Находим ТУ.  Если есть - режем по нему.
	CString sTU;
	int iTU = -1;
	i=last_pos; 
	if(i>l )i=l;
	while(i>2)
	{
		if(str[i]==_T('У'))
		{
			if(str[i-1]==_T('Т'))
			{
				if(str[i-2]==_T(' '))
				{
					pos=i-2;
				}
				else
				{
					if(str[i+1]==_T(' ')) pos=i+1;
				}
			}
		}
		if((pos>0)&&(l-pos>3) )
		{
			tmp=str.Left(pos);
			sz=pDC->GetTextExtent(tmp);
			if(sz.cx<=cx)
			{
//				result = tmp;
//				return pos;
				sTU = tmp;
				iTU = pos;
				break;
			}
		}
		i--;
	}

	// 2. Находим пробел.  Если есть - режем по нему.
	i=last_pos; 
	if(i>l )i=l;
	while(i>1)
	{
		i--;
		if(str[i]!=_T(' ')) continue;

		//нельзя отделять от Омов и Фарадов
		bool bNoRazd=false;
		buf=str.Mid(i+1,2);
		buf.MakeLower();
		if(buf==APL_T("ом") || buf==APL_T("пф") || buf==APL_T("мф") || buf==APL_T("нф") || buf==APL_T("фф") || buf==APL_T("ту")) 
			bNoRazd=true;

		if(!bNoRazd)
		{
			buf=str.Mid(i+1,3);
			buf.MakeLower();
			if(buf==APL_T("ком") || buf==APL_T("мом") || buf==APL_T("гом") || buf==APL_T("мкф") ) 
				bNoRazd=true;
		}
		if(!bNoRazd)
		{
			tmp=str.Left(i);
			sz=pDC->GetTextExtent(tmp);
			if(sz.cx<=cx)
			{
				if(i+1 > iGOST && i+1 > iTU)
				{
					result = tmp;
					return i+1;
				}
				else if(iGOST > iTU)
				{
					result = sGOST;
					return iGOST;
				}
				else
				{
					result = sTU;
					return iTU;
				}
			}
		}
	}
	if(iGOST > -1 && iGOST > iTU)
	{
		result = sGOST;
		return iGOST;
	}
	else if(iTU > -1)
	{
		result = sTU;
		return iTU;
	}

	i=ayatsk_ReverseFindChar(_T('№'),str,true,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('#'),str,true,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T(':'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T(';'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('!'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('('),str,true,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('['),str,true,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('{'),str,true,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T(')'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T(']'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('}'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('/'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('\\'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('='),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('%'),str,false,pDC,cx,last_pos,result);
	if(i>0) 
		return i;

	i=ayatsk_ReverseFindChar(_T('*'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('-'),str,false,pDC,cx,last_pos,result);
	if(i>0)
	{
		if (str[i-2]==_T('+')) {result = str.Left(i-2); return i-2;}
		else return i;
	}

	i=ayatsk_ReverseFindChar(_T('+'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;


	// ayatsk  по точке и запятой переносить нежелательно, т.к. это чила и получается фигня
	// поэтому рассматриваем как самые последние

	i=ayatsk_ReverseFindChar(_T(','),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	i=ayatsk_ReverseFindChar(_T('.'),str,false,pDC,cx,last_pos,result);
	if(i>0) return i;

	return -1;
}

// Проверка возможности объединения с предыдущим
bool ayatsk_UnionWithPrev(CStringArray *strs, CString &txt, CString &buf, int str_pos, CDC *pDC, int cx)
{
	
	if(strs->GetSize()< 1) return false;
	if(str_pos<1)return false;
	if(txt[str_pos-1]==_T('\n')) return false;

	CString buf1;
	CSize sz;
	buf1=strs->GetAt(strs->GetSize()-1);
	buf1+= _T(' ');
	buf1+= buf;
	sz=pDC->GetTextExtent(buf1);
	if(sz.cx<=cx) { strs->SetAt(strs->GetSize()-1,buf1); return true;}
	return false;
}


int ayatsk_BreakString(CStringArray *strs, int cx, CDC *pDC, CString &str)
{
	if(cx<0) return -1;
	if(strs==0) return -1;
	strs->RemoveAll();

	if(str==_T("")) return 0; // добавил ayatsk чтобы в отладке смотреть только реальные значения. Работает и без этого.
	CString buf,buf1,txt,tmp;

	txt = str;
	txt.Replace(_T("\r"), _T(""));

	int i, d_str=0, str_pos=0;
	int txtlen=txt.GetLength();

	while(true)
	{
		if(d_str>0) str_pos+=d_str;
		if(txtlen<=str_pos) break;

		int i_n=txt.Find(_T('\n'),str_pos);
		if(i_n==0) {d_str++; strs->Add(_T("")); continue;}
		else if(i_n>0) { tmp=txt.Mid(str_pos,i_n-str_pos); d_str=i_n+1-str_pos;}
		else { d_str=txtlen-str_pos; tmp=txt.Right(d_str); }

		//tmp.TrimLeft(); ayatsk убрал для возможности выравнивания пробелами в формуляре
		tmp.TrimRight();
		if(tmp==_T("")) {strs->Add(_T("")); continue;}

		CSize sz=pDC->GetTextExtent(tmp);
		if(sz.cx<cx)
		{
			if(!ayatsk_UnionWithPrev(strs,txt,tmp,str_pos,pDC,cx))
				strs->Add(tmp);
			continue;
		}
		d_str=tmp.GetLength()*cx/sz.cx;

		//buf=tmp.Left(d_str); Это для отладки работы без эвристик
		//strs->Add(buf); 

		// Компенсируем разницу в ширине символов и попадание внутрь ГОСТ
			// эти 2 строки отражают смысл, но не учитывают \n
			//d_str+=15; 
			//if( (str_pos+d_str) > txtlen) d_str=txtlen-str_pos;
		
		int j=15;
		while(j>0)
		{
			if(tmp[d_str]==_T('\n')) break;
			if(tmp[d_str]==_T('\0')) break;
			d_str++;
			j--;
		}

		i=FindRazelitInSTR2(tmp,pDC,cx,d_str,buf);
		if(i>0)
		{
			d_str=i;
			if(!ayatsk_UnionWithPrev(strs,txt,buf,str_pos,pDC,cx))
				strs->Add(buf);
			continue;
		}

		// Найти разделитель не получилось - рвем где получится.
		i=d_str;
		while(i>1)
		{
			if(i==1)// не влез ни один символ
			{
				buf=_T("");
				i=d_str;
				break;
			}
			i--;
			buf=tmp.Left(i);
			sz=pDC->GetTextExtent(buf);
			if(sz.cx<=cx)
				break;
		}
		d_str=i;
		strs->Add(buf);
	}

	/*TRACE(_T("\n\n\n"));
	for(i=0;i<strs->GetSize();i++)
	{
		buf=strs->GetAt(i);
		TRACE(_T("\n%s"),LPCSTR(buf));
	}*/

	return strs->GetSize();
};


int CTextValue::BreakString(CStringArray *strs, int cx, CDC *pDC, CString &str)
{
/*	str=_T("1234\n5678\nccc123\nabc/defghijl4567890\nqwe");
	//str=_T("678\nabcdefghijl4567890");
	ayatsk_BreakString(strs,200,pDC,str);

	str=APL_T("с1(с2(с3(с4(с5(с6(с7(с8(с9,C10");
	ayatsk_BreakString(strs,200,pDC,str);

	str=APL_T("90 ГОСТ 12345-98 234567 3456789 ОСТ 123 с1");
	ayatsk_BreakString(strs,200,pDC,str);

	str=APL_T("1 \n ГОСТ 123435-98 234567 3456789 ОСТ 123 с1");
	ayatsk_BreakString(strs,200,pDC,str);

	str=APL_T("1 \nГОСТ 123435-98 234567 3456789 ОСТ 123 с1");
	ayatsk_BreakString(strs,200,pDC,str);

	str=APL_T("1\n ГОСТ 123435-98 234567 3456789 ОСТ 123 с1");
	ayatsk_BreakString(strs,200,pDC,str);
	str=APL_T("1\nГОСТ 123435-98 234567 3456789 ОСТ 123 с1");
	ayatsk_BreakString(strs,200,pDC,str);

	str=APL_T("1234 5678\n1b bb123+45678912345 67891+-234567891 234567891234\ncccc12№34567890 ГОСТ 12345-98 234567 ОСТ 123 с1,с2,с3,с4,с5,с6,с7,с8,с9,C10");
	str=APL_T("+-234567891 234567891234\ncccc12№34567890 ГОСТ 12345-98 234567 ОСТ 123 с1,с2,с3,с4,с5,с6,с7,с8,с9,C10");
	//str=_T("1b bb1 2345678 912345 6789123 4567891 2345 67891234");
	ayatsk_BreakString(strs,200,pDC,str);
	
	return -1;*/
	return ayatsk_BreakString(strs,cx,pDC,str);

	if(cx<0) return -1;
	if(strs==0) return -1;
	strs->RemoveAll();


	if(str==_T("")) return 0; // добавил ayatsk чтобы в отладке смотреть только реальные значения. Работает и без этого.
	CString txt;
	CString tmp;
	
	int len, s_ind, n_len, up_len, min_len;
	tmp = str;

	//CString br_str;
	//br_str = char(13);
	//tmp.Replace(br_str, _T(""));
	tmp.Replace(_T("\r"), _T(""));  // заменил предыдущее ayatsk

	while(!tmp.IsEmpty())
	{
		txt = tmp;
		len = tmp.GetLength();
		n_len = len;
		s_ind = n_len;
		min_len = 0;
		up_len = len;
		do
		{
			txt = tmp.Left(n_len);
			if(pDC->GetTextExtent(txt).cx>cx)
			{
				up_len = n_len;
				n_len =(up_len+min_len)/2;
			}
			else if(pDC->GetTextExtent(txt).cx==cx)
			{
				min_len = txt.GetLength();
				break;
			}
			else if(n_len==len)
			{
				min_len = len;
				break;
			}
			else
			{
				min_len = n_len;
				n_len =(up_len+min_len)/2;
				if(min_len==n_len && n_len==1)
					return -1;//Не уместился ни один символ!
			}
			if((up_len-min_len)/2==0)
				break;
		}while(1);

		if(min_len==0) 
			return -1;//В данную ширину не помещается ни один символ

		n_len = min_len;
		min_len+=3;

		//Добавил ayatsk, чтобы ТУ не попадали отдельно на строку
		txt=tmp.Right(len-min_len);
		txt.TrimLeft(); txt.TrimRight();
		txt.MakeUpper();
		if(txt==APL_T("ТУ"))
			min_len-=2;
		
		txt = tmp.Left(min_len);

		int br_pos = txt.Find(_T("\n"));
		if(tmp==txt && br_pos<0 && tmp.Left(n_len)==txt)
		{
			strs->Add(txt);
			return strs->GetSize();
		}
		int pos=min_len<br_pos?min_len:br_pos;
		if(br_pos>-1)
		{
			pos = br_pos;
			txt = txt.Left(pos+1);
		}
		else
		{
#ifndef GRPZ
			pos=FindRazelitInSTR(txt);
			if(pos>n_len)
				pos = FindRazelitInSTR(txt.Left(n_len));
#else
			int r_pos = txt.ReverseFind(_T('\\'));
			pos = r_pos;
			if(r_pos<0)
			{
				int b_pos = txt.ReverseFind(_T(' '));
				if(b_pos>-1)
				{
					pos = b_pos;
					if(b_pos>=4)//Это не гост
					{
						CString tstr4 = txt.Mid(b_pos-4,4);
						CString tstr3 = txt.Mid(b_pos-3,3);
						CString tstr2 = txt.Mid(b_pos-2,2);
						if(tstr4==APL_T("ГОСТ")) pos = b_pos - 4-1;
						else if(tstr3==APL_T("ОСТ")) pos = b_pos-3-1;
						else if(tstr2==APL_T("ТУ")) pos = b_pos-2-1;
					}
					else if(b_pos>=3)
					{
						CString tstr = txt.Mid(b_pos-3,3);
						if(tstr==_T("OCT")) pos = b_pos-3-1;
						else if(tstr.Right(2)==APL_T("ТУ")) pos = b_pos-2-1;
					}
					else if(b_pos>=2)
					{
						CString tstr = txt.Mid(b_pos-2,2);
						if(tstr==APL_T("ТУ")) pos = b_pos-2-1;
					}
					if(pos==0) pos = b_pos;
				}
				if(pos<=0)
				{
					int tpos;
					tpos = txt.ReverseFind(_T('.'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T('!'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T('?'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T(','));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T(':'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T(';'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T('-'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T('\\'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T('+'));
					pos = tpos > pos ? tpos : pos;
					tpos = txt.ReverseFind(_T('='));
					pos = tpos > pos ? tpos : pos;
				}
			}
#endif
		}
		if(pos>-1)
		{
			txt = txt.Left(pos+1);
			tmp = tmp.Right(tmp.GetLength()-txt.GetLength());
			if(txt.GetLength()>0)
			{
				if(txt[txt.GetLength()-1]==_T('\n') && tmp.IsEmpty())
				{
					txt.TrimRight(_T("\n"));
					strs->Add(txt);
					strs->Add(_T(""));
					return strs->GetSize();
				}
				else if(txt[txt.GetLength()-1]==_T(' '))
					txt = txt.Left(txt.GetLength()-1);
				else
				{
					if(pos==n_len)
						txt = txt.Left(n_len);
					txt.TrimRight(_T("\n"));
				}
			}
		}
		else
		{
			pos = txt.Left(n_len).GetLength()-1;
			txt.TrimRight(_T("\n"));
			tmp = tmp.Right(tmp.GetLength()-txt.GetLength());
		}
		strs->Add(txt);
	}
	int cnt = strs->GetSize();
	return cnt;
}

CTextValue::CTextValue()
{
	m_text_params = 0;
	m_val = NULL;
	m_inst=0;
	m_font_inst = NULL;
	m_type = NONE_VAL;
	m_align = AT_CENTER|AT_VCENTER;
	m_direction = HORIZ_TEXT,
	m_border_visible = TRUE;
	m_font.lfOutPrecision = OUT_DEFAULT_PRECIS;
	m_font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
	m_font.lfQuality = DEFAULT_QUALITY;
	m_font.lfPitchAndFamily = DEFAULT_PITCH;
	m_font.lfWidth = 0;
	m_font.lfOrientation = 0;
	m_font.lfStrikeOut = 0;
	m_font.lfItalic = 255;
	m_font.lfUnderline = 0;
	m_font.lfEscapement = 0;
	m_font.lfHeight = 100;
	m_font.lfWeight = FW_NORMAL;
	m_font.lfCharSet = RUSSIAN_CHARSET;
	m_space_para = aplSpacePara15;
	
	m_color = 0;

	_strcpy(m_font.lfFaceName,_T("Arial"));
}

CTextValue::~CTextValue()
{
}

CString CTextValue::GetText() const
{
	if(m_type == TEXT_VAL)
		return m_text;
	else if(m_type == INST_VAL && m_val!=NULL)
		return m_val->GetText();
	return _T("");
}

int CTextValue::GetType() const
{
	return m_type;
}

void CTextValue::CreateInst(CaplReportMgr* dict)
{
	ASSERT(dict);
	CaplReportMgr* m_ReportMgr = dict;
	CaplStepDataWithFile* m_data = dict->m_data;
	if(m_inst!=0) return;
	m_inst = m_data->CreateInstance(m_ReportMgr->e_value);
	m_font_inst = m_data->CreateInstance(m_ReportMgr->e_font);
	ASSERT(m_inst);
	ASSERT(m_font_inst);
	UpdateData(dict);
}

void CTextValue::UpdateData(CaplReportMgr* dict)
{
	ASSERT(dict);
	CaplReportMgr* m_ReportMgr = dict;
	CaplStepDataWithFile* m_data = dict->m_data;
	if(m_inst==0) 
	{
		CreateInst(dict);
	}
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_text,m_text);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_align,(int)m_align);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_border_state,m_border_visible);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_orient,(int)m_direction);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_space_para,(int)m_space_para);
	if(m_val && m_type==INST_VAL)
		m_data->PutAttr(m_inst,m_ReportMgr->a_val_inst,m_val->m_inst);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_type,m_type);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_font,m_font_inst);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_color, (int)m_color);
	m_data->PutAttr(m_inst,m_ReportMgr->a_val_text_params,m_text_params);
	m_ReportMgr->SetFontValue(m_font_inst,m_font);
}

CTextValue* CTextValue::CreateFromInst(CaplInstance *inst,CaplReportMgr* dict)
{
	ASSERT(dict);
	if(inst==0) return NULL;
	m_inst = inst;
	int tmp=0;
	dict->m_data->GetAttr(m_inst,dict->a_val_text,m_text);
	dict->m_data->GetAttr(m_inst,dict->a_val_align,tmp);
	m_align = tmp;
	dict->m_data->GetAttr(m_inst,dict->a_val_border_state,m_border_visible);
	dict->m_data->GetAttr(m_inst,dict->a_val_orient,tmp);
	m_direction = tmp;
	dict->m_data->GetAttr(m_inst,dict->a_val_space_para,tmp);
	m_space_para = tmp;
	dict->m_data->GetAttr(m_inst,dict->a_val_type,m_type);
	dict->m_data->GetAttr(m_inst,dict->a_val_font,m_font_inst);
	dict->m_data->GetAttr(m_inst,dict->a_val_color,tmp);
	m_color = (COLORREF)tmp;
	dict->m_data->GetAttr(m_inst,dict->a_val_text_params, m_text_params);
	m_font = dict->GetFontValue(m_font_inst);
	if(m_type==INST_VAL)
	{
		CaplInstance* tmp_inst;
		dict->m_data->GetAttr(m_inst,dict->a_val_inst,tmp_inst);
		if(tmp_inst!=0)
		{
			int ind = dict->m_data_source.m_params.Find(tmp_inst);
			if(ind<0)
			{
				dict->m_data->DeleteInstance(tmp_inst);
				tmp_inst = 0;
				dict->m_data->PutAttr(m_inst,dict->a_val_inst,tmp_inst);
			}
			else
				m_val = dict->m_data_source.m_params.GetAt(ind);
		}
	}
	return this;
}

void CReportElement::Update(bool set)
{
}

void CTextValue::SetText(CString str)
{
	m_type = TEXT_VAL;
	m_text = str;
	m_val = NULL;
}

void CTextValue::SetText(CReportParam *param)
{
	m_val = param;
	m_type = INST_VAL;
}

CReportParam* CTextValue::GetParam() const
{
	if(m_type==INST_VAL) return m_val;
	return NULL;
}

bool CTableMapElement::SelectTable()
{
	HINSTANCE hInst = AfxGetResourceHandle();
	AfxSetResourceHandle(dllInst);
	CSelectTableDlg dlg;
	dlg.m_ReportMgr = m_owner_sheet->m_ReportMgr;
	if(dlg.DoModal()==IDOK)
	{
		m_table = dlg.m_table;
		m_name = APL_T("Продолжение таблицы ")+m_table->m_name;
		AfxSetResourceHandle(hInst);
		return true;
	}
	AfxSetResourceHandle(hInst);
	if(m_table==NULL) return false;
	return false;		
}

void CTableMapElement::Update(bool set)
{
	if(m_table!=0)
		m_table->Update(set);
	if(set)
	{
		if(m_inst==0)
			m_inst = m_ReportMgr->m_data->CreateInstance(m_ReportMgr->e_report_map);
		m_ReportMgr->m_data->PutAttr(m_inst,m_ReportMgr->a_map_src,m_table->m_inst);
		
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_name,m_name);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_line_width,m_line_width);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_fixed,m_fixed);
		
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_textcolor, (int)m_color);
		m_ReportMgr->m_data->PutAttr(m_inst, m_ReportMgr->a_elem_backgroundcolor, (int)m_background_color);
		
		m_ReportMgr->PutPoint(m_inst,m_ReportMgr->a_elem_org_pt,m_org_pt);
		m_ReportMgr->PutPoint(m_inst,m_ReportMgr->a_elem_size,m_size);
	}
	else
	{
		if(m_inst==0)
		{
			TRACE(APL_T("Не прочитал продолжение таблицы\n"));
			return;
		}
		CaplInstance* tmp_inst=0;
		int tmp;
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_map_src,tmp_inst);
		//Поиcк таблицы на которую ссылается елеммент.
		m_table = m_owner_sheet->m_ReportMgr->FindTable(tmp_inst);
		if(m_table==NULL)
			m_owner_sheet->m_ReportMgr->m_non_create_table_maps.Add(this);

		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_name,m_name);
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_line_width,m_line_width);
		m_ReportMgr->m_data->GetAttr(m_inst,m_ReportMgr->a_elem_fixed,m_fixed);
		
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_textcolor, tmp);
		m_color = (COLORREF)tmp;
		m_ReportMgr->m_data->GetAttr(m_inst, m_ReportMgr->a_elem_backgroundcolor, tmp);
		m_background_color= (COLORREF)tmp;
		
		m_ReportMgr->GetPoint(m_inst,m_ReportMgr->a_elem_org_pt,m_org_pt);
		m_ReportMgr->GetPoint(m_inst,m_ReportMgr->a_elem_size,m_size);
	}
}

CReportElement* CReportElement::CreateClon()
{
	ASSERT(0);
	return NULL;
//	CReportElement* elem = new CReportElement(m_ReportMgr);
//	elem->m_org_pt = m_org_pt;
//	elem->m_name = m_name;
//	elem->m_size = m_size;
//	elem->m_type = m_type;
//	elem->m_fixed = m_fixed;
//	elem->m_line_width = m_line_width;
//	elem->m_value = m_value;
//	return elem;
}

CReportElement* CTableElement::CreateClon()
{
	CTableMapElement* tmap = new CTableMapElement(m_ReportMgr);
	tmap->m_org_pt = m_org_pt;
	tmap->m_name = APL_T("Продолжение ")+m_name;
	tmap->m_size = m_size;
	tmap->m_table = this;
	tmap->m_line_width = m_line_width;
	tmap->m_fixed = m_fixed;
	tmap->m_color = m_color;
	return tmap;
}

CReportElement* CTableMapElement::CreateClon()
{
	CTableMapElement* tmap = new CTableMapElement(m_ReportMgr);
	tmap->m_org_pt = m_org_pt;
	tmap->m_name = m_name;
	tmap->m_size = m_size;
	tmap->m_table = m_table;
	tmap->m_line_width = m_line_width;
	tmap->m_fixed = m_fixed;
	tmap->m_color = m_color;
	return tmap;
}

int CTableElement::GetRows()
{
	int cnt = 0;
	for(int i=0; i<m_sections.GetSize();i++)
	{
		CReportSection* sec = m_sections.GetAt(i);
		cnt+=sec->GetRows();
	}
	return cnt;
}

CTextValue& CTextValue::operator = (CTextValue val)
{
	m_type = val.GetType();
	m_font = val.m_font;
	m_direction = val.m_direction;
	m_align = val.m_align;
	m_text_params = val.m_text_params;
	m_border_visible = val.m_border_visible;
	m_color = val.m_color;
	m_space_para = val.m_space_para;
	if(val.GetType()==INST_VAL)
		SetText(val.GetParam());
	else 
		SetText(val.GetText());
	
	return *this;
}

CReportSheet* CTableElement::GenTable()
{
	int i;
	int row = 0;
	CReportElement* table=this;
	int flag = 0;
	int y_pos = 0;
	CString page_num = m_owner_sheet->m_name;
	page_num.TrimLeft(APL_T("Лист"));
	m_cur_page = _atoi(page_num);
	bool res = false;
	for(i=0; i<m_sections.GetSize();i++)
	{
		int rows = m_sections.GetAt(i)->GetRows();
		if(!((rows==3 && m_sections.GetAt(i)->m_show_empty_string_in_title>0) || (rows==1 && m_sections.GetAt(i)->m_show_empty_string_in_title==0)))
		{
			res = true;
			break;
		}
	}

	if(!res)
		return NULL;

	for(i=0; i<m_sections.GetSize();i++)
	{
		if(m_sections.GetSize()==i+1)
			flag = APL_SECTION_LINING_TO_END;
		table = m_sections.GetAt(i)->GenSection(table,row,y_pos,flag);
		if(table==NULL) return NULL;
	}
	return cur_sheet;
}

int CReportElement::GetMemSize()
{
	int int_size = sizeof(int);
	int dw_size = sizeof(DWORD);
	int size = 4*int_size;//размер элемента;
	size+=sizeof(TReportElementType);//тип элемента;
	size+=int_size;//толщина линии;
	size+=sizeof(COLORREF);//line_color;
	
	return size;
}	

void CReportElement::CopyToMem(BYTE *pByte, int &ind)
{
	int* pInt = NULL;
	int int_size = sizeof(int);
	
	pInt = (int*)&pByte[ind];
	*pInt = m_type;//записал тип элемента;
	ind+=sizeof(TReportElementType);
	
	pInt = (int*)&pByte[ind];
	*pInt = m_org_pt.x;//записал x;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_org_pt.y;//записал y;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_size.cx;//записал cx;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_size.cy;//записал cy;
	ind+=int_size;

	pInt = (int*)&pByte[ind];
	*pInt = m_line_width;//записал толщину линии;
	ind+=int_size;

	COLORREF *pCR = (COLORREF*)&pByte[ind];
	*pCR = m_color;//записал цвет линии;
	ind+=sizeof(COLORREF);
}

void CTableElement::CopyToMem(BYTE *pByte, int &ind)
{
	CReportElement::CopyToMem(pByte, ind);
	int* pInt = NULL;
	LOGFONT* lf = NULL;
	int int_size = sizeof(int);

	pInt = (int*)&pByte[ind];
	*pInt = m_row_height;
	ind+=int_size;

	lf = (LOGFONT*)&pByte[ind];
	*lf = m_row_lf;
	ind+=sizeof(LOGFONT);

	pInt = (int*)&pByte[ind];
	*pInt = m_sections.GetSize();
	ind+=int_size;
	for(int i=0; i<m_sections.GetSize();i++)
		m_sections.GetAt(i)->CopyToMem(pByte, ind);
}

int CTextValue::GetMemSize()
{
	int size=0;
	int int_size = sizeof(int);
	int dw_size = sizeof(DWORD);
	size+=int_size;//value_type;
	size+=dw_size;//выравнивание текста;
	size+=dw_size;//direction;
	size+=dw_size;//space_para;
	size+=int_size;//m_text_params;
	size+=int_size;//border_visible;
	size+=sizeof(COLORREF);//text_color;
	size+=sizeof(LOGFONT);//font;
	size+=int_size;//размер текста;
	size+=m_text.GetLength()*sizeof(TCHAR);//text;
	return size;
}

void CTextValue::CopyToMem(BYTE *pByte, int &ind)
{
	int* pInt = NULL;
	DWORD *pDw = NULL;
	int int_size = sizeof(int);
	int dw_size = sizeof(DWORD);
	TCHAR* pCh = NULL;
	
	pInt = (int*)&pByte[ind];
	*pInt = m_type;
	ind+=int_size;

	pDw = (DWORD*)&pByte[ind];
	*pInt = m_align;
	ind+=dw_size;

	pDw = (DWORD*)&pByte[ind];
	*pDw= m_direction;
	ind+=dw_size;

	pDw = (DWORD*)&pByte[ind];
	*pDw= m_space_para;
	ind+=dw_size;

	pInt = (int*)&pByte[ind];
	*pInt = m_text_params;
	ind+=int_size;

	pInt = (int*)&pByte[ind];
	*pInt = m_border_visible;
	ind+=int_size;

	COLORREF *pCR = (COLORREF*)&pByte[ind];
	*pCR = m_color;//записал цвет текста;
	ind+=sizeof(COLORREF);
	
	LOGFONT* lf = NULL;
	lf = (LOGFONT*)&pByte[ind];
	ind+=sizeof(LOGFONT);
	*lf = m_font;

	pInt = (int*)&pByte[ind];//запись текста;
	*pInt = m_text.GetLength();
	ind+=int_size;
	for(int i=0; i<m_text.GetLength();i++)
	{
		pCh = (TCHAR*)&pByte[ind];
		*pCh = m_text[i];
		ind+=sizeof(TCHAR);
	}

}

bool CReportElement::LoadDataFromMem(BYTE *pByte, int &ind)
{
	int* pInt = NULL;
	int int_size = sizeof(int);
	
	pInt = (int*)&pByte[ind];
	m_org_pt.x = *pInt;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	m_org_pt.y = *pInt;
	ind+=int_size;

	pInt = (int*)&pByte[ind];
	m_size.cx = *pInt;//записал cx;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	m_size.cy = *pInt;//записал cy;
	ind+=int_size;
	
	pInt = (int*)&pByte[ind];
	m_line_width = *pInt;//записал толщину линии;
	ind+=int_size;

	COLORREF *pCR = (COLORREF*)&pByte[ind];
	m_color = *pCR;//записал цвет линии;
	ind+=sizeof(COLORREF);

	return true;
}

bool CTextValue::LoadDataFromMem(BYTE *pByte, int &ind)
{
	int* pInt = NULL;
	DWORD *pDw = NULL;
	int int_size = sizeof(int);
	int dw_size = sizeof(DWORD);
	TCHAR* pCh = NULL;
	
	pInt = (int*)&pByte[ind];
	m_type = *pInt;
	ind+=int_size;

	pDw = (DWORD*)&pByte[ind];
	m_align = *pInt;
	ind+=dw_size;

	pDw = (DWORD*)&pByte[ind];
	m_direction = *pDw;
	ind+=dw_size;

	pDw = (DWORD*)&pByte[ind];
	m_space_para = *pDw;
	ind+=dw_size;

	pInt = (int*)&pByte[ind];
	m_text_params = *pInt;
	ind+=int_size;

	pInt = (int*)&pByte[ind];
	m_border_visible = *pInt;
	ind+=int_size;

	COLORREF *pCR = (COLORREF*)&pByte[ind];
	m_color = *pCR;//записал цвет текста;
	ind+=sizeof(COLORREF);

	LOGFONT* lf = NULL;
	lf = (LOGFONT*)&pByte[ind];
	ind+=sizeof(LOGFONT);
	m_font = *lf;

	pInt = (int*)&pByte[ind];//запись текста;
	int cnt = *pInt;
	ind+=int_size;
	m_text = _T("");
	for(int i=0; i<cnt;i++)
	{
		pCh = (TCHAR*)&pByte[ind];
		m_text+=*pCh;
		ind+=sizeof(TCHAR);
	}

	SetText(m_text);
	return true;
}

bool CTableElement::LoadDataFromMem(BYTE *pByte, int &ind)
{
	CReportElement::LoadDataFromMem(pByte, ind);
	int* pInt = NULL;
	LOGFONT* lf = NULL;
	int int_size = sizeof(int);

	pInt = (int*)&pByte[ind];
	m_row_height = *pInt;
	ind+=int_size;

	lf = (LOGFONT*)&pByte[ind];
	m_row_lf = *lf;
	ind+=sizeof(LOGFONT);

	pInt = (int*)&pByte[ind];
	int cnt = *pInt;
	ind+=int_size;
	m_sections.RemoveAll();
	for(int i=0; i<cnt;i++)
	{
		CReportSection* sec= new CReportSection(m_ReportMgr);
		sec->LoadDataFromMem(pByte, ind);
		m_sections.Add(sec);
	}
	return true;
}

void CReportElement::Align()
{
	double x,y;
	x = m_org_pt.x;
	y = m_org_pt.y;
	x=x/10;y=y/10;
	m_org_pt.x = (int)(x+0.5)*10;
	m_org_pt.y = (int)(y-0.5)*10;
	x = m_size.cx;
	y = m_size.cy;
	x=x/10;y=y/10;
	double dx,dy;
	dx = m_size.cx>0 ? 0.5 : -0.5;
	dy = m_size.cy>0 ? 0.5 : -0.5;
	m_size.cx = (int)(x+dx)*10;
	m_size.cy = (int)(y+dy)*10;
}

int CReportElement::ExecuteCmd(UINT cmd)
{
	if(cmd==0) return 0;
	switch(cmd) 
	{
	case ID_REPORTELEM_BACK : 
		{
		   if(m_owner_sheet==0) return 0;
		   int old_pos = -1;
		   int cnt = m_owner_sheet->m_els.GetSize();
		   for(int i=0; i<cnt;i++)
			   if(m_owner_sheet->m_els.GetAt(i)==this)
			   {
				   old_pos = i;
				   break;
			   }
			if(old_pos>-1)
			{
				m_owner_sheet->m_els.RemoveAt(old_pos);
				m_owner_sheet->m_els.InsertAt(0,this);
			}
		}
		break;
	case ID_REPORTELEM_FRONT : 
		{
		   if(m_owner_sheet==0) return 0;
		   int old_pos = -1;
		   int cnt = m_owner_sheet->m_els.GetSize();
		   for(int i=0; i<cnt;i++)
			   if(m_owner_sheet->m_els.GetAt(i)==this)
			   {
				   old_pos = i;
				   break;
			   }
			if(old_pos>-1)
			{
				m_owner_sheet->m_els.RemoveAt(old_pos);
				m_owner_sheet->m_els.Add(this);
			}
		}
		break;
	default: return cmd;
	}
	return 0;
}

void CTextValue::Delete(CaplReportMgr* dict)
{
	ASSERT(dict);		
	if(m_inst==NULL) return;
	dict->m_data->DeleteInstance(m_inst);
	dict->m_data->DeleteInstance(m_font_inst);
}

void CReportElement::Delete()
{
	CString buf;
	buf.Format(APL_T("Не реализована функция удаления элементов типа %s"), GetTypeName(m_type));
	TRACE_TO_FILE(buf);
}

void CReportElement::ConvertLOMETRICtoTEXT(CDC *pDC, CRect &rect)
{
	if(pDC==NULL) return;
	if(pDC->GetMapMode()==MM_TEXT) return;
	
	POINT *pt = new POINT[2];
	pt[0] = rect.TopLeft();
	pt[1] = rect.BottomRight();
	//Преобразование в TEXT 

	::LPtoDP(pDC->m_hDC, pt, 2);

	int dc = ::GetDeviceCaps(pDC->m_hDC, TECHNOLOGY);

	if(dc==DT_RASDISPLAY && !pDC->IsPrinting())
	{
		int mm = ::SetMapMode(pDC->m_hDC, MM_TEXT);
		::DPtoLP(pDC->m_hDC, pt, 2);
		::SetMapMode(pDC->m_hDC, mm);
	}

	//Смещение начала координат
	rect.left = pt[0].x;
	rect.right = pt[1].x;
	rect.top = pt[0].y;
	rect.bottom = pt[1].y;
	delete []pt;

	if(dc==DT_RASDISPLAY)
		rect.OffsetRect(pDC->GetViewportOrg());
}
