// CompareFoldersDlg.cpp : implementation file
//

#include "stdafx.h"
#include "CompareFoldersDlg.h"
#include "SSWhatDlg.h"

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

#define DISK_COLUMN 1
/////////////////////////////////////////////////////////////////////////////
// CCompareFoldersDlg dialog


CCompareFoldersDlg::CCompareFoldersDlg(CWnd* pParent /*=NULL*/)
	: CResizableDialog(CCompareFoldersDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CCompareFoldersDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_path = _T("");
	m_api = 0;
	m_folder = 0;
	m_folder_rec = false;
	m_dif_show = TRUE;
	m_disk_show = FALSE;
	m_psm_show = FALSE;
	m_doc_rec = TRUE;
}


void CCompareFoldersDlg::DoDataExchange(CDataExchange* pDX)
{
	CResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CCompareFoldersDlg)
	DDX_Control(pDX, IDC_SS_PRINT_DOCS, m_print);
	DDX_Control(pDX, IDC_STATIC_LEG, m_legenda);
	DDX_Control(pDX, IDC_UNDO_CHECKOUT, m_undo_btn);
	DDX_Control(pDX, IDC_REFRESH, m_refresh_btn);
	DDX_Control(pDX, IDC_ADDDOC, m_adddoc_btn);
	DDX_Control(pDX, IDC_GETLASTVER, m_lver_btn);
	DDX_Control(pDX, IDC_CHECKOUT, m_cout_btn);
	DDX_Control(pDX, IDC_CHECKIN, m_cin_btn);
	DDX_Control(pDX, IDOK, m_ok_btn);
	DDX_Control(pDX, IDC_SS_CFD_LISTPSM, m_psm_list);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CCompareFoldersDlg, CResizableDialog)
	//{{AFX_MSG_MAP(CCompareFoldersDlg)
	ON_WM_PAINT()
	ON_BN_CLICKED(IDC_CHECKOUT, OnCheckout)
	ON_BN_CLICKED(IDC_CHECKIN, OnCheckin)
	ON_BN_CLICKED(IDC_GETLASTVER, OnGetlastver)
	ON_BN_CLICKED(IDC_ADDDOC, OnAdddoc)
	ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_SS_CFD_LISTPSM, OnItemchangedSsCfdListpsm)
	ON_BN_CLICKED(IDC_UNDO_CHECKOUT, OnUndoCheckout)
	ON_WM_SIZE()
	ON_NOTIFY(NM_RCLICK, IDC_SS_CFD_LISTPSM, OnRclickSsCfdListpsm)
	ON_COMMAND(ID_SOURCESAFE_VIEW_FILE, OnSourcesafeView)
	ON_COMMAND(ID_SOURCESAFE_VIEW_DOC, OnSourcesafeViewDoc)
	ON_COMMAND(ID_SOURCESAFE_REFRESH, OnRefresh)
	ON_COMMAND(ID_SOURCESAFE_CHECKIN, OnCheckin)
	ON_COMMAND(ID_SOURCESAFE_SAVE, OnGetlastver)
	ON_COMMAND(ID_SOURCESAFE_UNDO_CHECKOUT, OnUndoCheckout)
	ON_COMMAND(ID_SOURCESAFE_LOAD, OnAdddoc)
	ON_BN_CLICKED(IDC_SS_PRINT_DOCS, OnSsPrintDocs)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCompareFoldersDlg message handlers

BOOL CCompareFoldersDlg::OnInitDialog() 
{
	CResizableDialog::OnInitDialog();
	ModifyStyleEx(0, WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT);   
	ModifyStyle(0, WS_MAXIMIZEBOX);   
	
	// TODO: Add extra initialization here
	if(m_api==0 || m_path==_T("") || m_folder==0)
	{
#ifdef _DEBUG
		AfxMessageBox( APL_T("Не заданы исходные данные!"));
#endif
		EndDialog(0);
		return FALSE;
	}
	m_ok_btn.SetIcon(GetAplStdIco16(APLSTDICO_OK));
	m_ok_btn.SetFlat(FALSE);


	AddAnchor(IDC_SS_CFD_LISTPSM,TOP_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDOK,BOTTOM_RIGHT);
	AddAnchor(IDC_STATIC_LEG,TOP_LEFT,TOP_RIGHT);

	CImageList il;
	il.Create(IDR_NAVIGATOR_ICON,20,20,RGB(255,0,255));
	TCHAR dir[255]=_T("");
	::GetSystemDirectory(dir,255);
	CString dt = dir;
	HICON hIcon1, hIcon2;
	::ExtractIconEx( dt+_T("\\shell32.dll"), 0, &hIcon1, &hIcon2, 1);
	CImageList img;
	img.Create(16,16,ILC_MASK|ILC_COLOR32,0,2);
	img.Add(hIcon2);
	::ExtractIconEx( dt+_T("\\shell32.dll"), 4, &hIcon1, &hIcon2, 1);
	img.Add(hIcon2);
	img.Add(il.ExtractIcon(6));
	img.Add(il.ExtractIcon(7));
	m_psm_list.SetImageList(&img,LVS_SMALLICON,DISK_COLUMN);
	img.DeleteImageList();
	
	m_lver_btn.SetIcon(GetAplCheckIco(APL_ICON_SAVE, true));
	m_lver_btn.SetTooltipText( APL_T("Взять последнюю версию"));
	m_adddoc_btn.SetIcon(GetAplCheckIco(APL_ICON_LOAD, true));
	m_adddoc_btn.SetTooltipText( APL_T("Добавить документ в БД"));
	m_cin_btn.SetIcon(GetAplCheckIco(APL_ICON_CHECKIN,true));
	m_cin_btn.SetTooltipText( APL_T("Завершить редактирование"));
	m_cout_btn.SetIcon(GetAplCheckIco(APL_ICON_CHECKOUT,true));
	m_cout_btn.SetTooltipText( APL_T("Взять документ на редактирование"));
	m_refresh_btn.SetIcon(GetAplCheckIco(APL_ICON_REFRESH, true));
	m_refresh_btn.SetTooltipText( APL_T("Обновить"));
	m_undo_btn.SetIcon(GetAplCheckIco(APL_ICON_UNDOCHECKOUT,true));
	m_undo_btn.SetTooltipText( APL_T("Отменить редактирование"));
	m_print.SetIcon(GetAplTableIco(56));
	m_print.SetFlat(FALSE);
	m_print.SetTooltipText( APL_T("Печать"));

	m_undo_btn.SetFlat(FALSE);
	m_cin_btn.SetFlat(FALSE);
	m_cout_btn.SetFlat(FALSE);
	m_refresh_btn.SetFlat(FALSE);
	m_adddoc_btn.SetFlat(FALSE);
	m_lver_btn.SetFlat(FALSE);

	CRect r;
	m_psm_list.GetClientRect(r);
	r.right-=4;
	m_psm_list.ModifyStyle(0,LVS_OWNERDRAWFIXED);
	m_psm_list.InsertColumn(0, APL_T("Документ на диске"),LVCFMT_LEFT,r.Width()/2);
	m_psm_list.InsertColumn(0, APL_T("Документ в БД"),LVCFMT_LEFT,r.Width()/2-60);
	m_psm_list.InsertColumn(2, APL_T("Размер"),LVCFMT_LEFT,60);
	m_psm_list.SetColor(RGB(250,0,0),LCC_RED);
	m_psm_list.SetColor(RGB(200,200,200),LCC_DARK);
	m_psm_list.SetColor(RGB(0,150,0),LCC_GREEN);
	m_psm_list.SetColor(RGB(0,0,150),LCC_BLUE);
	m_psm_list.SetLevelCX(10);
	LoadDirectory(m_folder,m_path);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CCompareFoldersDlg::LoadDirectory(CaplInstance *folder, CString path, int level)
{
	long dw;
	if(folder==m_folder) 
	{
		dw = aplStartWaitDlg( APL_T("Чтение данных."));
		m_psm_list.SetRedraw(FALSE);
		m_psm_list.DeleteAllItems();
		CItem *item = new CItem;
		item->m_inst = folder;
		item->path = path;
		item->img1 = item->img2 = 1;
		item->m_folder = 0;
		CString fname=_T("");
		m_api->m_data.GetAttr(folder,m_api->m_folder_mgr.a_folder_name,fname);
		m_psm_list.InsertItem(0,fname,1);
		m_psm_list.SetItemText(0,1,path);
		m_psm_list.SetItemData(0,(DWORD)item);
	}
	if(folder==0) return;
	CString fname=_T("");
	if(folder) m_api->m_data.GetAttr(folder,m_api->m_folder_mgr.a_folder_name,fname);
	TCHAR dir[1024];
	GetCurrentDirectory(1024,dir);
	if(!SetCurrentDirectory(path))
	{
		return;
	};
	CStringArray files;
	FindFiles(path+_T("*.*"),0,&files);//поиск файлов
	CString t = _T("");
	t+=dir;
	aplExtent ext;
	GetDocs(folder,ext);
	CItem *item;
	while(files.GetSize()>0 || ext.Size>0)
	{
		CString namefile, namedoc;
		if(ext.Size>0)
		{
			item = new CItem;
			item->level1 = level;
			item->level2 = level;
			int crc_doc=0, crc_file=0;
			CaplInstance *active;
			m_api->m_data.GetAttr(ext[0],m_api->m_doc_mgr.a_apl_doc_active,active);
			m_api->m_data.GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_crc,crc_doc);
			namedoc = GetDocFileName(ext[0]);
			item->path = path+namedoc;

			int cnt_files = files.GetSize();
			int ind = -1;
			for(int i=0; i<cnt_files;i++)
				if(files.GetAt(i)==namedoc) 
				{
					ind = i;
					files.RemoveAt(i);
					break;
				}
			item->m_inst = ext[0];
			item->m_folder = folder;
			if(ind<0) 
			{
				namefile = _T("");
				item->img2 = -1;
			}
			else 
			{
				namefile = namedoc;
				crc_file = ::GetFileCRC32(path+namefile);
				item->img2 = 0;
				CFileStatus fs;
				CFile::GetStatus(path+namefile,fs);
				item->fsize = fs.m_size;
			}
			if(crc_doc!=crc_file && crc_file!=0) 
				item->color = 1;
			else if(ind<0)
				item->color = 3;
			item->img1 = 2;
			m_api->m_data.GetAttr(ext[0],m_api->m_doc_mgr.a_apl_doc_lock,active);
			if(active)
				item->img1 = 3;
			if((m_dif_show && crc_doc!=crc_file && crc_file!=0) || (m_psm_show && ind<0) || (m_compare_show && crc_file == crc_doc))
			{
				int i = m_psm_list.InsertItem(m_psm_list.GetItemCount(),namedoc,0);
				m_psm_list.SetItemText(i,DISK_COLUMN,namefile);
				m_psm_list.SetItemData(i,(DWORD)item);
				CString size;
				size.Format(_T("%d"),item->fsize);
				m_psm_list.SetItemText(i,2,size);
			}
			else
			{
				delete item;
			}
			RecCompareDocs(ext[0],&files,level+1, level,path,folder);
			ext.Remove(0);
		}
		else if(files.GetSize()>0)
		{
			if(!m_disk_show)
			{
				files.RemoveAll();
				continue;
			}
			namefile = files.GetAt(0);
			files.RemoveAt(0);
			CFileStatus fs;
			if(!CFile::GetStatus(path+namefile,fs)) continue;
			int i = m_psm_list.InsertItem(m_psm_list.GetItemCount(),_T(""),0);
			m_psm_list.SetItemText(i,DISK_COLUMN,namefile);
			TRACE(APL_T("Добавлен документ на диске: ")+namefile+_T("\n"));
			item = new CItem;
			item->level1 = level;
			item->level2 = level;
			item->m_inst = 0;
			item->path = path+namefile;
			item->img2 = 0;
			item->img1 = -1;
			item->color = 2;
			item->m_folder = folder;
			item->fsize = fs.m_size;
			m_psm_list.SetItemData(i,(DWORD)item);
			CString size;
			size.Format(_T("%d"),item->fsize);
			m_psm_list.SetItemText(i,2,size);
		}
	}
	{
		FindFiles(path+_T("*"),1,&files);
		aplExtent ext;
		m_api->m_folder_mgr.GetAllSubFolder(folder,ext);
		while(files.GetSize()>0 || ext.Size>0)
		{
			if(ext.Size>0)
			{
				CString fname, dname;
				m_api->m_data.GetAttr(ext[0],m_api->m_folder_mgr.a_folder_name, fname);

				int ind = -1;
				int cnt_files = files.GetSize();
				for(int i=0; i<cnt_files;i++)
					if(files.GetAt(i)==fname)
					{
						ind = i;
						files.RemoveAt(i);
						break;
					}
				if(ind<0 && m_psm_show!=TRUE) 
				{
					ext.Remove(0);
					continue;
				}
				item = new CItem;
				item->img1 = -1;
				item->color = 3;
				if(ind<0) dname=_T("");
				else
				{
					dname = path+fname+_T("\\");
					item->img2 = 1;
					item->color = 0;
				}
				item->level1 = level;
				item->level2 = level;
				item->m_inst = ext[0];
				item->path = dname;
				item->img1 = 1;
				item->m_folder = folder;
				m_psm_list.InsertItem(m_psm_list.GetItemCount(),fname,1);
				m_psm_list.SetItemText(m_psm_list.GetItemCount()-1,DISK_COLUMN,dname);
				m_psm_list.SetItemData(m_psm_list.GetItemCount()-1,(DWORD)item);
				if(m_folder_rec) LoadDirectory(ext[0],dname,level+1);
				ext.Remove(0);
			}
			else if(files.GetSize()>0)
			{
				if(!m_disk_show)
				{
					files.RemoveAll();
					continue;
				}
				CString str = files.GetAt(0);
				files.RemoveAt(0);
				CItem *item = new CItem;
				item->level1 = level;
				item->level2 = level;
				item->path = path;
				item->m_folder = folder;
				item->img1 = -1;
				item->img2 = 1;
				item->color = 2;
				item->path = path+str+_T("\\");
				m_psm_list.InsertItem(m_psm_list.GetItemCount(),_T(""),1);
				m_psm_list.SetItemText(m_psm_list.GetItemCount()-1,DISK_COLUMN,path+str+_T("\\"));
				m_psm_list.SetItemData(m_psm_list.GetItemCount()-1,(DWORD)item);
				if(m_folder_rec) LoadDirectory(0,path+str+_T("\\"),level+1);
			}
		}
	}
	SetCurrentDirectory(t);
	if(folder==m_folder) 
	{
		aplEndWaitDlg(dw);
		m_psm_list.SetRedraw(TRUE);
	}
	return;
}

void CCompareFoldersDlg::GetDocs(CaplInstance *inst, aplExtent &docs)
{
	if(inst==0) return;
	if(m_api->m_data.IsKindOf(inst,m_api->m_folder_mgr.e_folder))
	{
		aplExtent ext;
		m_api->m_folder_mgr.GetFolderContents(inst,ext);
		for(int i=0;i<ext.Size;i++)
			if(m_api->m_data.IsKindOf(ext[i],m_api->m_doc_mgr.e_doc))
			{
				docs.Add(ext[i]);
//				if(m_doc_rec)GetDocs(ext[i],docs);
			}
	}
	else if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc))
	{
		aplExtent ext, rel;
		m_api->m_doc_mgr.FindAssociatedDocuments(inst,ext,rel);
		for(int i=0;i<ext.Size;i++)
			if(m_api->m_data.IsKindOf(ext[i],m_api->m_doc_mgr.e_doc))
			{
				docs.Add(ext[i]);
				if(m_doc_rec) GetDocs(ext[i],docs);
			}
	}
}


void CCompareFoldersDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

	}
	else
	{
		CPaintDC dc(this);
		CRect clrect, r;
		m_legenda.GetWindowRect(clrect);
		ScreenToClient(clrect);
		COLORREF tcolor = dc.SetTextColor(RGB(0,0,150));
		CFont *font = dc.SelectObject(GetFont());
		int mm = dc.SetBkMode(TRANSPARENT);
		clrect.left+=5;
		
		int width = dc.GetTextExtent( APL_T("Существуют только в БД")).cx + dc.GetTextExtent( APL_T("Существуют на только диске")).cx + dc.GetTextExtent( APL_T("Только отличающиеся")).cx+10;
		if(clrect.Width()<width+10)
		{
			dc.TextOut(clrect.left,clrect.top+13, APL_T("Существуют только в БД"));
			CSize txt = dc.GetTextExtent( APL_T("Существуют только в БД"));
			dc.SetTextColor(RGB(0,150,0));
			dc.TextOut(clrect.left,clrect.top+13+txt.cy, APL_T("Существуют только на диске"));
			txt = dc.GetTextExtent( APL_T("Существуют только на диске"));
			clrect.left+=txt.cx+10;
			dc.SetTextColor(RGB(250,0,0));
			dc.TextOut(clrect.left,clrect.top+13, APL_T("Отличающиеся"));
			txt = dc.GetTextExtent( APL_T("Отличающиеся"));
		}
		else
		{
			dc.TextOut(clrect.left,clrect.top+13, APL_T("Существуют только в БД"));
			CSize txt = dc.GetTextExtent( APL_T("Существуют только в БД"));
			clrect.left+=txt.cx+5;
			dc.SetTextColor(RGB(250,0,0));
			dc.TextOut(clrect.left,clrect.top+13, APL_T("Отличающиеся"));
			dc.SetTextColor(RGB(0,150,0));
			txt = dc.GetTextExtent( APL_T("Отличающиеся"));
			dc.TextOut(clrect.left+txt.cx+5,clrect.top+13, APL_T("Существуют только на диске"));
		}
		
		dc.SetBkMode(mm);
		dc.SelectObject(font);
		dc.SetTextColor(tcolor);
		CResizableDialog::OnPaint();
	}
}

void CCompareFoldersDlg::OnCheckout() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = (CItem*)m_psm_list.GetItemData(cur);
	if(item)
	{
		if(item->m_inst==0) return;
		if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_folder_mgr.e_folder))
		{
			if(m_api->m_folder_mgr.CopyDocOnDisk(item->m_inst,item->path,true))
				LoadDirectory(m_folder,m_path);
		}
		else if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc))
		{
			m_api->m_folder_mgr.CreateFolderOndisk(item->path);
			if(m_api->m_doc_mgr.CheckOutEx(item->m_inst,item->path,false,false))
			{
				AfxMessageBox( APL_T("Документ взят на редактирование!"));
				TRACE( APL_T("Документ ")+GetDocFileName(item->m_inst)+ APL_T(" взят на редактирование\n"));
				LoadDirectory(m_folder,m_path);
			}
			if(item->img1==2) item->img1 = 3;
			m_psm_list.RedrawItems(cur-1,cur+1);
		}
	}
}

void CCompareFoldersDlg::OnCheckin() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = (CItem*)m_psm_list.GetItemData(cur);
	if(item)
	{
		if(item->m_inst==0) return;
		if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_folder_mgr.e_folder))
		{
			if(m_api->m_folder_mgr.CheckInAllDocs(item->m_inst, item->path))
				LoadDirectory(m_folder,m_path);
		}
		else if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc))
		{
			bool bOldMI = m_api->m_ModeInteractive;
			m_api->m_ModeInteractive = false;
			if(m_api->m_doc_mgr.CheckInEx(item->m_inst,item->path,true,true,false))
			{
				AfxMessageBox( APL_T("Редактирование документа завершено!"));
				if(item->img1==3) item->img1 = 2;
				m_psm_list.RedrawItems(cur,cur);
	//			TRACE0("Редактирование документа "+GetDocFileName(item->m_inst)+" завершено\n");
				LoadDirectory(m_folder,m_path);
			}
			m_api->m_ModeInteractive = bOldMI;
		}
	}
}

void CCompareFoldersDlg::OnGetlastver() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = (CItem*)m_psm_list.GetItemData(cur);
	if(item)
	{
		if(item->m_inst==0) return;
		if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_folder_mgr.e_folder))
		{
			if(item->path==_T(""))
				if(item->m_folder!=0)
				{
					CItem* titem = FindItem(item->m_folder);
					if(titem) 
					{
						CString name;
						m_api->m_data.GetAttr(item->m_inst,m_api->m_folder_mgr.a_folder_name, name);
						item->path = titem->path+name+_T("\\");
						m_api->m_folder_mgr.CreateFolderOndisk(item->path);
					}
				}
			if(m_api->m_folder_mgr.CopyDocOnDisk(item->m_inst,item->path))
				LoadDirectory(m_folder,m_path);
		}
		else if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc))
		{
			m_api->m_folder_mgr.CreateFolderOndisk(item->path);
			CaplInstance *active, *af;
			CaplAttr *source=0;
			m_api->m_data.GetAttr(item->m_inst,m_api->m_doc_mgr.a_apl_doc_active,active);
			m_api->m_doc_mgr.LogDocAccess(active,_T("CCompareFoldersDlg"),item->path);
			m_api->m_data.GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,af);
			if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_stored_document))
				source = m_api->m_doc_mgr.a_apl_stored_document_source;
			else if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_assigned_document))
				source = m_api->m_doc_mgr.a_apl_assigned_document_location_path;
			if(!m_api->m_data.NET_LoadBlob(af,source,item->path))
			{
				TRACE( APL_T("Ошибка создания файла")+item->path+GetDocFileName(item->m_inst)+_T("\n"));
				AfxMessageBox( APL_T("Не могу создать файл!"));
				return;
			}
			else
			{
				TRACE( APL_T("Взяли последнюю версию документа БД ")+GetDocFileName(item->m_inst)+_T("->")+item->path+GetDocFileName(item->m_inst)+_T("\n"));
				m_api->m_folder_mgr.RecursiveCopyDocs(item->m_inst,item->path);
				LoadDirectory(m_folder,m_path);
			}
		}
	}
	m_psm_list.EnsureVisible(cur,TRUE);
	m_psm_list.SelCur(cur);
}

void CCompareFoldersDlg::OnAdddoc() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = (CItem*)m_psm_list.GetItemData(cur);
	if(item)
	{
		if(item->m_inst==0)//Файл не сужествует.
		{
			if(item->m_folder==0) return;

			CString str = m_psm_list.GetItemText(cur,1);
			if(str.Find(_T("\\"))>-1) //Папка
			{
				str = str.Left(str.GetLength()-1);
				CString name = str.Right(str.GetLength()-str.ReverseFind(_T('\\'))-1);
				CaplInstance *folder = m_api->m_folder_mgr.CreateFolder(item->m_folder,name,_T(""));
				if(folder==0) return;
				item->m_inst = folder;
				m_api->m_folder_mgr.AddDocPath(folder,str+_T("\\"),true);
				TRACE( APL_T("Добавлена папка в БД: ")+str+_T("\\\n"));
			}
			else//Документ
			{
				CString id;
				id = str.Left(str.ReverseFind(_T('.')));
				CaplInstance *old = m_api->m_doc_mgr.FindDocById(id);
				CaplInstance *inst = 0;
				if(old!=0)
				{
					if(old->GetAccessmode()>=aplRO) return;
					bool lock = true;
					CaplInstance *locker=0;
					m_api->m_data.GetAttr(old,m_api->m_doc_mgr.a_apl_doc_lock,locker);
					if(locker!=0)
					{
						CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
						aplExtent ext;
						CString name=_T("");
						if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,name);
						if(pers) name+=_T(" (");
						name+= m_api->m_data.GetNameCurrUser();
						if(pers) name+=_T(")");
						
						CString username;
						m_api->m_data.GetAttr(locker,m_api->m_doc_mgr.a_apl_doc_rev_user,username);
						if(username!=name) lock = false;
					}
					else lock= false;
					CSSWhatDlg wdlg;
					wdlg.m_api = m_api;
					wdlg.m_doc_db = old;
					wdlg.m_lock = !lock;
					wdlg.m_doc = item->path;
					BOOL res = 0;
					res = wdlg.DoModal();
					if(res==IDCANCEL)
						return;
					if(wdlg.m_what==1)
					{
						m_api->m_doc_mgr.CheckInEx(old,item->path,(wdlg.m_acver==TRUE),false, true);
							TRACE( APL_T("Создана новая версия документа\n"));
					}
					else if(wdlg.m_what==2)
					{
						inst = m_api->m_doc_mgr.CreateDocument(id,str,_T(""),0,item->path,true);
						if(inst==NULL)
						{
							TRACE( APL_T("Документ ")+item->path+ APL_T(" пропущен\n"));
							return;
						}
					}
					else 
					{
						TRACE( APL_T("Документ ")+item->path+ APL_T(" пропущен\n"));
						return;
					}
				}
				else
					inst = m_api->m_doc_mgr.CreateDocument(id,str,_T(""),0,item->path);
				if(inst==0) 
				{
					AfxMessageBox( APL_T("Не могу создать документ."));
					return;
				}
				m_api->m_folder_mgr.AddToFolder(item->m_folder,inst);
				TRACE( APL_T("Добавлен документ в БД. Обозначение: ")+id+ APL_T(" Наименование: ")+str+ APL_T(" Файл: ")+item->path+_T("\\\n"));
			}
			LoadDirectory(m_folder,m_path);
		}
		else
		{
			if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_folder_mgr.e_folder))
			{
				m_api->m_folder_mgr.AddDocPath(item->m_inst,item->path,true);
			}
		}
	}
	m_psm_list.EnsureVisible(cur,TRUE);
	m_psm_list.SelCur(cur);
}

void CCompareFoldersDlg::OnRefresh() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	LoadDirectory(m_folder, m_path);
	m_psm_list.EnsureVisible(cur,TRUE);
	m_psm_list.SelCur(cur);
}


CString CCompareFoldersDlg::GetDocFileName(CaplInstance *inst)
{
	if(inst==0) return _T("");
	if(!m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc)) return _T("");

	CaplInstance *active, *af;
	m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_active,active);
	m_api->m_data.GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,af);
	CaplAttr *source = 0;
	CString fname, str;
	if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_stored_document))
		m_api->m_data.GetAttr(af,m_api->m_doc_mgr.a_apl_stored_document_file_name,str);
	else if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_assigned_document))
		m_api->m_data.GetAttr(af,m_api->m_doc_mgr.a_apl_assigned_document_location_path,str);
	if(str.ReverseFind(_T('.'))>-1) str = str.Right(str.GetLength()-str.ReverseFind(_T('.')));
	else str=_T("");
	m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_doc_id,fname);
	for(int i=0;i<fname.GetLength();i++){
		if(fname[i]==_T('"'))fname.SetAt(i,_T('\''));
		else if(fname[i]==_T('\\') || fname[i]==_T('/'))fname.SetAt(i,_T(' '));
	}
	return fname+str;
}

BOOL CCompareFoldersDlg::DestroyWindow() 
{
	m_psm_list.DeleteAllItems();
	
	return CResizableDialog::DestroyWindow();
}

void CCompareFoldersDlg::OnItemchangedSsCfdListpsm(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur>-1)
	{
		CItem *item = (CItem*)m_psm_list.GetItemData(cur);
		if(item->m_inst==0)
		{
			m_lver_btn.EnableWindow(FALSE);
			m_cin_btn.EnableWindow(FALSE);
			m_cout_btn.EnableWindow(FALSE);
			m_undo_btn.EnableWindow(FALSE);
		}
		else
		{
			m_lver_btn.EnableWindow(TRUE);
			m_cin_btn.EnableWindow(TRUE);
			m_cout_btn.EnableWindow(TRUE);
			m_undo_btn.EnableWindow(TRUE);
			if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc))
			{
				CaplInstance *lock;
				m_api->m_data.GetAttr(item->m_inst,m_api->m_doc_mgr.a_apl_doc_lock,lock);
				if(lock)
					m_cout_btn.EnableWindow(FALSE);
				else
				{
					m_cin_btn.EnableWindow(FALSE);
					m_undo_btn.EnableWindow(FALSE);
				}
			}
		}
		if(m_psm_list.GetItemText(cur,1)==_T(""))
			m_adddoc_btn.EnableWindow(FALSE);
		else
			m_adddoc_btn.EnableWindow(TRUE);
	}
	
	*pResult = 0;
}

CString CCompareFoldersDlg::GetDocFileName(CaplInstance *inst, CaplAPI *m_api)
{
	if(0==inst) return _T("");
	CaplInstance *active=0, *af;
	if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_doc)) 
	{
		m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_active,active);
	}
	else if(m_api->m_data.IsKindOf(inst,m_api->m_doc_mgr.e_apl_doc_rev)	)
	{
		active=inst;
		m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_rev_doc,inst);
	}


	if(0==active)return _T("");

	m_api->m_data.GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,af);
	if(af==0)return _T("");
	CaplAttr *source = 0;
	CString fname, str;
	if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_stored_document))
		m_api->m_data.GetAttr(af,m_api->m_doc_mgr.a_apl_stored_document_file_name,str);
	else if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_assigned_document))
		m_api->m_data.GetAttr(af,m_api->m_doc_mgr.a_apl_assigned_document_location_path,str);
	if(str.ReverseFind(_T('.'))>-1) str = str.Right(str.GetLength()-str.ReverseFind(_T('.')));
	else str=_T("");
	m_api->m_data.GetAttr(inst,m_api->m_doc_mgr.a_doc_id,fname);
	for(int i=0;i<fname.GetLength();i++){
		if(fname[i]==_T('"'))fname.SetAt(i,_T('\''));
		else if(fname[i]==_T('\\') || fname[i]==_T('/'))fname.SetAt(i,_T(' '));
	}
	return fname+str;
}

CItem* CCompareFoldersDlg::FindItem(CaplInstance *inst)
{
	if(inst==0) return NULL;
	int cnt = m_psm_list.GetItemCount();
	for(int i=0;i<cnt;i++)
	{
		CItem *item = (CItem*)m_psm_list.GetItemData(i);
		if(item)
			if(item->m_inst==inst) return item;
	}
	return NULL;
}

void CCompareFoldersDlg::OnUndoCheckout() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = (CItem*)m_psm_list.GetItemData(cur);
	if(item)
	{
		if(item->m_inst==0) return;
		if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_folder_mgr.e_folder))
		{
			if(m_api->m_folder_mgr.UndoCheckOut(item->m_inst))
				LoadDirectory(m_folder,m_path);
		}
		else if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc))
		if(m_api->m_doc_mgr.UndoCheckOutEx(item->m_inst,false))
		{
			if(item->img1==3) item->img1 = 2;
			m_psm_list.RedrawItems(cur,cur);
			TRACE( APL_T("Редактирование документа ")+item->path+GetDocFileName(item->m_inst)+ APL_T(" отменено\n"));
			LoadDirectory(m_folder,m_path);
		}
	}
}

void CCompareFoldersDlg::OnSize(UINT nType, int cx, int cy) 
{
	CResizableDialog::OnSize(nType, cx, cy);
	if(m_psm_list)
		if(m_psm_list.IsWindowVisible())
	{
		CRect r;
		m_psm_list.GetWindowRect(r);
		m_psm_list.SetColumnWidth(0,(r.Width()-4)/2);
		m_psm_list.SetColumnWidth(1,(r.Width()-4)/2-65);
	}
}

int CCompareFoldersDlg::RecCompareDocs(CaplInstance *doc, CStringArray *files, int level, int oldlevel, CString path, CaplInstance *folder)
{
	aplExtent ext, rel;
	m_api->m_doc_mgr.FindAssociatedDocuments(doc,ext,rel);
	CItem *item;
	CString namedoc, namefile;
	while(ext.Size>0)
	{
		item = new CItem;
		item->level1 = level;
		item->level2 = oldlevel;
		int crc_doc=0, crc_file=0;
		CaplInstance *active;
		m_api->m_data.GetAttr(ext[0],m_api->m_doc_mgr.a_apl_doc_active,active);
		m_api->m_data.GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_crc,crc_doc);
		namedoc = GetDocFileName(ext[0]);
		
		int ind = -1;
		for(int i=0;i<files->GetSize();i++)
			if(files->GetAt(i)==namedoc)
			{
				ind = i;
				files->RemoveAt(i);
				break;
			}
		item->m_inst = ext[0];
		item->m_folder = folder;
		if(ind<0) 
		{
			namefile = _T("");
			item->img2 = -1;
		}
		else 
		{
			namefile = namedoc;
			crc_file = ::GetFileCRC32(path+namefile);
			item->img2 = 0;
			CFileStatus fs;
			CFile::GetStatus(path+namefile,fs);
			item->fsize = fs.m_size;
		}
		item->path = path+namefile;
		if(crc_doc!=crc_file && crc_file!=0) 
			item->color = 1;
		else if(ind<0)
			item->color = 3;
		item->img1 = 2;
		m_api->m_data.GetAttr(ext[0],m_api->m_doc_mgr.a_apl_doc_lock,active);
		if(active)
			item->img1 = 3;
		if((m_dif_show && crc_doc!=crc_file && crc_file!=0) || (m_psm_show && ind<0) || (m_compare_show && crc_file == crc_doc))
		{
			int i = m_psm_list.InsertItem(m_psm_list.GetItemCount(),namedoc,0);
			m_psm_list.SetItemText(i,DISK_COLUMN,namefile);
			m_psm_list.SetItemData(i,(DWORD)item);
			CString size;
			size.Format(_T("%d"),item->fsize);
			m_psm_list.SetItemText(i,2,size);
		}
		else
		{
			delete item;
		}
		RecCompareDocs(ext[0],files,level+1,oldlevel,path,folder);
		ext.Remove(0);
	}
	return true;
}

void CCompareFoldersDlg::OnRclickSsCfdListpsm(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	NMITEMACTIVATE *ia = (NMITEMACTIVATE*)pNMHDR;
	CMenu menu;
	CMenu *pPopup;
	VERIFY(menu.LoadMenu(IDR_CONTEXT_MENU));
	pPopup = menu.GetSubMenu(6);
	if(ia->ptAction.x<m_psm_list.GetColumnWidth(0))
		pPopup->DeleteMenu(ID_SOURCESAFE_VIEW_FILE,MF_BYCOMMAND);
	else
		pPopup->DeleteMenu(ID_SOURCESAFE_VIEW_DOC,MF_BYCOMMAND);
	m_psm_list.ClientToScreen(&ia->ptAction);
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0 || cur>m_psm_list.GetItemCount()-1) return;
	m_psm_list.SetItemState(cur,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
	CItem *item = m_psm_list.GetItemData(cur);

	if(item->m_inst==0)
	{
		pPopup->EnableMenuItem(ID_SOURCESAFE_SAVE,MF_BYCOMMAND|MF_GRAYED);
		pPopup->EnableMenuItem(IDC_CHECKOUT,MF_BYCOMMAND|MF_GRAYED);
		pPopup->EnableMenuItem(ID_SOURCESAFE_CHECKIN,MF_BYCOMMAND|MF_GRAYED);
		pPopup->EnableMenuItem(ID_SOURCESAFE_UNDO_CHECKOUT,MF_BYCOMMAND|MF_GRAYED);
		if(item->path==_T("") || item->path.Right(1)==_T("\\")) pPopup->EnableMenuItem(ID_SOURCESAFE_VIEW_FILE,MF_BYCOMMAND|MF_GRAYED);
		pPopup->EnableMenuItem(ID_SOURCESAFE_VIEW_DOC,MF_BYCOMMAND|MF_GRAYED);
	}
	else
	{
		if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc))
		{
			CaplInstance *lock;
			m_api->m_data.GetAttr(item->m_inst,m_api->m_doc_mgr.a_apl_doc_lock,lock);
			if(lock)
				pPopup->EnableMenuItem(IDC_CHECKOUT,MF_BYCOMMAND|MF_GRAYED);
			else
			{
				pPopup->EnableMenuItem(ID_SOURCESAFE_CHECKIN,MF_BYCOMMAND|MF_GRAYED);
				pPopup->EnableMenuItem(ID_SOURCESAFE_UNDO_CHECKOUT,MF_BYCOMMAND|MF_GRAYED);
			}
			if(item->path==_T("") || item->path.Right(1)==_T("\\")) pPopup->EnableMenuItem(ID_SOURCESAFE_VIEW_FILE,MF_BYCOMMAND|MF_GRAYED);
		}
		else
		{
			if(item->path==_T("") || item->path.Right(1)==_T("\\")) pPopup->EnableMenuItem(ID_SOURCESAFE_VIEW_FILE,MF_BYCOMMAND|MF_GRAYED);
			pPopup->EnableMenuItem(ID_SOURCESAFE_VIEW_DOC,MF_BYCOMMAND|MF_GRAYED);
		}
	}

	pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,ia->ptAction.x,ia->ptAction.y,this);

	*pResult = 0;
}

void CCompareFoldersDlg::OnSourcesafeView() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = m_psm_list.GetItemData(cur);
	if(item->path>_T(""))
		ShellExecute(NULL,_T("open"),item->path,_T(""),_T(""),SW_SHOW);
}

void CCompareFoldersDlg::OnSourcesafeViewDoc() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = m_psm_list.GetItemData(cur);
	if(item->m_inst)
	{
		if(!m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc)) return;
		CString tmp_path; tmp_path.GetEnvironmentVariable(_T("temp"));
		CaplInstance *active;
		m_api->m_data.GetAttr(item->m_inst,m_api->m_doc_mgr.a_apl_doc_active,active);
		if(!active) return;
		CaplAttr *source;
		m_api->m_doc_mgr.LogDocAccess(active,_T("CCompareFoldersDlg"),tmp_path);
		m_api->m_data.GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,active);
		if(m_api->m_data.IsKindOf(active,m_api->m_doc_mgr.e_apl_stored_document))
			source = m_api->m_doc_mgr.a_apl_stored_document_source;
		else if(m_api->m_data.IsKindOf(active,m_api->m_doc_mgr.e_apl_assigned_document))
			source = m_api->m_doc_mgr.a_apl_assigned_document_location_path;
		if(!m_api->m_data.NET_LoadBlob(active,source,tmp_path+_T("\\")+GetDocFileName(item->m_inst)))
		{
			TRACE( APL_T("Ошибка создания файла")+item->path+GetDocFileName(item->m_inst)+_T("\n"));
			AfxMessageBox( APL_T("Не могу создать файл!"));
			return;
		}
		else
			ShellExecute(NULL,_T("open"),tmp_path+_T("\\")+GetDocFileName(item->m_inst),_T(""),tmp_path,SW_SHOW);
	}
}

void CCompareFoldersDlg::OnSsPrintDocs() 
{
	int cur = m_psm_list.GetNextItem(-1,LVIS_SELECTED);
	if(cur<0) return;
	CItem *item = (CItem*)m_psm_list.GetItemData(cur);
	if(item)
	{
		if(item->m_inst==0) return;
		if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_folder_mgr.e_folder))
		{
			if(item->path==_T(""))
				if(item->m_folder!=0)
				{
					CItem* titem = FindItem(item->m_folder);
					if(titem) 
					{
						CString name;
						m_api->m_data.GetAttr(item->m_inst,m_api->m_folder_mgr.a_folder_name, name);
						item->path = titem->path+name+_T("\\");
						m_api->m_folder_mgr.CreateFolderOndisk(item->path);
					}
				}
			m_api->m_folder_mgr.CopyDocOnDisk(item->m_inst,item->path,APL_PRINT_DOCS);
		}
		else if(m_api->m_data.IsKindOf(item->m_inst,m_api->m_doc_mgr.e_doc))
		{
			m_api->m_folder_mgr.CreateFolderOndisk(item->path);
			CaplInstance *active, *af;
			CaplAttr *source=0;
			m_api->m_data.GetAttr(item->m_inst,m_api->m_doc_mgr.a_apl_doc_active,active);
			m_api->m_doc_mgr.LogDocAccess(active,_T("CCompareFoldersDlg"),item->path);
			m_api->m_data.GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,af);
			if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_stored_document))
				source = m_api->m_doc_mgr.a_apl_stored_document_source;
			else if(m_api->m_data.IsKindOf(af,m_api->m_doc_mgr.e_apl_assigned_document))
				source = m_api->m_doc_mgr.a_apl_assigned_document_location_path;
			if(!m_api->m_data.NET_LoadBlob(af,source,item->path+GetDocFileName(item->m_inst)))
			{
				TRACE( APL_T("Ошибка создания файла")+item->path+GetDocFileName(item->m_inst)+_T("\n"));
				AfxMessageBox( APL_T("Не могу создать файл!"));
				return;
			}
			else
			{
				CString tmp = item->path+GetDocFileName(item->m_inst);
				ShellExecute(this->m_hWnd,_T("print"),tmp,NULL,item->path,SW_HIDE);
				m_api->m_folder_mgr.RecursiveCopyDocs(item->m_inst,item->path,APL_PRINT_DOCS);
			}
		}
	}
}

bool CCompareFoldersDlg::FindFiles(CString filter, UINT type, CStringArray *array)
{
	array->RemoveAll();
	if(type==0)//Поиск файлов
	{
		HANDLE find;
		WIN32_FIND_DATA fdata;
		find = FindFirstFile(filter,&fdata);
		if(find!=INVALID_HANDLE_VALUE)
		{
			if(!(fdata.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
				array->Add(fdata.cFileName);
			while(FindNextFile(find,&fdata))
			{
				if(!(fdata.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
					array->Add(fdata.cFileName);
			}
			FindClose(find);
			return true;
		}
	}
	else if(type==1)//Поиск каталогов
	{
		HANDLE find;
		WIN32_FIND_DATA fdata;
		find = FindFirstFile(filter,&fdata);
		if(find!=INVALID_HANDLE_VALUE)
		{
			CString str = fdata.cFileName;
			if(fdata.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
				if(str!=_T(".") && str!=_T(".."))
					array->Add(str);
			while(FindNextFile(find,&fdata))
			{
				str = fdata.cFileName;
				if(fdata.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
					if(str!=_T(".") && str!=_T(".."))
						array->Add(str);
			}
			FindClose(find);
			return true;
		}
	}
	return false;
}
