// OscilloscopeView.cpp : implementation of the COscilloscopeView class

#include "stdafx.h"
#include "Oscilloscope.h"

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include "OscilloscopeDoc.h"
#include "FiguresOsc.h"
#include "OscilloscopeView.h"
#include "SinTable.h"
#include "MainFrm.h"
#include "DialogueBox.h"
#include "StringEdit.h"

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

BOOL COscilloscopeView::m_bIsON;
//////////////////////////////////////////////////////////////////////
// COscilloscopeView

///////////////////////////////////////
UINT ShowTwoD(LPVOID WinObjPtr) ;
UINT ShowThreeD(LPVOID WinObjPtr) ;
///////////////////////////////////////


IMPLEMENT_DYNCREATE(COscilloscopeView, CView)

BEGIN_MESSAGE_MAP(COscilloscopeView, CView)
	//{{AFX_MSG_MAP(COscilloscopeView)
	ON_WM_KEYDOWN()
	ON_COMMAND(ID_2DGraph_III, On2DGraph_III)
	ON_COMMAND(ID_2DGraph_II, On2DGraph_II)
	ON_COMMAND(ID_2DGraph_IV, On2DGraph_IV)
	ON_COMMAND(ID_2DGraph_V, On2DGraph_V)
	ON_COMMAND(ID_2DGraph_VI, On2DGraph_VI)
	ON_COMMAND(ID_2DGraph_VII, On2DGraph_VII)
	ON_COMMAND(ID_2DGraph_VIII, On2DGraph_VIII)
	ON_COMMAND(ID_2DGraph, On2DGraph_I)
	ON_COMMAND(ID_Parameters, OnChangeParameters)
	ON_COMMAND(ID_Functions, OnFunctions)
	ON_COMMAND(ID_PROCEED, OnProceed)
	ON_COMMAND(ID_SPEED_UP, OnSpeedUp)
	ON_COMMAND(ID_SLOW_DOWN, OnSlowDown)
	ON_COMMAND(Quick_Function, OnQuickFunction)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
	ON_COMMAND(ID_IS_PD, &COscilloscopeView::OnIsPD)
	ON_UPDATE_COMMAND_UI(ID_IS_PD, &COscilloscopeView::OnUpdateIsPD)
	ON_WM_LBUTTONDOWN()
	ON_COMMAND(ID_SMALLER_PANNELS, &COscilloscopeView::OnSmallerPanels)
	ON_COMMAND(ID_BIGGER_PANNELS, &COscilloscopeView::OnBiggerPanels)
	ON_WM_CONTEXTMENU()
	ON_WM_RBUTTONDOWN()
	ON_WM_KEYUP()
	ON_COMMAND(ID_SCALE_DELETE_FIGS, &COscilloscopeView::OnDeleteFigs)
	ON_COMMAND(ID_SCALE_DELETE_THE_REST, &COscilloscopeView::OnDelete_the_Rest_Figs)
	ON_COMMAND(ID_FILE_SAVE, &COscilloscopeView::OnFileSave)
	ON_COMMAND(ID_FILE_OPEN, &COscilloscopeView::OnFileOpen)
	ON_EN_CHANGE(IDC_EDIT_STRING1, &COscilloscopeView::OnEnChangeEditString1)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////


// COscilloscopeView construction/destruction
COscilloscopeView::COscilloscopeView()
{
	m_nColorShow=BLACK_BRUSH;
	m_bShow2D=0;  
	m_bFistTime=1;
	m_nKey=0;
	m_nSpeed=0;
	FlagVerScreen=0;
	m_DispEventIdx=0;
	m_bProceed=0;
	m_bIsToggleON=0;
	m_bIsON=0;
	m_dScaleUpDn=1;
	m_dHowManyRows=MaxFigRow; m_dHowManyClmns=MaxFigCln;
	m_BlownUpPaneID=-1;
	m_selectedChan=0; m_PrvSelectedChan=0; m_StartAfresh=0;
	////////////////////////////////////
	m_NULL.CreatePen(PS_NULL, 1,RGB(0,0,0));
	m_RED.CreatePen(PS_SOLID, 1,RGB(255,0,0));
	m_RED3.CreatePen(PS_SOLID, 3,RGB(255,0,0));
	m_RED5.CreatePen(PS_SOLID, 5,RGB(255,0,0));
	m_RED8.CreatePen(PS_SOLID, 8,RGB(255,0,0));
	m_ORANGE2.CreatePen(PS_SOLID, 2,RGB(255,150,0));
	m_GREEN.CreatePen(PS_SOLID, 1,RGB(0,255,0));
	m_BLUE.CreatePen(PS_SOLID, 1,RGB(100,100,255));
	m_BLUE3.CreatePen(PS_SOLID, 3,RGB(100,100,255));
	m_BLUE5.CreatePen(PS_SOLID, 5,RGB(100,100,255));
	m_BLUE8.CreatePen(PS_SOLID, 8,RGB(100,100,255));
	m_GREEN3.CreatePen(PS_SOLID, 3,RGB(0,255,0));
	m_DkGREEN.CreatePen(PS_SOLID, 1,RGB(0,155,0));
	m_CYAN.CreatePen(PS_SOLID, 1,RGB(0,255,255));
	m_CYAN3.CreatePen(PS_SOLID, 3,RGB(200,255,255));
	m_PINK.CreatePen(PS_SOLID, 1,RGB(255,150,150));
	m_PINK3.CreatePen(PS_SOLID, 3,RGB(255,150,150));
	m_BROWN.CreatePen(PS_SOLID, 1,RGB(240,130,0));
	m_VIOLET.CreatePen(PS_SOLID, 1,RGB(200,90,250));
	m_VIOLET2.CreatePen(PS_SOLID, 2,RGB(200,90,250));
	m_VIOLET3.CreatePen(PS_SOLID, 3,RGB(200,90,250));
	m_bkPen.CreatePen(PS_SOLID, 1,RGB(220,220,220));
	m_GRAY1.CreatePen(PS_SOLID, 1,RGB(170,170,170));
	m_GRAY2.CreatePen(PS_SOLID, 3,RGB(170,170,170));
	m_BlueGRAY.CreatePen(PS_SOLID, 1,RGB(210,210,240));
	m_BLACK.CreatePen(PS_SOLID, 1,RGB(0,0,0));
	m_BLACK3.CreatePen(PS_SOLID, 3,RGB(0,0,0));
	m_BLACK2.CreatePen(PS_SOLID, 2,RGB(0,0,0));
	m_BLACK5.CreatePen(PS_SOLID, 5,RGB(0,0,0));
	/////////////
	//SigmoidColorMix(m_RGB100,MaxRGB100);
	//GaussianColorMix(m_RGB100,MaxRGB100);
	MyOriginalColorMix(m_RGB100,MaxRGB100);

	int i,j;
	for(i=0;i<MaxPen;i++){
		j=(MaxRGB100-1)-i*(MaxRGB100/MaxPen);
		if(j<0)j=0;
		m_rgbPEN1[i].CreatePen(PS_SOLID, 1,m_RGB100[j]);
		m_rgbPEN2[i].CreatePen(PS_SOLID, 2,m_RGB100[j]);
		m_rgbPEN3[i].CreatePen(PS_SOLID, 3,m_RGB100[j]);
	}
	LOGBRUSH LogBrh[MaxBrush];
	for(i=0;i<MaxBrush;i++){
		LogBrh[i].lbStyle=BS_SOLID;
		LogBrh[i].lbColor=RGB((int)((255./MaxBrush)*i),(int)((255./MaxBrush)*i),(int)((255./MaxBrush)*i));
		m_Gray[i].CreateBrushIndirect( &LogBrh[i] );
	}

	/////////////// Parameters For Applications
	m_GlobalTitle="NoName";
	m_NewlyLoaded=0; m_DoNotErase=0;
	m_dMinimumX=-1000;m_dMaximumX=1000;
	m_dMinimumY=0;m_dMaximumY=100;
	m_savedClientRect.top=0;m_savedClientRect.bottom=0;m_savedClientRect.left=0;m_savedClientRect.right=0;
	m_SelectedItemID=-1; m_numCaptured=0;
	m_IsThresholdHeld=0; m_prvThreshold_onScrn=0;

	
	m_FirstTime0ElementErr=1;
	m_pSpotlightFig=&m_Fig[0][0][0];
}					


COscilloscopeView::~COscilloscopeView() 
{
	m_bIsON=0;
	
	for(int timeOut=0; timeOut<10; timeOut++){
		Sleep(10);
	}	
	CloseSharedMemoryArea();

	int i;
	for(i=0; i<MaxDC;i++){
		m_DC[i].DeleteDC();
		m_bmp[i].DeleteObject();
	}
	for(i=0; i<MaxBrush;i++)m_Gray[i].DeleteObject();
	m_bkBrush.DeleteObject();
	for(i=0; i<MaxPen;i++){
		m_rgbPEN1[i].DeleteObject(); m_rgbPEN2[i].DeleteObject(); m_rgbPEN3[i].DeleteObject();
	}
	m_NULL.DeleteObject(); m_RED.DeleteObject(); m_BLUE.DeleteObject();m_GREEN.DeleteObject(); ;m_DkGREEN.DeleteObject(); m_PINK.DeleteObject();m_BROWN.DeleteObject();m_VIOLET.DeleteObject();
	m_ORANGE2.DeleteObject(); m_VIOLET2.DeleteObject();m_VIOLET3.DeleteObject();m_BLACK.DeleteObject();m_BLACK2.DeleteObject();m_BLACK3.DeleteObject();m_bkPen.DeleteObject();
	m_GRAY1.DeleteObject();m_GRAY2.DeleteObject();m_CYAN3.DeleteObject();m_BlueGRAY.DeleteObject();m_PINK3.DeleteObject();m_RED3.DeleteObject(); m_BLUE3.DeleteObject(); m_GREEN3.DeleteObject();
	m_RED5.DeleteObject(); m_BLUE5.DeleteObject(); m_BLACK5.DeleteObject(); m_RED8.DeleteObject(); m_BLUE8.DeleteObject(); m_BLACK8.DeleteObject();
	m_font.DeleteObject();
}

BOOL COscilloscopeView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
UINT Graph2D_I(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Oscilloscope_thread() ;
	if(*(pView->M_Blip_OFF)==1)AfxGetMainWnd()->SendMessage(WM_CLOSE);
	return 0;
}
#define SIZE_OF_BITMAP_X 0.5
#define SIZE_OF_BITMAP_Y 0.5
void COscilloscopeView::OnDraw(CDC* pDC)
{
#define CH_SIZE_X 8
#define CH_SIZE_Y 10
#define LINE_GAP  5
#define STR_SIZE  150
#define SFT		  0
#define SFT1      200
#define SFT2      400
#define SFT3      600

	COscilloscopeDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	if(m_bFistTime==1){
		VirMemDC();
		m_dHowManyClmns=-1;
		OnFileOpen();//Try to open a default root file.
		if(m_dHowManyClmns!=-1){
			RecalibratePanes();
			AfxBeginThread( Graph2D_I, this);
			return;//Opening a default root file has been successful.
		}
		else{//Failed to open a default root file => implement the programs own version.
			sprintf(m_FileName,"");
			sprintf(m_JustFileName,"NO root file");
			m_dHowManyClmns=1; 
		}
		Re_measure_ClientView();
		Start_a_NEW_set_of_figures();
		RecalibratePanes();
		m_bFistTime=0;
		AfxBeginThread( Graph2D_I, this);
	}
	else{
		CRect rt;
		GetClientRect(&rt);
		if(m_savedClientRect.right!=rt.right||m_savedClientRect.bottom!=rt.bottom){//Specifies the window's coordinates when the window is in the normal (restored) position. 
			if(m_savedClientRect.right<rt.right ||m_savedClientRect.bottom<rt.bottom){
				if(m_savedClientRect.right>=SIZE_OF_BITMAP_X*m_nScrMaxX ||m_savedClientRect.bottom>=SIZE_OF_BITMAP_Y*m_nScrMaxY){
					int Y=SIZE_OF_BITMAP_Y*m_nScrMaxY;
					char ScreenMsg[1024]; sprintf(ScreenMsg,"Simon: To save Bitmap memory, the size of the window is currently limited to Horizontal:%d, Vertical:%d\n To change this setting, adjust SIZE_OF_BITMAP_X and SIZE_OF_BITMAP_Y in the program.",(int)(SIZE_OF_BITMAP_X*m_nScrMaxX),Y);
					AfxMessageBox(ScreenMsg);
				}
			}
			RequestDisplayEvent(RESIZING_WIN);
		}
		else{//Just display without changing anything
			CClientDC objDC(this);
			objDC.BitBlt(0,0,m_nScrMaxX,m_nScrMaxY,&m_DC[0],0,0,SRCCOPY);
		}
	}
}

void COscilloscopeView::Start_a_NEW_set_of_figures()
{			
	int i,j;
	CFigure *pFig;
	m_numCaptured=0;
	for(i=0;i<m_dHowManyRows;i++){
		for(j=0;j<m_dHowManyClmns;j++){
			pFig=&m_Fig[i][j][0];
			pFig->SetMinMaxXY(-1000,1000,0,100);pFig->SetLabelsXY("","");
			pFig->m_Captured=0;
			pFig->m_Deleted=0;
	}	}
	Batch_FigPosition_Settings(m_dSizeOfOneRow, m_dSizeOfOneClmn, m_dScaleUpDn);
	Batch_SetFontSize(&m_DC[0]);
	Batch_Prepare4FigFrame();
	Batch_DrawFigureFrames();
}

void COscilloscopeView::Re_measure_ClientView()
{			
	CRect rt;
	GetClientRect(&rt);
	if(m_bFistTime==1){
		CFont* pFont = m_DC[0].GetCurrentFont();
		LOGFONT LogFont;
		pFont->GetLogFont(&LogFont);
		m_fontHeight=LogFont.lfHeight;
	}
	m_TitleArea.top=rt.top;	m_TitleArea.bottom=rt.top+m_fontHeight*2; m_topOfFigs=m_TitleArea.bottom;
	m_TitleArea.left=rt.left; m_TitleArea.right=rt.right;
	m_dSizeOfOneRow =(rt.bottom-m_topOfFigs-ViewMargin4FigsAlongEdges)/m_dHowManyRows;  if(m_dSizeOfOneRow <=0)m_dSizeOfOneRow=0;
	m_dSizeOfOneClmn=(rt.right-rt.left-ViewMargin4FigsAlongEdges)/m_dHowManyClmns; if(m_dSizeOfOneClmn<=0)m_dSizeOfOneClmn=0;
	m_savedClientRect=rt;m_savedClientRect.top=m_topOfFigs;
}


/////////////////////////////////////////////////////////////////////////////
// COscilloscopeView printing

BOOL COscilloscopeView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void COscilloscopeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void COscilloscopeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// COscilloscopeView diagnostics

#ifdef _DEBUG
void COscilloscopeView::AssertValid() const
{
	CView::AssertValid();
}

void COscilloscopeView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

COscilloscopeDoc* COscilloscopeView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(COscilloscopeDoc)));
	return (COscilloscopeDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// COscilloscopeView message handlers

UINT Graph2D_II(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Show2D_II() ;
	return 0;
}
UINT Graph2D_III(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Show2D_III() ;
	return 0;
}
UINT Graph2D_IV(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Show2D_IV() ;
	return 0;
}
UINT Graph2D_V(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Show2D_V() ;
	return 0;
}
UINT Graph2D_VI(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Show2D_VI() ;
	return 0;
}
UINT Graph2D_VII(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Show2D_VII() ;
	return 0;
}
UINT Graph2D_VIII(LPVOID WinObjPtr) //A global Function
{
	COscilloscopeView* pView=(COscilloscopeView*) WinObjPtr;
	pView->Show2D_VIII() ;
	return 0;
}


void COscilloscopeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	//if(m_nShowMode==GRAPH_3D){ThD.KeyDown(nChar); goto ToEND;}
	m_KeyCode=nChar;
	switch(nChar){
		case VK_DELETE:
			OnDeleteFigs();
			break;
		default: break;
	}

	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void COscilloscopeView::On2DGraph_I() 
{
		AfxBeginThread( Graph2D_I, this);
}
void COscilloscopeView::On2DGraph_II() 
{
		AfxBeginThread( Graph2D_II, this);
}
void COscilloscopeView::On2DGraph_III() 
{
		AfxBeginThread( Graph2D_III, this);
}
void COscilloscopeView::On2DGraph_IV() 
{
		AfxBeginThread( Graph2D_IV, this);
}
void COscilloscopeView::On2DGraph_V() 
{
		AfxBeginThread( Graph2D_V, this);
}
void COscilloscopeView::On2DGraph_VI() 
{
		AfxBeginThread( Graph2D_VI, this);
}
void COscilloscopeView::On2DGraph_VII() 
{
		AfxBeginThread( Graph2D_VII, this);
}
void COscilloscopeView::On2DGraph_VIII() 
{
		AfxBeginThread( Graph2D_VIII, this);
}

void COscilloscopeView::VirMemDC()
{
	//########  Preparing Virtual Window  ##########
	if(FlagVerScreen==1){
		return;
	}
	FlagVerScreen=1;
////////////////////////////////
   LOGFONT lf;                        // Used to create the CFont.
   memset(&lf, 0, sizeof(LOGFONT));   // Clear out structure.
   lf.lfWidth = 6;                   // Width of font
   lf.lfHeight = 12;                  // Request a 20-pixel-high font
   strcpy(lf.lfFaceName, "Times New Roman");    //    with face name "Arial".
   m_font.CreateFontIndirect(&lf);    // Create the font.
   // Use the font to paint a control. This code assumes
   // a control named IDC_TEXT1 in the dialog box.
   SetFont(&m_font);
//////////////////////////////////////
	
	m_nScrMaxX=GetSystemMetrics(SM_CXSCREEN);
	m_nScrMaxY=GetSystemMetrics(SM_CYSCREEN);
	LOGBRUSH LogBrh;
	LogBrh.lbStyle=BS_SOLID;	LogBrh.lbColor=RGB(220,220,220);	
	m_bkBrush.CreateBrushIndirect( &LogBrh );
	//m_bkBrush.CreateStockObject(WHITE_BRUSH);
	CClientDC aDC(this);
	
	for(int i=0;i<MaxDC;i++){
		m_DC[i].CreateCompatibleDC(&aDC);
		m_bmp[i].CreateCompatibleBitmap(&aDC, m_nScrMaxX*SIZE_OF_BITMAP_X, m_nScrMaxY*SIZE_OF_BITMAP_Y);
		m_DC[i].SelectObject(&m_bmp[i]);
		m_DC[i].SelectObject(&m_bkBrush);
		m_DC[i].SelectObject(&m_font);
		//m_DC[i].PatBlt(0,0,m_nScrMaxX,m_nScrMaxY,PATCOPY);
	}
	m_SavedDC=m_DC[0].SaveDC();
	m_Fig[0][0][0].m_pDC=&m_DC[0];
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
//################################################  2D Graphics #######################################


void COscilloscopeView::Oscilloscope_thread() 
{
	if(m_bIsON==1){m_bIsON=0;return; }
	m_bIsON=1;
	VirMemDC();
	CClientDC objDC(this);
	int nSaveDC=m_DC[0].SaveDC();
	//////////// Implementation Below ///////////
	//////////// Implementation Below ///////////
	CFigure *pFig1=&m_Fig[0][0][0]; 
	pFig1->ComputeMapping_XY(); 
	pFig1->Frame_Graph2D(&m_DC[0],1);
	m_DC[0].SelectObject(m_BLUE);
	objDC.SelectObject(m_BLUE);
	m_pSpotlightFig=pFig1;
	RequestDisplayEvent(RESIZING_WIN);

	int dataIdx,i=0, dispX=0,savedDispX=-1, completedDrawing=0, distBetweenDispIdxDataIdxIn_ms=0, sparceDisp=0;
	unsigned int prvUsablelData_idx, latestUsablelData_idx,dataIdxToProcess;
	char BacklogMsg[512];
	CSingleLock SyncObj_Display(&m_sema); 

	CreateSharedMemoryArea();
	
	//This one has been added in case this function becomes stuck in the following two while() loop that it does not process any display.
	//This one needs to come after CreateSharedMemoryArea() since it uses the Memory map member
	DrawOneFigure(pFig1, 0); 
	
	//Wait for DAS-server to start & initialize "DYNAMIC" variables.
	while(*M_isDAS_Running==0){	Sleep(10);	if(m_bIsON==0|| *M_Blip_OFF==1)goto END_SIG_ACQUISION1;	}

	while(*M_usableAiIdx[m_selectedChan]<0){	Sleep(1);	if(m_bIsON==0|| *M_Blip_OFF==1)goto END_SIG_ACQUISION1;	}
	dataIdx=*M_usableAiIdx[m_selectedChan]; i=dataIdx;
	latestUsablelData_idx=*M_usableAiIdx[m_selectedChan], prvUsablelData_idx=latestUsablelData_idx;
	clock_t m_newT, m_lastT=clock();
	double *pAI=M_AI[m_selectedChan], dAI;
	m_dMinimumX=pFig1->m_dMinX; m_dMaximumX=pFig1->m_dMaxX; m_dMinimumY=pFig1->m_dMinY; m_dMaximumY=pFig1->m_dMaxY;
	m_prvThreshold_onScrn=pFig1->FromDataToScreenY(M_Threshold[m_selectedChan]);

	if(M_Threshold[NUM_NN_AI_CHAN]==INT_MAX)ReadThresholds();//Read the threshold only when the DAS server hasn't. ==>Does it ever happen?


#define DispEvery_Nms 33 // 33ms means about 30 Frams/Sec
	int DispIdx=0, DispIdxDist, nextDispIDx;
	m_prvX=0; m_prvY=0;
	pFig1->MyMoveTo(0,0);
	while(1){
		//After the user has changed the channel to display.
		if(m_StartAfresh==1){
			m_StartAfresh=0;
			i=0; dispX=0;savedDispX=-1; completedDrawing=0; distBetweenDispIdxDataIdxIn_ms=0;
			while(*M_usableAiIdx[m_selectedChan]<0){	Sleep(1);	if(m_bIsON==0|| *M_Blip_OFF==1)goto END_SIG_ACQUISION1;	}
			dataIdx=*M_usableAiIdx[m_selectedChan]; i=dataIdx;
			latestUsablelData_idx=*M_usableAiIdx[m_selectedChan], prvUsablelData_idx=latestUsablelData_idx;
			m_lastT=clock();
			pAI=M_AI[m_selectedChan];
			//If the sampling rate of the data of the newly selected channel is different from the that of the previous channel, redraw the figure
			if((m_selectedChan<NUM_NN_AI_CHAN && !(m_PrvSelectedChan<NUM_NN_AI_CHAN)) || (!(m_selectedChan<NUM_NN_AI_CHAN) && m_PrvSelectedChan<NUM_NN_AI_CHAN)){
				if(m_selectedChan<NUM_NN_AI_CHAN){
					pFig1->m_dLabelScale=1000./(DATA_SAMPLING_RATE); 
				}
				else{
					pFig1->m_dLabelScale=1000./(BEHAVIOR_DATA_SAMPLING_RATE); 
				}
			}

			SyncObj_Display.Lock();
			DrawOneFigure(pFig1, 0);
			SyncObj_Display.Unlock();
			m_PrvSelectedChan=m_selectedChan;
		}

		//Refresh the figure (reflect the new drawing)
		m_newT=clock();
		if(m_newT-m_lastT>DispEvery_Nms && completedDrawing==1){
			SyncObj_Display.Lock();
			if(sparceDisp++>10){
				sparceDisp=0; if(distBetweenDispIdxDataIdxIn_ms>1000){sprintf_s(BacklogMsg,"Backlog: %d ms",distBetweenDispIdxDataIdxIn_ms);	objDC.TextOut(300,m_dTitleRect.top,BacklogMsg);}
			}
			//pFig1->PutIntVal(MsgPosX(pFig1,0.1),MsgPosY(pFig1,1.04),distBetweenDispIdxDataIdxIn_ms,&objDC);
			m_DC[0].SelectObject(m_GRAY1);
			pFig1->RefreshPane(&objDC,&m_DC[0]);
			pFig1->ErasePaneGray(&m_DC[0]);
			m_lastT=m_newT; completedDrawing=0;
			m_DC[0].SelectObject(m_BLUE);
			objDC.SelectObject(m_BLUE);
			SyncObj_Display.Unlock();
		}

		while(*M_isDAS_Running==0){Sleep(5); if(m_bIsON==0|| *M_Blip_OFF==1)goto END_SIG_ACQUISION1;}

		latestUsablelData_idx=*M_usableAiIdx[m_selectedChan];
		if(latestUsablelData_idx!=prvUsablelData_idx && completedDrawing==0){//Draw only when there has been a change
			prvUsablelData_idx=latestUsablelData_idx;
			if(dataIdx>latestUsablelData_idx){//The M_usableAiIdx[m_selectedChan] has returned to the head part of the data.
				dataIdxToProcess=M_AIQueueSize[m_selectedChan]-1;//Display the rest first before returning to the begining of the queue.  //--Line (1)
			}
			else{
				dataIdxToProcess=latestUsablelData_idx; 
			}
			//###### Draw the signal ######
			SyncObj_Display.Lock();
			pFig1->MyMoveTo(m_prvX, m_prvY);
			for(;dataIdx<=dataIdxToProcess;dataIdx++, dispX++){
				dAI=pAI[dataIdx];
				if(dAI>pFig1->m_dMaxY)dAI=pFig1->m_dMaxY; else if(dAI<pFig1->m_dMinY)dAI=pFig1->m_dMinY;
				if(dispX>pFig1->m_dMaxX){
					//In case the dataIdx is behind more than 1 frame period (DispEvery_Nms), make it to be behind only 1 frame.
					distBetweenDispIdxDataIdxIn_ms=(int)(0.001*(*M_microSecPerPoint)*(dataIdxToProcess-dataIdx));//Because of Line(1) above, (dataIdxToProcess-dataIdx)>0 always
					if(distBetweenDispIdxDataIdxIn_ms>DispEvery_Nms){
						dataIdx=qIdx(dataIdxToProcess-(int)(DispEvery_Nms/(0.001*(*M_microSecPerPoint))));
					}
					//Draw
					dispX=0; completedDrawing=1;
					pFig1->MyMoveTo(0,dAI);
					m_prvX=0; m_prvY=dAI;
					dataIdx++;//This is needed because the end of the for-loop expects that the index to point the next data
					break;
				}
				else{
					pFig1->MyLineTo(dispX,dAI); 
					m_prvX=dispX; m_prvY=dAI;
				}
			}
			SyncObj_Display.Unlock();
			//#############################
			if(dataIdx>M_AIQueueSize[0]-1){
				dataIdx=0;
			}
		}
		else Sleep(1);
		
		//###########  Take care of Display requests  ##################
		if(DispIdx<=m_DispEventIdx)DispIdxDist=m_DispEventIdx-DispIdx;
		else DispIdxDist=MAX_DISP_REQUESTS-DispIdx+m_DispEventIdx;
		if(DispIdxDist>0){
			for(i=0;i<DispIdxDist; i++){
				if(DispIdx+1<MAX_DISP_REQUESTS)nextDispIDx=DispIdx+1; else nextDispIDx=0;
				if(i+1<DispIdxDist && m_DispEvents[DispIdx][0]==m_DispEvents[nextDispIDx][0]){
					if(m_DispEvents[DispIdx][1]>=1){//The number of arguments.
						if(m_DispEvents[DispIdx][2]==m_DispEvents[nextDispIDx][2]){//The 1st argument
							if(m_DispEvents[DispIdx][1]>=2){
								if(m_DispEvents[DispIdx][3]==m_DispEvents[nextDispIDx][3]){//The 2nd argument
									DispIdx=nextDispIDx; continue;//In case the next dispaly request is the same as the current one, skip the current one.
								}
							}
							else {DispIdx=nextDispIDx; continue;}//In case the next dispaly request is the same as the current one, skip the current one.
						}
					}
					else {DispIdx=nextDispIDx; continue;}//In case the next dispaly request is the same as the current one, skip the current one.
				}
				SyncObj_Display.Lock();
				Display_forOscilloscope(DispIdx,&objDC);	DispIdx=nextDispIDx;				
				SyncObj_Display.Unlock();
			}
		}

		if(m_bIsON==0 || *M_Blip_OFF==1)break;
	}
END_SIG_ACQUISION1:;

	/////////////////////
	m_bIsON=0;
	m_DC[0].RestoreDC(nSaveDC); 
	objDC.BitBlt(0,0,m_nScrMaxX,m_nScrMaxY,&m_DC[0],0,0,SRCCOPY);
}

void COscilloscopeView::RequestDisplayEvent(int Event) 
{
	RequestDisplayEvent(Event, 0, NULL,  NULL);
}
void COscilloscopeView::RequestDisplayEvent(int Event,  int SomeIntValue) 
{
	RequestDisplayEvent(Event, 1, SomeIntValue,  NULL); 
}
void COscilloscopeView::RequestDisplayEvent(int Event,  int SomeIntValue1,  int SomeIntValue2) 
{
	RequestDisplayEvent(Event, 2, SomeIntValue1, SomeIntValue2);
}
void COscilloscopeView::RequestDisplayEvent(int Event, int NumVariables,  int SomeIntValue1,  int SomeIntValue2) 
{	
	m_DispEvents[m_DispEventIdx][0]=Event;
	m_DispEvents[m_DispEventIdx][1]=NumVariables;
	for(int i=0; i<NumVariables;i++){
		if(i==0)m_DispEvents[m_DispEventIdx][i+2]=SomeIntValue1; 
		else if(i==1)m_DispEvents[m_DispEventIdx][i+2]=SomeIntValue2; 
	}
	if(m_DispEventIdx+1<MAX_DISP_REQUESTS)m_DispEventIdx++; else m_DispEventIdx=0;
}

void COscilloscopeView::Display_forOscilloscope(int RequestIdx, CDC *pObjDC)
{
	CFigure *pFig=&m_Fig[0][0][0];
	switch(m_DispEvents[RequestIdx][0]){
	case RESIZING_WIN:
		Re_measure_ClientView();
		Batch_FigPosition_Settings(m_dSizeOfOneRow, m_dSizeOfOneClmn, m_dScaleUpDn);
		Batch_Prepare4FigFrame();
		RecalibratePanes();
		DrawOneFigure(pFig, 0);
		DisplayGlobalTitle();
		break;
	case DISP_CHAN_NAMES:
		pFig->ListChanIDs(pObjDC,m_selectedChan);
		break;
	case DISP_THRESHOLD:
		pObjDC->MoveTo(m_pSpotlightFig->m_nPaneTx-2*m_pSpotlightFig->m_FontWidth,m_prvThreshold_onScrn);pObjDC->LineTo(m_pSpotlightFig->m_nPaneBx-2,m_prvThreshold_onScrn);
		m_DC[0].MoveTo(m_pSpotlightFig->m_nPaneTx-2*m_pSpotlightFig->m_FontWidth,m_prvThreshold_onScrn);m_DC[0].LineTo(m_pSpotlightFig->m_nPaneBx-2,m_prvThreshold_onScrn);
		break;
	case RESCALING_AXES:
		DrawOneFigure(pFig, 0);
	case REDRAW_FIG:
		DrawOneFigure(pFig, 0);
		break;
	}
}

void COscilloscopeView::DrawOneFigure(CFigure *pFig, int isToHighlight) 
{
	CClientDC objDC(this);
	pFig->ComputeMapping_XY(); 
	pFig->Frame_Graph2D(&m_DC[0],1); 
	m_DC[0].SelectObject(m_BLUE3);
	m_prvThreshold_onScrn=pFig->FromDataToScreenY(M_Threshold[m_selectedChan]);
	m_DC[0].MoveTo(pFig->m_nPaneTx-2*pFig->m_FontWidth,m_prvThreshold_onScrn);m_DC[0].LineTo(pFig->m_nPaneBx-2,m_prvThreshold_onScrn);
	pFig->ListChanIDs(&m_DC[0],m_selectedChan);
	//if(isToHighlight==1)Hilight_OneCapturedFig(pFig);
	//else UnHilight_OneCaptured(pFig);
	pFig->RefreshFrame(&objDC,&m_DC[0]); 
	objDC.BitBlt(0,0,m_nScrMaxX,m_nScrMaxY,&m_DC[0],0,0,SRCCOPY);
}

int COscilloscopeView::qIdx(int i)
{
	if(i>=0 && i<M_AIQueueSize[0])return i;
	else if(i>M_AIQueueSize[0]-1)return (i-M_AIQueueSize[0]);
	else return (M_AIQueueSize[0]+i);//if(i<0) => This happens when the program tries to retrieve the pre-threshold-crossing portion of the wave.
}

void COscilloscopeView::Show2D_II() 
{	

}


void COscilloscopeView::Show2D_III() 
{
}


void COscilloscopeView::Show2D_IV() 
{  

}

void COscilloscopeView::Show2D_V() 
{

}
void COscilloscopeView::Show2D_VI() 
{
}


void COscilloscopeView::Show2D_VII() 
{
}


void COscilloscopeView::Show2D_VIII()
{ 
}

void COscilloscopeView::Tics_n_Lines(CFigure *pBrd, int HowManyTicsX, int HowManyTicsY) 
{
#define TICK_STEPX(pB) ((pB->m_dMaxX-pB->m_dMinX)/(pB->m_howManyX-1))
#define TICK_STEPY(pB) ((pB->m_dMaxY-pB->m_dMinY)/(pB->m_howManyY-1))
	int i;
	float TickStepX, TickStepY;

	pBrd->m_howManyX=HowManyTicsX; TickStepX=TICK_STEPX(pBrd);
	for(i=0;i<pBrd->m_howManyX;i++){pBrd->m_IsLabeledTicX[i]=1;pBrd->m_XTics[i]=pBrd->m_dMinX+i*TickStepX;} 
	pBrd->m_howManyY=HowManyTicsY; TickStepY=TICK_STEPY(pBrd);
	for(i=0;i<pBrd->m_howManyY;i++){pBrd->m_IsLabeledTicY[i]=1;pBrd->m_YTics[i]=pBrd->m_dMinY+i*TickStepY;} 
}

void COscilloscopeView::Batch_FigPosition_Settings(int sizeOfOneRow, int sizeOfOneClmn, double scale) 
{
#define F2FY 5
#define F2FX 5
	int i,j;
	CFigure *pFig;

	for(i=0;i<m_dHowManyRows;i++){
		for(j=0;j<m_dHowManyClmns;j++){
			pFig=&m_Fig[i][j][0];
			pFig->m_normTx=scale*((j+1)*F2FX+    j*(sizeOfOneClmn-F2FX));  pFig->m_normTy=scale*((i+1)*F2FY+    i*(sizeOfOneRow-F2FY)+m_topOfFigs);   
			pFig->m_normBx=scale*((j+1)*F2FX+(j+1)*(sizeOfOneClmn-F2FX));  pFig->m_normBy=scale*((i+1)*F2FY+(i+1)*(sizeOfOneRow-F2FY)+m_topOfFigs); 
			pFig-> m_LateralMargin=20;
			pFig->SetFig_Position_in_ClientView(pFig->m_normTx,pFig->m_normTy,pFig->m_normBx,pFig->m_normBy);

			pFig->m_BlownUpTx=200; pFig->m_BlownUpTy=5; pFig->m_BlownUpBx=820; pFig->m_BlownUpBy=605; pFig->m_LateralMargin=20;
		}	
	}
}
void COscilloscopeView::Batch_SetFontSize(CDC* pDC) 
{
	int i,j;
	CFigure *pFig;

	for(i=0;i<m_dHowManyRows;i++){
		for(j=0;j<m_dHowManyClmns;j++){
			pFig=&m_Fig[i][j][0];
			pFig->SetFontSize(pDC);
		}	
	}
}
void COscilloscopeView::Batch_Prepare4FigFrame() 
{
	int i,j;
	CFigure *pFig;

	for(i=0;i<m_dHowManyRows;i++){
		for(j=0;j<m_dHowManyClmns;j++){
			pFig=&m_Fig[i][j][0];
			pFig->ComputeMapping_XY();
		}	
	}
}

void COscilloscopeView::Batch_DrawFigureFrames() 
{	
	CClientDC objDC(this);
	m_DC[0].SelectObject(m_bkBrush);m_DC[0].Rectangle(0,0,m_nScrMaxX,m_nScrMaxY); 
	objDC.BitBlt(0,0,m_nScrMaxX,m_nScrMaxY,&m_DC[0],0,0,SRCCOPY);
	m_DoNotErase=1;//This is to inform the Labeling part not to erase previous site, which may not correspond to new position due to resize.
	int i,j;
	CFigure *pFig;
	for(i=0;i<m_dHowManyRows;i++){
		for(j=0;j<m_dHowManyClmns;j++){
			pFig=&m_Fig[i][j][0];
			if(pFig->m_Deleted==0)pFig->Frame_Graph2D(&m_DC[0],1); 
		}
	}
	m_DC[0].SetBkColor(RGB(220, 220, 220));
	m_DC[0].TextOut( m_TitleArea.left+5,m_TitleArea.top+5, m_JustFileName);
	objDC.BitBlt(0,0,m_nScrMaxX,m_nScrMaxY,&m_DC[0],0,0,SRCCOPY);
}

// Writes a string sText with a size which fits perfectly in a rectangle rFont
// Font already attached with device context pDC is scaled
// This does not work for default font of the device contex
void COscilloscopeView::FontInRect(CDC *pDC, CString sText, CRect &rFont)
{
	// Gets current font details
	CFont* pFont = pDC->GetCurrentFont();
	LOGFONT LogFont;
	pFont->GetLogFont(&LogFont);

	// Scales the font to fit in the rectangle
	int a=pDC->GetDeviceCaps(LOGPIXELSY);
	LogFont.lfHeight = -72 * rFont.Height() / pDC->GetDeviceCaps(LOGPIXELSY);
	LogFont.lfWidth = -72 * rFont.Width() / pDC->GetDeviceCaps(LOGPIXELSX) / sText.GetLength();

	// Create a font of calculated size
	CFont Font;
	Font.CreateFontIndirect(&LogFont);

	// Rechecks the string width and height
	pFont = pDC->SelectObject(&Font);
	CSize Size = pDC->GetTextExtent(sText);
	pDC->SelectObject(pFont);
	Font.DeleteObject();

	// Fine tunes the font width and height
	LogFont.lfWidth = (int) (LogFont.lfWidth * rFont.Width() / Size.cx);
	LogFont.lfHeight = (int) (LogFont.lfHeight * rFont.Height() / Size.cy);

	// Create a font with accurate size and displays string
	Font.CreateFontIndirect(&LogFont);
	pFont = pDC->SelectObject(&Font);
	pDC->DrawText(sText, rFont, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
	pDC->SelectObject(pFont);
	Font.DeleteObject();
}

void COscilloscopeView::OnFunctions() 
{

}

void COscilloscopeView::OnQuickFunction() 
{

}

void COscilloscopeView::OnProceed() 
{
	m_bProceed=!m_bProceed;
}


void COscilloscopeView::OnSlowDown() 
{
	m_nSpeed+=10;	
}

void COscilloscopeView::OnSpeedUp() 
{
	if(m_nSpeed>=10)m_nSpeed-=10;	
}

void COscilloscopeView::OnIsPD()
{
	m_bIsToggleON=!m_bIsToggleON;
}

void COscilloscopeView::OnUpdateIsPD(CCmdUI *pCmdUI)
{
	pCmdUI->SetCheck(m_bIsToggleON==1);
}

void COscilloscopeView::OnBiggerPanels()
{
	VirMemDC();
	if(m_dScaleUpDn<10.)m_dScaleUpDn+=0.1;	
	m_bIsScrXYforIJ=0;
	m_DC[0].SelectObject(m_bkBrush);m_DC[0].Rectangle(0,0,m_nScrMaxX,m_nScrMaxY);
}

void COscilloscopeView::OnSmallerPanels()
{
	VirMemDC();
	if(m_dScaleUpDn>0.3)m_dScaleUpDn-=0.1;	
	m_bIsScrXYforIJ=0;
	m_DC[0].SelectObject(m_bkBrush);m_DC[0].Rectangle(0,0,m_nScrMaxX,m_nScrMaxY);
}


