QuakeGod
2023-10-23 843262f9d0438611258363d15a82be7f6e1bc411
MTerm1/MTerm1View.cpp
@@ -17,6 +17,7 @@
#include "DialogSetData.h"
#include "DialogIoComment.h"
#include "KDefine.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -27,6 +28,10 @@
IMPLEMENT_DYNCREATE(CMTerm1View, CScrollView)
/// <summary>
/// 消息映射
/// 是 MFC 中用于将 Windows 消息(如鼠标点击、按键等)映射到成员函数的机制。
/// </summary>
BEGIN_MESSAGE_MAP(CMTerm1View, CScrollView)
   // 标准打印命令
   ON_COMMAND(ID_FILE_PRINT, &CScrollView::OnFilePrint)
@@ -101,19 +106,31 @@
   return CScrollView::PreCreateWindow(cs);
}
/// <summary>
///  MFC 中的一个函数,它在视图首次显示之前被调用
/// </summary>
void CMTerm1View::OnInitialUpdate()
{
   CScrollView::OnInitialUpdate();
   //创建了三种不同的字体
   TextFont.CreateFont(13, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, _T("宋体"));
   MonTextFont.CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, _T("宋体"));
   AnnoFont.CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, _T("宋体"));
   //获取了状态栏的引用并存储在 m_pStatusBar 成员变量中
   m_pStatusBar = ((CChildFrame *)GetParentFrame())->GetStatusBar();
   CSize sizeTotal;
   // TODO: 计算此视图的合计大小
   sizeTotal.cx = m_LeftMargin + m_CellWidth* m_CellPerLine + m_CellWidth *2;
   sizeTotal.cy = 2000;
   //设置了滚动大小
   SetScrollSizes(MM_TEXT, sizeTotal);
   CString s1;
   CString s1;//没啥用
   //设置了两个定时器,一个间隔为50毫秒,另一个为10毫秒。
   SetTimer(1, 50,NULL);
   SetTimer(2, 10, NULL);
@@ -129,25 +146,27 @@
      return;
   // TODO: 在此处为本机数据添加绘制代码
   CString s1;
   CString s1;//没啥用
   needReDraw = 1;
   DrawLDSGraph(pDC);
   needReDraw = 0;
}
// CMTerm1View 打印
// CMTerm1View 打印,MFC 函数,用于准备打印。
BOOL CMTerm1View::OnPreparePrinting(CPrintInfo* pInfo)
{
   // 默认准备
   return DoPreparePrinting(pInfo);
}
// MFC 函数,用于在打印开始之前进行初始化。
void CMTerm1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
   // TODO: 添加额外的打印前进行的初始化过程
}
//MFC 函数,用于在打印结束后进行清理。
void CMTerm1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
   // TODO: 添加打印后进行的清理过程
@@ -157,16 +176,19 @@
// CMTerm1View 诊断
#ifdef _DEBUG
//函数用于验证对象的有效性。
void CMTerm1View::AssertValid() const
{
   CScrollView::AssertValid();
}
 }
// 函数用于将对象的内容转储到指定的上下文。
void CMTerm1View::Dump(CDumpContext& dc) const
{
   CScrollView::Dump(dc);
}
//函数返回与此视图关联的文档对象。
CMTerm1Doc* CMTerm1View::GetDocument() const // 非调试版本是内联的
{
   ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMTerm1Doc)));
@@ -174,6 +196,7 @@
}
#endif //_DEBUG
//MFC 函数,用于处理视图的创建事件。
int CMTerm1View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
   if (CScrollView::OnCreate(lpCreateStruct) == -1)
@@ -184,9 +207,13 @@
   return 0;
}
/// <summary>
/// 用于重新绘制视图。
/// </summary>
/// <returns></returns>
int CMTerm1View::DoReDraw()
{
   // TODO: 在此处添加实现代码.
   CPoint scroll1;
   scroll1 = this->GetScrollPosition();
@@ -209,6 +236,13 @@
   return 0;
}
/// <summary>
/// 滚动到特定单元格
/// 函数内部计算了单元格的总高度,考虑了是否显示注释
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::ScrollToCell(int nRow, int nCol)
{
   int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
@@ -226,36 +260,57 @@
   return 0;
}
/// <summary>
/// 滚动单元格进入视图(未完成的功能)
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::ScrollCellIntoView(int nRow, int nCol)
{
   int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
   return 0;
}
/// <summary>
/// 检查单元格是否在视图中(未完成的功能)
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::isCellInView(int nRow, int nCol)
{
   int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
   return 0;
}
/// <summary>
/// 用于在视图中绘制图形的主要函数
/// </summary>
/// <param name="pDC">文档</param>
/// <returns></returns>
int CMTerm1View::DrawLDSGraph(CDC* pDC)
{
   // TODO: 在此处添加实现代码.
   CString s1;
   CString s1;//没啥用
   //验证文档引用
   CMTerm1Doc* pDoc = GetDocument();
   ASSERT_VALID(pDoc);
   if (!pDoc)   return false;
   if (m_bMonitoring) {
      pDoc->DoPLCMonitor();
   }
   int x1, y1, x2, y2;
   //   RECT rect1;
   int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
   int nDataType, nDataAddr;
   int nStat;
   CBrush br0(BkColor);
   CBrush br01(BkEditColor);
   CBrush br0(BkColor);//背景颜色
   CBrush br01(BkEditColor);//编辑(选中)状态下的背景颜色
   int nRow, nCol;
   CRect rect0;
   this->GetClientRect(&rect0);
@@ -263,19 +318,26 @@
   CPoint scroll1;
   scroll1 = this->GetScrollPosition();
   int nFirstVisibleLine;
   int nLastVisibleLine;
   int nFirstVisibleLine;//用于确定可见行范围-起始位置
   int nLastVisibleLine;//用于确定可见行范围-终止位置
   //通过滚动位置和视图的高度计算上述两个值
   nFirstVisibleLine = (scroll1.y - m_TopMargin) / CellTotalHeight;
   nLastVisibleLine = (rect0.Height() + scroll1.y - m_TopMargin) / CellTotalHeight + 1;
   if (nFirstVisibleLine < 0) { nFirstVisibleLine = 0; }
   if (nLastVisibleLine < 0) { nLastVisibleLine = 0; }
   if (nFirstVisibleLine < 0)
   {
      nFirstVisibleLine = 0;
   }
   if (nLastVisibleLine < 0)
   {
      nLastVisibleLine = 0;
   }
   //选择字体
   CFont *pOldFont;
   pOldFont = (CFont *)pDC->SelectObject(&TextFont);
   for (int i = nFirstVisibleLine; i < nLastVisibleLine && i < 1000; i++) {
   for (int i = nFirstVisibleLine; i < nLastVisibleLine && i < 1000; i++)
   {
      // 画一行 单元
      nRow = i;
      int x0, y0;
@@ -344,24 +406,31 @@
         }
      }
      // 获取数据  并显示各单元
      for (int j = 0; j < m_CellPerLine; j++) {
         nCol = j;
         nDataType = Cells[nRow][nCol].nDataType;
         nDataAddr = Cells[nRow][nCol].nDataAddr;
         if ((nDataType&TYPEDATA) == TYPEDATA) {
            nStat = pDoc->GetVarData(nDataType, nDataAddr);
         if (m_bMonitoring) {
            if ((nDataType & TYPEDATA) == TYPEDATA) {
               nStat = pDoc->GetVarData(nDataType, nDataAddr);
            }
            else {
               nStat = pDoc->GetCoilValue(nDataType, nDataAddr);
            }
            Cells[nRow][nCol].nStat = nStat;
            nType = Cells[nRow][nCol].nType;
            if (nType == typeNO || nType == typeNC || nType == typeCMP || nType == typeTM)
            {
               int nProgStep = Cells[nRow][nCol].nProgStep;
               int nBinProgStep = pDoc->Progs[nProgStep].nBinStep;
               Cells[nRow][nCol].nTrace = pDoc->ProgTrace[nBinProgStep];
            }
         }
         else {
            nStat = pDoc->GetCoilValue(nDataType, nDataAddr);
            Cells[nRow][nCol].nStat = 0; Cells[nRow][nCol].nTrace = 0;
         }
         Cells[nRow][nCol].nStat = nStat;
         nType = Cells[nRow][nCol].nType;
         if (nType == typeNO || nType == typeNC || nType == typeCMP || nType == typeTM)
         {
            int nProgStep = Cells[nRow][nCol].nProgStep;
            int nBinProgStep = pDoc->Progs[nProgStep].nBinStep;
            Cells[nRow][nCol].nTrace = pDoc->ProgTrace[nBinProgStep];
         }
         DrawCell(pDC, i, j);
      }
@@ -393,7 +462,6 @@
   return 0;
}
void  CMTerm1View::DrawFocusRect(CDC* pDC)
{
//   DrawCell(pDC, m_oldFocusRow, m_oldFocusCol);
@@ -422,7 +490,6 @@
//   pDC->SelectObject(poldBrush);
}
int CMTerm1View::DrawLeftRightLine(CDC* pDC, int x0, int y0, int size1, int size2)
{
   // TODO: 在此处添加实现代码.
@@ -444,7 +511,6 @@
   pDC->LineTo(x2, y2);
   return 0;
}
void CMTerm1View::DrawOT(CDC* pDC, int x0, int y0)
{
@@ -527,6 +593,7 @@
   pDC->LineTo(x2, y2);
   return 0;
}
int CMTerm1View::DrawAngleBracket(CDC* pDC, int x0, int y0, int size1, int size2)
{
   // TODO: 在此处添加实现代码.
@@ -534,7 +601,7 @@
   DrawLeftRightLine(pDC, x0, y0, size1, size2);
   // 左尖括号
   x1 = x0 + size1 + 6;
   y1 = y0 + m_LinePosY -6;
   y1 = y0 + m_LinePosY -6;
   x2 = x1 -6;
   y2 = y1 +6 ;
   pDC->MoveTo(x1, y1);
@@ -656,7 +723,7 @@
   int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
   rect1.left = m_LeftMargin + 1 + m_CellWidth * nCol;
   rect1.right = rect1.left + m_CellWidth;
   rect1.right = rect1.left + m_CellWidth;
   rect1.top = m_TopMargin + CellTotalHeight * nRow;
   rect1.bottom = rect1.top + CellTotalHeight;
@@ -670,6 +737,9 @@
      if (needReDraw) {
         pDC->MoveTo(x0, y0);
         pDC->LineTo(x0, y0 + m_LinePosY);
         //画直竖线
         //pDC->MoveTo(x0, y0 + (0.32 * CellTotalHeight));
         //pDC->LineTo(x0, y0 - (0.69 * CellTotalHeight));
      }
   }
   if (Cells[nRow][nCol].bLeftLineDn && nCol != 0)
@@ -694,9 +764,9 @@
   }
   else if (nType == typeLine2)
   {   //Draw Line
      //画直横线
//      pDC->MoveTo(x0, y0);
//      pDC->LineTo(x0, y0 + CellTotalHeight);
      //画直竖线
      pDC->MoveTo(x0, y0 + (0.32 * CellTotalHeight));
      pDC->LineTo(x0, y0 - (0.69 * CellTotalHeight));
   }
   else if (nType == typeNO)
   {
@@ -1085,6 +1155,7 @@
            nCol = 0; 
         }
      }
      CellFocusChg(nRow, nCol);
   }
   if (nChar == VK_RIGHT) {
      nCol += 1;
@@ -1097,15 +1168,17 @@
            nCol = m_CellPerLine - 1;
         }
      }
      CellFocusChg(nRow, nCol);
   }
   if (nChar == VK_UP) {
      nRow -= 1;
      if (nRow < 0) { nRow = 0; }
      CellFocusChg(nRow, nCol);
   }
   if (nChar == VK_DOWN) {
      nRow += 1;
      if (nRow >= m_nTotalRow + nLinesinView) { nRow = m_nTotalRow + nLinesinView -1; }
      CellFocusChg(nRow, nCol);
   }
   m_FocusRow = nRow;
   m_FocusCol = nCol;
@@ -1131,6 +1204,28 @@
   CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}
/// <summary>
/// 单元格焦点变化*选中点变化
/// </summary>
/// <param name="nRow"></param>
/// <param name="nCol"></param>
/// <returns></returns>
int CMTerm1View::CellFocusChg(int nRow, int nCol)
{
   CString s1;
   stCell & thecell = Cells[nRow][nCol];
   s1.Format(_T("Cell %d %d Type %02X \r\n"), nRow, nCol, thecell.nType);
   s1.AppendFormat(_T(" sCoilName %s sParam %s \r\n"), thecell.sCoilName, thecell.sParam );
   s1.AppendFormat(_T("LeftUp %d leftDn %d "), thecell.bLeftLineUp, thecell.bLeftLineDn);
   DbgLog(s1);
   auto p1 = (CMainFrame*)AfxGetMainWnd();
   auto p2 = p1->GetInputWnd();
       p2->SetCurCellPos(nRow,nCol,thecell);
      p2->focusCell = thecell;
   return 0;
}
//鼠标左键点击事件
void CMTerm1View::OnLButtonDown(UINT nFlags, CPoint point)
{
   // TODO: 在此添加消息处理程序代码和/或调用默认值
@@ -1144,10 +1239,21 @@
   int CellTotalHeight = m_CellHeight + (m_bShowComments ? m_CommentHeight : 0);
   nRow = (ty - m_TopMargin) / CellTotalHeight;
   nCol = (tx - m_LeftMargin) / m_CellWidth;
   if (nRow < 0) { nRow = 0; }
   if (nCol < 0) { nCol = 0; }
   if (nCol >= m_CellPerLine) { nCol = m_CellPerLine - 1; }
   s1.Format(_T("LD %d %d  %02X  Scroll %d %d  Total %d %d Row %d Col %d"), point.x, point.y, nFlags, scroll1.x, scroll1.y, tx, ty, nRow, nCol);
   if (nRow < 0)
   {
      nRow = 0;
   }
   if (nCol < 0)
   {
      nCol = 0;
   }
   if (nCol >= m_CellPerLine)
   {
      nCol = m_CellPerLine - 1;
   }
   s1.Format(_T("OnLButtonDown::zxd:: LD %d %d  %02X  Scroll %d %d  Total %d %d Row %d Col %d"), point.x, point.y, nFlags, scroll1.x, scroll1.y, tx, ty, nRow, nCol);
   DbgLog(s1);//zxd add to test
   m_pStatusBar->SetPaneText(6, s1);
   m_FocusRow = nRow;
   m_FocusCol = nCol;
@@ -1156,6 +1262,7 @@
   }
   //   DrawFocusRect();
   CellFocusChg(nRow, nCol);
   GetDocument()->UpdateAllViews(this, m_FocusCol);
   needReDraw = 1;
   this->RedrawWindow();
@@ -1375,16 +1482,27 @@
   pCmdUI->SetCheck(m_bMonitoring == true);
}
/// <summary>
/// 程序转换按钮点击
/// </summary>
void CMTerm1View::OnProgConvert()
{
   // TODO: 在此添加命令处理程序代码
   //转换前先对LDS的规则进行检验(检验规则与返回参数并未完全确定
 //   std::pair<int,CString> result = LDSCheckRule();
   //if (result.first == 111)
   //{
   //   DbgLog(result.second);
   //   return;
   //}
   CString s1;
   s1.Format(_T("Prog Convert"));
   SysLog(s1);
    SysLog(s1);
   int r = TransLDSToProg();
   s1.Format(_T("LDS To Prog result %d"), r);
   SysLog(s1);
   if (r==0) {
   if (r==0)
   {
   //   m_bModified = 0;
      int j=TransProgToLDS();
      s1.Format(_T("Porg to LDS retuls %d"), j);
@@ -1470,20 +1588,73 @@
   return -1;
}
void CMTerm1View::GetIncToView(stCell cell1)               //**************************************************************************************************//
/// <summary>
/// 设置Cell到窗口视图
/// </summary>
/// <param name="cell1"></param>
void CMTerm1View::SetCellToView(stCell cell1, int flag)               //**************************************************************************************************//
{
   bool changeVLine = false;
   if ((Cells[m_FocusRow][m_FocusCol].bLeftLineDn != cell1.bLeftLineDn)
      || (Cells[m_FocusRow][m_FocusCol].bLeftLineUp != cell1.bLeftLineUp))
   {
      changeVLine = true;
   }
   Cells[m_FocusRow][m_FocusCol] = cell1;
   m_bModified = 1;
   needReDraw = 1;
   m_FocusCol += 1;
   Cells[m_FocusRow][0].bEditing = 1;
   if (m_nTotalRow < m_FocusRow + 1)
   {
      m_nTotalRow = m_FocusRow + 1;
   }
   //单元格关联修改
   switch (flag)
   {
   case 1:
   {
      if(Cells[m_FocusRow - 1][m_FocusCol].nType == CMTerm1View::typeExt1)
      {
         //发送错误信息
         DbgLog(_T("插入纵线失败:光标位置错误!参数位置不允许添加纵线"));
         return;
      }
      //添加纵线时同步添加上一行
      Cells[m_FocusRow - 1][m_FocusCol].bLeftLineDn = 1;
   }break;
   case 2:
   {
      if (Cells[m_FocusRow - 1][m_FocusCol].nType == CMTerm1View::typeExt1)
      {
         //发送错误信息
         DbgLog(_T("删除纵线失败:光标位置错误!参数位置不允许删除纵线"));
         return;
      }
      //删除纵线时同步删除上一行
      Cells[m_FocusRow - 1][m_FocusCol].bLeftLineDn = 0;
   }break;
   default:
      break;
   }
   //如果变化的是竖线,焦点不后移
   if (!changeVLine)
   {
      //单元格位置后移
      m_FocusCol += 1;
   }
   if (m_FocusCol >= 16) 
   { m_FocusCol = 0;m_FocusRow += 1; }
   {
      m_FocusCol = 0;
      m_FocusRow += 1;
   }
   this->RedrawWindow();
   this->CellFocusChg(m_FocusRow, m_FocusCol);//改变焦点
}
void CMTerm1View::OnUpdateInsertBlankLine(CCmdUI *pCmdUI)
{
@@ -1770,7 +1941,10 @@
   }
}
/// <summary>
/// 程序数据转为梯形图
/// </summary>
/// <returns></returns>
int CMTerm1View::TransProgToLDS()
{
   CString s1;
@@ -1780,534 +1954,594 @@
   int stpos[100] = { 0 };
   int nSts = 0;
   for (int i = 0; i < m_nTotalRow && i < 2000; i++) {
      for (int j = 0; j < 16; j++) {
   for (int i = 0; i < m_nTotalRow && i < 2000; i++)
   {
      for (int j = 0; j < 16; j++)
      {
         Cells[i][j].clear();
         s1.Format(_T("%d:%d"), i, j);
          s1.Format(_T("%d:%d"), i, j);
         Cells[i][j].sCoilName = s1;
      }
   }
   POINT StPts[100];
   //   StPts[0] = POINT{ 0, 0 };
   POINT EndPt[100];
   POINT StrPt[100];
   int nStrPts = 0;
   int nEndPts = 0;
   nSts = 0;
   int nCurLine = 0;
   int cx = 0, cy = 0;
   int maxy = 0;
   for (int i = 0; i < pDoc->m_nProgSteps; i++)
   try
   {
      int nOp = pDoc->Progs[i].nOpType1;
      int nParamCount = pDoc->Progs[i].nParamCount;
      CStringA OpName;
      CStringA ShowTxt;
      pDoc->OpToTxt(nOp, OpName);
      pDoc->OpToShowTxt(nOp, ShowTxt);
      int nPairTo = pDoc->Progs[i].PairTo;
      int nPairOp = 0;
      if (nPairTo) nPairOp = pDoc->Progs[nPairTo].nOpType1;
      int nCellType;
      switch (nOp)
      for (int i = 0; i < pDoc->m_nProgSteps; i++)
      {
      case OP_NOP:
         break;
      case OP_ST:
      case OP_ST_:
         if (i == 0) {
         int nOp = pDoc->Progs[i].nOpType1;
         int nParamCount = pDoc->Progs[i].nParamCount;
         CStringA OpName;
         CStringA ShowTxt;
         pDoc->OpToTxt(nOp, OpName);
         pDoc->OpToShowTxt(nOp, ShowTxt);
         int nPairTo = pDoc->Progs[i].PairTo;
         int nPairOp = 0;
         if (nPairTo)
         {
            nPairOp = pDoc->Progs[nPairTo].nOpType1;
         }
         else {
            //记录当前位置
            EndPt[nEndPts] = POINT{ cx,cy };
            nEndPts++;
            if (nPairOp == OP_ANS) {
               //继续前进
               //cx = 0, cy = nCurLine;
               //cx = StPts[nSts - 1].x;
               //nCurLine = cy + 1; //另起一行
         int nCellType;
         switch (nOp)
         {
         case OP_NOP:
            break;
         case OP_ST:
         case OP_ST_:
            if (i == 0)
            {
            }
            else
            {
               //记录当前位置
               EndPt[nEndPts] = POINT{ cx,cy };
               nEndPts++;
               if (nPairOp == OP_ANS)
               {
                  //继续前进
                  //cx = 0, cy = nCurLine;
                  //cx = StPts[nSts - 1].x;
                  //nCurLine = cy + 1; //另起一行
///*            
               nCurLine=cy;
               int hasData = 1;
               while (hasData) {
                  hasData = 0;
                  for (int j = cx +1; j < m_CellPerLine; j++) {
                     if (Cells[nCurLine][j].nType != 0) {
                        nCurLine++; hasData = 1; break;
                  nCurLine = cy;
                  int hasData = 1;
                  while (hasData) {
                     hasData = 0;
                     for (int j = cx + 1; j < m_CellPerLine; j++)
                     {
                        if (Cells[nCurLine][j].nType != 0)
                        {
                           nCurLine++; hasData = 1; break;
                        }
                     }
                  }
                  //nCurLine = maxy + 1; //另起一行
                  if (nCurLine > maxy)
                  {
                     maxy = nCurLine;
                  }
                  for (int j = cy; j < nCurLine; j++)
                  {
                     Cells[j][cx].bLeftLineDn = 1;
                     Cells[j + 1][cx].bLeftLineUp = 1;
                  }
                  cy = nCurLine;
                  //*/
               }
               //               nCurLine = maxy + 1; //另起一行
               if (nCurLine > maxy) maxy = nCurLine;
               for (int j = cy; j < nCurLine; j++) {
                  Cells[j][cx].bLeftLineDn = 1;
                  Cells[j + 1][cx].bLeftLineUp = 1;
               }
               cy = nCurLine;
//*/
            }
            else if (nPairOp == OP_ORS) {
               cx = StPts[nSts - 1].x;
               nCurLine = cy + 1; //另起一行
               int hasData = 1;
               while (hasData) {
                  hasData = 0;
                  for (int j = cx; j < m_CellPerLine; j++) {
                     if (Cells[nCurLine][j].nType != 0) {
                        nCurLine++; hasData = 1; break;
               else if (nPairOp == OP_ORS)
               {
                  cx = StPts[nSts - 1].x;
                  nCurLine = cy + 1; //另起一行
                  int hasData = 1;
                  while (hasData)
                  {
                     hasData = 0;
                     for (int j = cx; j < m_CellPerLine; j++)
                     {
                        if (Cells[nCurLine][j].nType != 0)
                        {
                           nCurLine++; hasData = 1; break;
                        }
                     }
                  }
                  //               nCurLine = maxy + 1; //另起一行
                  if (nCurLine > maxy) maxy = nCurLine;
                  for (int j = cy; j < nCurLine; j++)
                  {
                     Cells[j][cx].bLeftLineDn = 1;
                     Cells[j + 1][cx].bLeftLineUp = 1;
                  }
                  cy = nCurLine;
               }
               //               nCurLine = maxy + 1; //另起一行
               if (nCurLine > maxy) maxy = nCurLine;
               for (int j = cy; j < nCurLine; j++) {
                  Cells[j][cx].bLeftLineDn = 1;
                  Cells[j + 1][cx].bLeftLineUp = 1;
               }
               cy = nCurLine;
            }
            else if (nPairOp == 0) {
               nCurLine = maxy + 1; //另起一行
               maxy = nCurLine;
               cx = 0; cy = nCurLine;
            }
         }
         stpos[nSts] = i;
         StPts[nSts] = POINT{ cx,cy };
         nSts++;
         Cells[cy][cx].nType = pDoc->Progs[i].nOpType1 == OP_ST ? typeNO : typeNC; //typeNC
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         cx++;   //移到下一格
         break;
      case OP_ST_EQ:
      case OP_ST_NE:
      case OP_ST_LT:
      case OP_ST_GT:
      case OP_ST_LE:
      case OP_ST_GE:
         if (i == 0) {
               else if (nPairOp == 0)
               {
                  if (i > 0 && nOp == pDoc->Progs[i-1].nOpType1)//如果前面也是ST,那就不换行
                  {
         }
         else {
            //记录当前位置
            EndPt[nEndPts] = POINT{ cx,cy };
            nEndPts++;
            if (nPairOp == OP_ANS) {
               //继续前进
               //cx = 0, cy = nCurLine;
                  }
                  else
                  {
                     nCurLine = ++maxy;
                     cx = 0;
                     cy = nCurLine;
                  }
               }
            }
            else if (nPairOp == OP_ORS) {
               cx = StPts[nSts - 1].x;
               nCurLine = cy + 1; //另起一行
               int hasData = 1;
               while (hasData) {
                  hasData = 0;
                  for (int j = cx; j < m_CellPerLine; j++) {
                     if (Cells[nCurLine][j].nType != 0) {
                        nCurLine++; hasData = 1; break;
            stpos[nSts] = i;
            StPts[nSts] = POINT{ cx,cy };
            nSts++;
            Cells[cy][cx].nType = pDoc->Progs[i].nOpType1 == OP_ST ? typeNO : typeNC; //typeNC
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx++;   //移到下一格
            break;
         case OP_ST_EQ:
         case OP_ST_NE:
         case OP_ST_LT:
         case OP_ST_GT:
         case OP_ST_LE:
         case OP_ST_GE:
            if (i == 0) {
            }
            else {
               //记录当前位置
               EndPt[nEndPts] = POINT{ cx,cy };
               nEndPts++;
               if (nPairOp == OP_ANS) {
                  //继续前进
                  //cx = 0, cy = nCurLine;
               }
               else if (nPairOp == OP_ORS) {
                  cx = StPts[nSts - 1].x;
                  nCurLine = cy + 1; //另起一行
                  int hasData = 1;
                  while (hasData) {
                     hasData = 0;
                     for (int j = cx; j < m_CellPerLine; j++) {
                        if (Cells[nCurLine][j].nType != 0) {
                           nCurLine++; hasData = 1; break;
                        }
                     }
                  }
               }
               //               nCurLine = maxy + 1; //另起一行
               if (nCurLine > maxy) maxy = nCurLine;
               for (int j = cy; j < nCurLine; j++) {
                  Cells[j][cx].bLeftLineDn = 1;
                  Cells[j + 1][cx].bLeftLineUp = 1;
               }
               cy = nCurLine;
            }
            else if (nPairOp == 0) {
               nCurLine = maxy + 1; //另起一行
               maxy = nCurLine;
               cx = 0; cy = nCurLine;
            }
         }
         stpos[nSts] = i;
         StPts[nSts] = POINT{ cx,cy };
         nSts++;
         Cells[cy][cx].nType = typeCMP;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sParam = OpName;
         Cells[cy][cx].sCoilName = ShowTxt;
         Cells[cy][cx + 1].nType = typeExt1;
         Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         Cells[cy][cx + 2].nType = typeExt1;
         Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
         Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
         Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
         cx += 3;   //移到下3格
         break;
      case OP_AN:
      case OP_AN_:
         Cells[cy][cx].nType = nOp == OP_AN ? typeNO : typeNC; //typeNC
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         cx++;
         break;
      case OP_AN_EQ:
      case OP_AN_NE:
      case OP_AN_LT:
      case OP_AN_GT:
      case OP_AN_LE:
      case OP_AN_GE:
         Cells[cy][cx].nType = typeCMP;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sCoilName = ShowTxt;
         Cells[cy][cx + 1].nType = typeExt1;
         Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         Cells[cy][cx + 2].nType = typeExt1;
         Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
         Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
         Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
         cx += 3;
         break;
      case OP_OR:
      case OP_OR_:
         EndPt[nEndPts] = POINT{ cx,cy };
         nEndPts++;
         cx = StPts[nSts - 1].x;
         nCurLine = cy + 1; //另起一行
         {
            int hasData = 1;
            while (hasData) {
               hasData = 0;
               for (int j = cx; j < m_CellPerLine; j++) {
                  if (Cells[nCurLine][j].nType != 0) {
                     nCurLine++; hasData = 1; break;
                  //               nCurLine = maxy + 1; //另起一行
                  if (nCurLine > maxy) maxy = nCurLine;
                  for (int j = cy; j < nCurLine; j++) {
                     Cells[j][cx].bLeftLineDn = 1;
                     Cells[j + 1][cx].bLeftLineUp = 1;
                  }
                  cy = nCurLine;
               }
               else if (nPairOp == 0) {
                  nCurLine = maxy + 1; //另起一行
                  maxy = nCurLine;
                  cx = 0; cy = nCurLine;
               }
            }
         }
         if (nCurLine > maxy)   maxy = nCurLine;
         for (int j = cy; j < nCurLine; j++) {
            Cells[j][cx].bLeftLineDn = 1;
            Cells[j + 1][cx].bLeftLineUp = 1;
         }
         cy = nCurLine;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].nType = nOp == OP_OR ? typeNO : typeNC; //typeNC
         Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         cx++;
         if (cx < EndPt[nEndPts - 1].x)
         {   //本行补齐
            for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
            {
               Cells[cy][j].nType = typeLine1;
            }
            cx = EndPt[nEndPts - 1].x;
         }
         else {
            //前一行补齐
            for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
            {
               Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
            }
            stpos[nSts] = i;
            StPts[nSts] = POINT{ cx,cy };
            nSts++;
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sParam = OpName;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;   //移到下3格
            break;
         }
         //连接上下线
         for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
         {
            Cells[j][cx].bLeftLineDn = 1;
            Cells[j + 1][cx].bLeftLineUp = 1;
         }
         //光标位置, 前一结束点位置
         cy = EndPt[nEndPts - 1].y;
         nEndPts--;
         case OP_AN:
         case OP_AN_:
         break;
      case OP_OR_EQ:
      case OP_OR_NE:
      case OP_OR_LT:
      case OP_OR_GT:
      case OP_OR_LE:
      case OP_OR_GE:
         EndPt[nEndPts] = POINT{ cx,cy };
         nEndPts++;
         cx = StPts[nSts - 1].x;
         nCurLine = cy + 1; //另起一行
         {
            int hasData = 1;
            while (hasData) {
               hasData = 0;
               for (int j = cx; j < m_CellPerLine; j++) {
                  if (Cells[nCurLine][j].nType != 0) {
                     nCurLine++; hasData = 1; break;
                  }
               }
            }
         }
         if (nCurLine > maxy)   maxy = nCurLine;
         for (int j = cy; j < nCurLine; j++) {
            Cells[j][cx].bLeftLineDn = 1;
            Cells[j + 1][cx].bLeftLineUp = 1;
         }
         cy = nCurLine;
         Cells[cy][cx].nType = typeCMP;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sCoilName = ShowTxt;
         Cells[cy][cx + 1].nType = typeExt1;
         Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         Cells[cy][cx + 2].nType = typeExt1;
         Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
         Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
         Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
         cx += 3;
         if (cx < EndPt[nEndPts - 1].x)
         {   //本行补齐
            for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
            {
               Cells[cy][j].nType = typeLine1;
            }
            cx = EndPt[nEndPts - 1].x;
         }
         else {
            //前一行补齐
            for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
            {
               Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
            }
         }
         //连接上下线
         for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
         {
            Cells[j][cx].bLeftLineDn = 1;
            Cells[j + 1][cx].bLeftLineUp = 1;
         }
         //光标位置, 前一结束点位置
         cy = EndPt[nEndPts - 1].y;
         nEndPts--;
         break;
      case OP_NOT:
         Cells[cy][cx].nType = typeNOT;
         Cells[cy][cx].sCoilName = _T("NOT");
         Cells[cy][cx].nProgStep = i;
         cx++;
         break;
      case OP_DF:
      case OP_DF_:
         Cells[cy][cx].nType = nOp == OP_DF ? typeDF : typeDF_;
         Cells[cy][cx].sCoilName = nOp == OP_DF ? _T("DF") : _T("DF/");
         Cells[cy][cx].nProgStep = i;
         cx++;
         break;
      case OP_ANS:
         nSts--;
         nEndPts--;
         break;
      case OP_ORS:
         // 当前序列与前面的序列合并。
         //当前序列的开始结束位置
         //EndPt[nEndPts] = POINT{ cx,cy };
         //nEndPts++;
         //StPts[nSts - 1]; EndPt[nEndPts - 1];
         //前一序列的开始结束位置
         StPts[nSts - 1]; EndPt[nEndPts - 1];
         //判断二者长度
         if (cx < EndPt[nEndPts - 1].x)
         {   //本行补齐
            for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
            {
               Cells[cy][j].nType = typeLine1;
            }
            cx = EndPt[nEndPts - 1].x;
         }
         else {
            //前一行补齐
            for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
            {
               Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
            }
         }
         //连接上下线
         for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
         {
            Cells[j][cx].bLeftLineDn = 1;
            Cells[j + 1][cx].bLeftLineUp = 1;
         }
         //光标位置, 前一结束点位置
         cy = EndPt[nEndPts - 1].y;
         nSts--;
         nEndPts--;
         break;
      case OP_PSHS:
         EndPt[nEndPts] = POINT{ cx,cy };
         nEndPts++;
         break;
      case OP_RDS:
         cx = EndPt[nEndPts - 1].x;
         for (int j = cx; j < m_CellPerLine; j++) {
            if (Cells[cy][j].nType != 0)
            {
               cy++; j = cx - 1; //break;
            }
         }
         for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
         {
            Cells[j][cx].bLeftLineDn = 1;
            Cells[j + 1][cx].bLeftLineUp = 1;
         }
         break;
      case OP_POPS:
         cx = EndPt[nEndPts - 1].x;
         for (int j = cx; j < m_CellPerLine; j++) {
            if (Cells[cy][j].nType != 0)
            {
               cy++; j = cx - 1; break;
            }
         }
         for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
         {
            Cells[j][cx].bLeftLineDn = 1;
            Cells[j + 1][cx].bLeftLineUp = 1;
         }
         nEndPts--;
         break;
      case OP_OUT:
      case OP_SET:
      case OP_RESET:
         nCellType = nOp == OP_OUT ? typeOUT : nOp == OP_SET ? typeSET : typeRESET;
         nCurLine = cy;
         if (cx <= m_CellPerLine) {
            int hasData = 1;
            while (hasData) {
               hasData = 0;
               for (int j = cx; j < m_CellPerLine; j++) {
                  if (Cells[nCurLine][j].nType != 0) {
                     nCurLine++; hasData = 1; break;
                  }
               }
            }
            //if (nCurLine > maxy)   maxy = nCurLine;
            for (int j = cy; j < nCurLine; j++) {
               Cells[j][cx].bLeftLineDn = 1;
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            cy = nCurLine;
            for (int j = cx; j < m_CellPerLine; j++)
            {
               Cells[cy][j].nType = typeLine1;
            }
            Cells[cy][m_CellPerLine - 1].nType = nCellType;
            Cells[cy][m_CellPerLine - 1].nProgStep = i;
            Cells[cy][m_CellPerLine - 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][m_CellPerLine - 1].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][m_CellPerLine - 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][m_CellPerLine - 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         }
         else {
            Cells[cy][cx].nType = nCellType;
            Cells[cy][cx].nType = nOp == OP_AN ? typeNO : typeNC; //typeNC
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx++;
            break;
         case OP_AN_EQ:
         case OP_AN_NE:
         case OP_AN_LT:
         case OP_AN_GT:
         case OP_AN_LE:
         case OP_AN_GE:
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            break;
         case OP_OR:
         case OP_OR_:
            EndPt[nEndPts] = POINT{ cx,cy };
             nEndPts++;
            cx = StPts[nSts - 1].x;
            nCurLine = cy + 1; //另起一行
            {
               int hasData = 1;
               while (hasData)
               {
                  hasData = 0;
                  for (int j = cx; j < m_CellPerLine; j++)
                  {
                     if (Cells[nCurLine][j].nType != 0)
                     {
                        nCurLine++;
                        hasData = 1;
                        break;
                     }
                  }
               }
            }
            if (nCurLine > maxy)
            {
               maxy = nCurLine;
            }
            for (int j = cy; j < nCurLine; j++)
            {
               Cells[j][cx].bLeftLineDn = 1;
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            cy = nCurLine;
            StPts[nSts] = POINT{ cx,cy };//+++
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].nType = nOp == OP_OR ? typeNO : typeNC; //typeNC
            Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx++;
            //if (cx <= EndPt[nEndPts - 1].x)
            //{   //本行补齐
            //   for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
            //   {
            //      Cells[cy][j].nType = typeLine1;
            //   }
            //   cx = EndPt[nEndPts - 1].x;
            //}
            //else {
            //   //前一行补齐
            //   for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
            //   {
            //      Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
            //   }
            //}
            //连接上下线
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
               Cells[j][cx].bLeftLineDn = 1;
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            //光标位置, 前一结束点位置
            cy = EndPt[nEndPts - 1].y;
            nEndPts--;
            break;
         case OP_OR_EQ:
         case OP_OR_NE:
         case OP_OR_LT:
         case OP_OR_GT:
         case OP_OR_LE:
         case OP_OR_GE:
            EndPt[nEndPts] = POINT{ cx,cy };
            nEndPts++;
            cx = StPts[nSts - 1].x;
            nCurLine = cy + 1; //另起一行
            {
               int hasData = 1;
               while (hasData) {
                  hasData = 0;
                  for (int j = cx; j < m_CellPerLine; j++) {
                     if (Cells[nCurLine][j].nType != 0) {
                        nCurLine++; hasData = 1; break;
                     }
                  }
               }
            }
            if (nCurLine > maxy)   maxy = nCurLine;
            for (int j = cy; j < nCurLine; j++) {
               Cells[j][cx].bLeftLineDn = 1;
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            cy = nCurLine;
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            if (cx < EndPt[nEndPts - 1].x)
            {   //本行补齐
               for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
               {
                  Cells[cy][j].nType = typeLine1;
               }
               cx = EndPt[nEndPts - 1].x;
            }
            else {
               //前一行补齐
               for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
               {
                  Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
               }
            }
            //连接上下线
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
               Cells[j][cx].bLeftLineDn = 1;
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            //光标位置, 前一结束点位置
            cy = EndPt[nEndPts - 1].y;
            nEndPts--;
            break;
         case OP_NOT:
            Cells[cy][cx].nType = typeNOT;
            Cells[cy][cx].sCoilName = _T("NOT");
            Cells[cy][cx].nProgStep = i;
            cx++;
            break;
         case OP_DF:
         case OP_DF_:
            Cells[cy][cx].nType = nOp == OP_DF ? typeDF : typeDF_;
            Cells[cy][cx].sCoilName = nOp == OP_DF ? _T("DF") : _T("DF/");
            Cells[cy][cx].nProgStep = i;
            cx++;
            break;
         case OP_ANS:
            //ANS说明是有环路,整行进行移动(向右)从后向前进行移动
            EndPt[nEndPts].y;
            for (int i = EndPt[nEndPts-1].x ; i > 0; i--)
            {
               for (int j = EndPt[nEndPts].x; j >= 0; j--)
               {
                  if (j > 0
                     && Cells[cy + 1][j-1].nType == typeNone
                     || Cells[cy + 1][j - 1].nType == typeLine1
                     || Cells[cy + 1][j - 1].nType == typeLine2)
                  {
                     continue;
                  }
                  Cells[cy + 1][j] = Cells[cy + 1][j - 1];
               }
            }
            Cells[EndPt[nEndPts].y][EndPt[nEndPts-1].x].bLeftLineDn = 1;
            Cells[EndPt[nEndPts].y+1][EndPt[nEndPts-1].x].bLeftLineUp = 1;
            nSts--;
            nEndPts--;
            break;
         case OP_ORS:
            if (nEndPts <= 0)
            {
               break;
            }
            //判断二者长度
            if (cx < EndPt[nEndPts - 1].x)
            {
               //本行补齐
               for (int j = cx; j < EndPt[nEndPts - 1].x; j++)
               {
                  Cells[cy][j].nType = typeLine1;
               }
               cx = EndPt[nEndPts - 1].x;
            }
            else
            {
               //前一行补齐
               for (int j = EndPt[nEndPts - 1].x; j < cx; j++)
               {
                  if (Cells[EndPt[nEndPts - 1].y][j].nType == typeNone)
                  {
                     Cells[EndPt[nEndPts - 1].y][j].nType = typeLine1;
                  }
               }
            }
            //连接上下线
            Cells[cy][cx].bLeftLineUp = 1;
            Cells[cy-1][cx].bLeftLineDn = 1;
            //光标位置, 前一结束点位置
            nSts--;
            nEndPts--;
            cy = EndPt[nEndPts].y;
            cx = EndPt[nEndPts].x;
            break;
         case OP_PSHS:
            StrPt[nStrPts] = POINT{ EndPt[nEndPts].x,EndPt[nEndPts].y+1 };
            nStrPts++;
            break;
         case OP_RDS:
            cx = EndPt[nEndPts - 1].x;
            for (int j = cx; j < m_CellPerLine; j++) {
               if (Cells[cy][j].nType != 0)
               {
                  cy++; j = cx - 1; //break;
               }
            }
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
               Cells[j][cx].bLeftLineDn = 1;
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            break;
         case OP_POPS:
            nStrPts--;
            cy = StrPt[nStrPts].y;
            cx = StrPt[nStrPts].x;
            break;
         case OP_OUT:
         case OP_SET:
         case OP_RESET:
            nCellType = nOp == OP_OUT ? typeOUT : nOp == OP_SET ? typeSET : typeRESET;
            nCurLine = cy;
            if (cx <= m_CellPerLine) {
               int hasData = 1;
               while (hasData) {
                  hasData = 0;
                  for (int j = cx; j < m_CellPerLine; j++) {
                     if (Cells[nCurLine][j].nType != 0) {
                        nCurLine++; hasData = 1; break;
                     }
                  }
               }
               //if (nCurLine > maxy)   maxy = nCurLine;
               for (int j = cy; j < nCurLine; j++) {
                  Cells[j][cx].bLeftLineDn = 1;
                  Cells[j + 1][cx].bLeftLineUp = 1;
               }
               cy = nCurLine;
               for (int j = cx; j < m_CellPerLine; j++)
               {
                  Cells[cy][j].nType = typeLine1;
               }
               Cells[cy][m_CellPerLine - 1].nType = nCellType;
               Cells[cy][m_CellPerLine - 1].nProgStep = i;
               Cells[cy][m_CellPerLine - 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
               Cells[cy][m_CellPerLine - 1].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
               Cells[cy][m_CellPerLine - 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
               Cells[cy][m_CellPerLine - 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            }
            else {
               Cells[cy][cx].nType = nCellType;
               Cells[cy][cx].nProgStep = i;
               Cells[cy][cx].sParam = pDoc->Progs[i].Params[0].sParamStr;
               Cells[cy][cx].sCoilName = pDoc->Progs[i].Params[0].sParamStr;
               Cells[cy][cx].nDataType = pDoc->Progs[i].Params[0].nParamType;
               Cells[cy][cx].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            }
            if (cy > maxy) { maxy = cy; }
            //cy++;
            break;
         case OP_TML:
         case OP_TMR:
         case OP_TMX:
         case OP_TMY:
            Cells[cy][cx].nType = typeTM;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = KLDataTypeEV;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            break;
         case OP_INC:
         case OP_DEC:
            Cells[cy][cx].nType = typeFN1;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            cx += 2;
            break;
         case OP_MV:
         case OP_ADD2:
         case OP_SUB2:
            Cells[cy][cx].nType = typeFN2;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            cx += 3;
            break;
         case OP_ADD3:
         case OP_SUB3:
         case OP_MUL:
         case OP_DIV:
            Cells[cy][cx].nType = typeFN3;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
            Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
            Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
            Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
            Cells[cy][cx + 2].nType = typeExt1;
            Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
            Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
            Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
            Cells[cy][cx + 3].nType = typeExt1;
            Cells[cy][cx + 3].sParam = pDoc->Progs[i].Params[2].sParamStr;
            Cells[cy][cx + 3].nDataType = pDoc->Progs[i].Params[2].nParamType;
            Cells[cy][cx + 3].nDataAddr = pDoc->Progs[i].Params[2].nParamAddr;
            cx += 4;
            break;
         default:
            break;
         }
         if (cy > maxy) { maxy = cy; }
         //cy++;
         break;
      case OP_TML:
      case OP_TMR:
      case OP_TMX:
      case OP_TMY:
         Cells[cy][cx].nType = typeTM;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sCoilName = ShowTxt;
         Cells[cy][cx + 1].nType = typeExt1;
         Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx + 1].nDataType = KLDataTypeEV;
         Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         Cells[cy][cx + 2].nType = typeExt1;
         Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
         Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
         Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
         cx += 3;
         break;
      case OP_INC:
      case OP_DEC:
         Cells[cy][cx].nType = typeFN1;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sCoilName = ShowTxt;
         Cells[cy][cx + 1].nType = typeExt1;
         Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         cx += 2;
         break;
      case OP_MV:
      case OP_ADD2:
      case OP_SUB2:
         Cells[cy][cx].nType = typeFN2;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sCoilName = ShowTxt;
         Cells[cy][cx + 1].nType = typeExt1;
         Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         Cells[cy][cx + 2].nType = typeExt1;
         Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
         Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
         Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
         cx += 3;
         break;
      case OP_ADD3:
      case OP_SUB3:
      case OP_MUL:
      case OP_DIV:
         Cells[cy][cx].nType = typeFN3;
         Cells[cy][cx].nProgStep = i;
         Cells[cy][cx].sCoilName = ShowTxt;
         Cells[cy][cx + 1].nType = typeExt1;
         Cells[cy][cx + 1].sParam = pDoc->Progs[i].Params[0].sParamStr;
         Cells[cy][cx + 1].nDataType = pDoc->Progs[i].Params[0].nParamType;
         Cells[cy][cx + 1].nDataAddr = pDoc->Progs[i].Params[0].nParamAddr;
         Cells[cy][cx + 2].nType = typeExt1;
         Cells[cy][cx + 2].sParam = pDoc->Progs[i].Params[1].sParamStr;
         Cells[cy][cx + 2].nDataType = pDoc->Progs[i].Params[1].nParamType;
         Cells[cy][cx + 2].nDataAddr = pDoc->Progs[i].Params[1].nParamAddr;
         Cells[cy][cx + 3].nType = typeExt1;
         Cells[cy][cx + 3].sParam = pDoc->Progs[i].Params[2].sParamStr;
         Cells[cy][cx + 3].nDataType = pDoc->Progs[i].Params[2].nParamType;
         Cells[cy][cx + 3].nDataAddr = pDoc->Progs[i].Params[2].nParamAddr;
         cx += 4;
         break;
      default:
         break;
      }
   }
   catch (const std::exception&)
   {
      DbgLog(_T("无法绘制图形(程序不合理)"));
   }
   m_nTotalRow = maxy + 1;
   /*
      for (int i = 0; i < 25; i++)
@@ -2323,45 +2557,73 @@
   needReDraw = 1;
   return 0;
}
bool firstCoil = true;//本段第一个单元格
bool isPops = false;
/// <summary>
/// 梯形图转Prog
/// </summary>
/// <returns></returns>
int CMTerm1View::TransLDSToProg()
{
   // TODO: 在此处添加实现代码.
   CMTerm1Doc * pDoc = GetDocument();
   CString s1;
   s1.Format(_T("Trans LDS to PRrog"));
   DbgLog(s1);
   s1.Format(_T("将梯形图转成prog格式"));
   DbgLog(s1);
   //梯形图 数量
   //梯形图 ROW数量
   s1.Format(_T("总计行数 %d"), m_nTotalRow);
   DbgLog(s1);
   s1.Format(_T("Total Lines %d"), m_nTotalRow);
   DbgLog(s1);
   //分段
   int nDivCount = 0;
   //分段 点集合
   int Divs[100] = { 0 };
   for (int i = 0; i < m_nTotalRow; i++)   {
   for (int i = 0; i < m_nTotalRow; i++)
   {
      int nRow = i;
      int bConnected = 0;
      for (int j = 0; j < m_CellPerLine; j++)      {
       for (int j = 0; j < m_CellPerLine; j++)
      {
         int nCol = j;
         if (Cells[nRow][nCol].bLeftLineDn) {
            bConnected = 1; break;
         if (Cells[nRow][nCol].bLeftLineDn)
         {
            bConnected = 1;
            s1.Format(_T("row==%d col==%d 有左下竖线!!!"), nRow,nCol);
            DbgLog(s1);
            break;
         }
      }
      if (!bConnected) {
        }
      if (!bConnected)
      {
         //找到一处分界点
         Divs[nDivCount] = i;
         s1.Format(_T("Div at Line %d "), nRow);
         s1.Format(_T("Div at Line %d 是 ::::::::::::分界点"), nRow);
         DbgLog(s1);
         nDivCount++;
      }
   }
   stProgSection allprogs;
    stProgSection allprogs;
   //每段单独处理
   for (int i = 0; i < nDivCount; i++)   {
   for (int i = 0; i < nDivCount; i++)
   {
      int nStartLine, nEndLine;
      if (i == 0) { nStartLine = 0; nEndLine = Divs[i]; }
      else { nStartLine = Divs[i - 1]+1; nEndLine = Divs[i]; }
      if (i == 0)
      {
         nStartLine = 0;
         nEndLine = Divs[i];
       }
      else
      {
         nStartLine = Divs[i - 1]+1;
         nEndLine = Divs[i];
      }
      s1.Format(_T("本段行号 起始-终止: %d - %d "), nStartLine, nEndLine);
      DbgLog(s1);
      s1.Format(_T("Process Line %d - %d "), nStartLine, nEndLine);
      DbgLog(s1);
      int nCounts[20] = { 0 };
@@ -2369,35 +2631,50 @@
      int nCounts3[20] = { 0 };
      s1.Empty();
      for (int j = 0; j < m_CellPerLine; j++)   {
      for (int j = 0; j < m_CellPerLine; j++)
      {
         int nCount = 0;
         int nCount2 = 0;
         int nCount3 = 0;
         for (int k = nStartLine; k <= nEndLine; k++) {
            if (Cells[k][j].nType) {
         for (int k = nStartLine; k <= nEndLine; k++)
         {
            if (Cells[k][j].nType)
            {
               nCount += 1;
               nCount2 += 1;
               nCount3 += 1;
               if (Cells[k][j].bLeftLineUp) nCount2 -= 1;
               if (Cells[k][j].bLeftLineUp)
               {
                  nCount2 -= 1;
               }
//               if (Cells[k][j].bLeftLineDn) nCount2 -= 1;
               if (j != m_CellPerLine - 1)   {
                  if (Cells[k][j + 1].bLeftLineUp) nCount3 -= 1;
               if (j != m_CellPerLine - 1)
               {
                  if (Cells[k][j + 1].bLeftLineUp)
                  {
                     nCount3 -= 1;
                  }
//                  if (Cells[k][j + 1].bLeftLineDn) nCount3 -= 1;
               }
            }
         }
         nCounts[j] = nCount;
         nCounts2[j] = nCount2;
         nCounts3[j] = nCount3;
      }
      s1.Empty();
      for (int j = 0; j < m_CellPerLine; j++) {
      for (int j = 0; j < m_CellPerLine; j++)
      {
         s1.AppendFormat(_T(" %d(%d)"), nCounts[j],nCounts3[j]);
      }
      DbgLog(_T(""));
      DbgLog(s1);
      s1.Empty();
      for (int j = 0; j < m_CellPerLine; j++)   {
      for (int j = 0; j < m_CellPerLine; j++)
      {
         s1.AppendFormat(_T(" %d "), nCounts2[j]);
      }
      DbgLog(s1);
@@ -2408,22 +2685,39 @@
      CString sProg;
      int nAllSteps=0;
      stProgSection Progsec;
      for (int i = nStartLine; i <= nEndLine; i++){
      for (int i = nStartLine; i <= nEndLine; i++)
      {
         CString sProgSec;
         int nSteps = 0;;
         nCurPosY = i;
         stProgSection thisprogsec;
         if (Cells[i][0].nType)
         ScanLDSCells(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec,nSteps);
         sProg += sProgSec;
         nAllSteps += nSteps;
         Progsec += thisprogsec;
         {
            firstCoil = true;
            //循环遍历单元格(转换的逻辑在这个函数)
            //ScanLDSCells(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec, nSteps);
            //ScanLDSCells2(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec, nSteps);
         }
         //sProg += sProgSec;
       //   nAllSteps += nSteps;
         //Progsec += thisprogsec;
      }
      CString sProgSec;
      int nSteps = 0;;
      nCurPosY = i;
      stProgSection thisprogsec;
      ScanLDSCells2(nStartLine, nEndLine, nCurPosY, nCurPosX, 16,0, thisprogsec, sProgSec, nSteps);
      sProg += sProgSec;
      nAllSteps += nSteps;
      Progsec += thisprogsec;
      DbgLog(_T("\r\n")+ sProg);
      int n = int(Progsec.Progs.size());
      s1.Format(_T("程序段步数: %d "), n);
      DbgLog(s1);
      s1.Format(_T("progSec steps %d "), n);
      DbgLog(s1);
      for (int i = 0; i < n; i++) {
      for (int i = 0; i < n; i++)
      {
         int optype = Progsec.Progs[i].nOpType1;
         CStringA OpTxtA, OpShowTxtA;
         CString OpTxt, OpShowTxt;
@@ -2436,12 +2730,18 @@
      }
      allprogs += Progsec;
   }
   //输出程序
   int n=(int)allprogs.Progs.size();
   s1.Format(_T("总程序步数 %d "), n);
   DbgLog(s1);
   s1.Format(_T("all prog steps %d "), n);
   DbgLog(s1);
   for (int i = 0; i < n; i++)   {
   for (int i = 0; i < n; i++)
   {
      int optype=allprogs.Progs[i].nOpType1;
      allprogs.Progs[i].PairTo = 0;//??????????
      allprogs.Progs[i].nBinStep = i;
      CStringA OpTxtA,OpShowTxtA;
      CString OpTxt,OpShowTxt;
      pDoc->OpToTxt(optype, OpTxtA);
@@ -2449,250 +2749,162 @@
      OpTxt = OpTxtA;
      OpShowTxt = OpShowTxtA;
      s1.Format(_T("%d %s %s"), optype, OpTxt, OpShowTxt);
      pDoc->Progs[i] = allprogs.Progs[i];
//      DbgLog(s1);
   }
   pDoc->m_nProgSteps = n;
   return 0;
}
int CMTerm1View::ScanLDSCells(int nStartLine, int nEndLine, int nPosY, int nPosX, int nLevel, stProgSection & progsec, CString & sProgSec, int &nSteps)
/// <summary>
/// :绘制每个单元格的内容
/// </summary>
/// <param name="nStartLine"></param>
/// <param name="nEndLine"></param>
/// <param name="nPosY">行</param>
/// <param name="nPosX">列</param>
/// <param name="nLevel">层级</param>
/// <param name="progsec">prog格式的指令集</param>
/// <param name="sProgSec">指令集</param>
/// <param name="nSteps">程序步数</param>
/// <returns></returns>
int CMTerm1View::ScanLDSCells(int nStartLine, int nEndLine, int nPosY, int nPosX,
   int nLevel, stProgSection & progsec, CString & sProgSec, int &nSteps)
{
   // TODO: 在此处添加实现代码.
   CString s1;
   int nCurPosX, nCurPosY;
   int nNextX = 1;
   int nNextX = 1;//步长(下个起始点移动的距离)
   nCurPosY = nPosY;
   nCurPosX = nPosX;
   for (int j = nPosX; j < m_CellPerLine; j+=nNextX) {
   int nCoilType, CoilAddr;
   CMTerm1Doc* pDoc = GetDocument();
   for (int j = nPosX; j < m_CellPerLine; j += nNextX)
   {
      nCurPosX = j;
      //先处理当前单元;
      //先处理当前单元基本信息;
      int nType = Cells[nCurPosY][nCurPosX].nType;
      CString sCellName = Cells[nCurPosY][nCurPosX].sCoilName;
      CMTerm1Doc::stProg theprog;
      CStringA sCellNameA;
      sCellNameA = sCellName;
      if (nType == typeNO) {
         if (j==0) {
            s1.Format(_T("%d %d ST %s"), nCurPosY, nCurPosX,sCellName);
            sProgSec.AppendFormat(_T("ST %s\r\n"),sCellName);
            theprog.nOpType1 = OP_ST;
            progsec.Append(theprog);
         }
         else {
            s1.Format(_T("%d %d AN %s"), nCurPosY, nCurPosX, sCellName);
            sProgSec.AppendFormat(_T("NO %s\r\n"), sCellName);
            theprog.nOpType1 = OP_AN;
            progsec.Append(theprog);
         }
         nSteps += 1;
         DbgLog(s1);
         nNextX =  1;
      }else
      if (nType == typeNC) {
         if (j == 0) {
            s1.Format(_T("%d %d ST/ %s"), nCurPosY, nCurPosX, sCellName);
            sProgSec.AppendFormat(_T("ST/ %s\r\n"), sCellName);
            theprog.nOpType1 = OP_ST_;
            progsec.Append(theprog);
         }
         else
         {
            s1.Format(_T("%d %d AN/ %s"), nCurPosY, nCurPosX, sCellName);
            sProgSec.AppendFormat(_T("AN/ %s\r\n"), sCellName);
            theprog.nOpType1 = OP_AN_;
            progsec.Append(theprog);
         }
         DbgLog(s1);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typePP) {
         s1.Format(_T("%d %d PP %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         //progsec.Append(theprog);
         sProgSec.AppendFormat(_T("PP %s\r\n"), sCellName);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typePN) {
         s1.Format(_T("%d %d PN %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         //progsec.Append(theprog);
         sProgSec.AppendFormat(_T("PN %s\r\n"), sCellName, sCellName);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typeNOT) {
         s1.Format(_T("%d %d NOT %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("NOT %s\r\n"), sCellName);
         theprog.nOpType1 = OP_NOT;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typeDF) {
         s1.Format(_T("%d %d DF %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("DF %s\r\n"), sCellName);
         theprog.nOpType1 = OP_DF;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typeDF_) {
         s1.Format(_T("%d %d DF/ %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("DF/ %s\r\n"), sCellName);
         theprog.nOpType1 = OP_DF_;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typeOUT) {
         s1.Format(_T("%d %d OUT %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("OUT %s\r\n"), sCellName);
         theprog.nOpType1 = OP_OUT;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typeSET) {
         s1.Format(_T("%d %d SET %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("SET %s\r\n"), sCellName);
         theprog.nOpType1 = OP_SET;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typeRESET) {
         s1.Format(_T("%d %d RESET %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("RESET %s\r\n"), sCellName);
         theprog.nOpType1 = OP_RESET;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX =  1;
      }else
      if (nType == typeCMP) {
         s1.Format(_T("%d %d CMP %s %s %s"), nCurPosY, nCurPosX, sCellName,Cells[nCurPosY][nCurPosX+1].sParam,Cells[nCurPosY][nCurPosX + 2].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_ST_GT;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("CMP %s %s %s \r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         nSteps += 1;
         nNextX =  3;
      }else
      if (nType == typeTM) {
         s1.Format(_T("%d %d TM %s %d %s"), nCurPosY, nCurPosX, sCellName,Cells[nCurPosY][nCurPosX+1].sParam,Cells[nCurPosY][nCurPosX + 2].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_TMX;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("TM %s %d %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX+1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         nSteps += 1;
         nNextX =  3;
      }else
      if (nType == typeFN1) {
         s1.Format(_T("%d %d FN1 %s %s"), nCurPosY, nCurPosX, sCellName,Cells[nCurPosY][nCurPosX + 1].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_INC;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("FN1 %s %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam);
         nSteps += 1;
         nNextX =  2;
      }else
      if (nType == typeFN2) {
         s1.Format(_T("%d %d FN2 %s %s %s "), nCurPosY, nCurPosX, sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_MV;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("FN2 %s %s %s \r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         nSteps += 1;
         nNextX =  3;
      }else
      if (nType == typeFN3) {
         s1.Format(_T("%d %d FN3 %s %s %s %s"), nCurPosY, nCurPosX, sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam, Cells[nCurPosY][nCurPosX + 3].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_ADD3;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("FN3 %s %s %s %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam, Cells[nCurPosY][nCurPosX + 3].sParam);
         nSteps += 1;
         nNextX =  4;
      }else {
         nNextX =  1;
         //continue;
      if (j + nNextX >= m_CellPerLine)
      {
         continue;
      }
      if (j + nNextX >= m_CellPerLine) continue;
      if (Cells[nCurPosY][j + nNextX].bLeftLineUp || Cells[nCurPosY][j + nNextX].bLeftLineDn) {   // 发现竖线
      //1.先获取此单元格右侧一格的竖线
      if (Cells[nCurPosY][j + nNextX].bLeftLineUp
         || Cells[nCurPosY][j + nNextX].bLeftLineDn)
      {
         //先看往上面有没有连接
         if (Cells[nCurPosY][j + nNextX].bLeftLineUp) { // 往上面有连接
         if (Cells[nCurPosY][j + nNextX].bLeftLineUp)
         {
            // 往上面有连接且有触点连接,才使用ORS
            s1.Format(_T("%d %d ORS "), nCurPosY, nCurPosX);
            DbgLog(s1);
            theprog.nOpType1 = OP_ORS;
            progsec.Append(theprog);
            sProgSec.AppendFormat(_T("ORS \r\n"));
            firstCoil = false;
            nSteps += 1;
            nLevel -= 1;
         }
         //右侧一格的左上是否有链接
         int nLeftUpCon = 0;
         if (Cells[nCurPosY][j + nNextX].bLeftLineUp ) nLeftUpCon = 1;
         //向下查找,看看竖线的左侧下面还有没有连接其他东西/
         int nLeftDnCon = 0;
         for (int k = nCurPosY + 1; k <= nEndLine; k++) {
            if (!Cells[k][j + nNextX].bLeftLineUp) break;  // 竖线到最下面的端点了。
            if (Cells[k][j + nNextX - 1 ].nType) { nLeftDnCon += 1; break; }
         if (Cells[nCurPosY][j + nNextX].bLeftLineUp)
         {
            nLeftUpCon = 1;
         }
         //向下查找,看看竖线的右侧一格的左侧下面还有没有连接其他东西
         int nLeftDnCon = 0;//单元格右侧一格的左侧向下连接数
         for (int k = nCurPosY; k <= nEndLine; k++)
         {
            if (Cells[k][j + nNextX].bLeftLineDn)
            {
               if (Cells[k][j + nNextX - 1].nType)
               {
                  nLeftDnCon += 1;
               }
            }
            else
            {
               break;  // 竖线到最下面的端点了。
            }
         }
         s1.Format(_T("LeftUp %d   LeftDn  %d"), nLeftUpCon, nLeftDnCon);
         DbgLog(s1);
         if (nLeftDnCon) {   //左侧有连接,那么扫描到这个竖线,继续扫描左侧下面的内容。
         //右侧一格的左侧下面有连接,那么扫描到这个竖线时返回,继续扫描左侧下面的内容。
         if (nLeftDnCon)
         {
            return 1;
         }
         if (!nLeftDnCon) {// 左侧下面没有连接,那么这个就是左面最后的单元,开始处理右面的单元。
            if (nLeftUpCon) {
               if ( nPosX >0 || nLevel > 0) {
               s1.Format(_T("%d %d ANS "), nCurPosY, nCurPosX);
               DbgLog(s1);
               theprog.nOpType1 = OP_ANS;
               progsec.Append(theprog);
               sProgSec.AppendFormat(_T("ANS \r\n"));
               nSteps += 1;
               nLevel -= 1;
            }
         //右侧一格的左侧下面没有连接,那么这个就是左面最后的单元,开始处理右面的单元。
         else
         {
            if (nLeftUpCon)
            {
               if (nPosX > 0 || nLevel > 0)
               {
                  s1.Format(_T("%d %d ANS "), nCurPosY, nCurPosX);
                  DbgLog(s1);
                  theprog.nOpType1 = OP_ANS;
                  progsec.Append(theprog);
                  sProgSec.AppendFormat(_T("ANS \r\n"));
                  nSteps += 1;
                  nLevel -= 1;
               }
            }
            //从头到尾处理, 查找此竖线的最高位置;
            int nLineTop = nCurPosY;
            int nLineBottom = nCurPosY;
            for (int k = nCurPosY; k >= nStartLine; k--)
            {
               if (!Cells[k][j + nNextX].bLeftLineUp) {  break; }
               nLineTop = k -1;
               if (!Cells[k][j + nNextX].bLeftLineUp)
               {
                  break;
               }
               nLineTop = k - 1;
            }
            // 查找右侧有几个连接
            int nRightCon = 0;
            for (int k = nLineTop; k <= nEndLine; k++) {
               if (Cells[k][j + nNextX].nType) { nRightCon += 1; }
            int nRightCon = 0;//单元格右侧连接数
            for (int k = nLineTop; k <= nEndLine; k++)
            {
               if (Cells[k][j + nNextX].nType)
               {
                  nRightCon += 1;
               }
               nLineBottom = k;
               if (!Cells[k][j + nNextX].bLeftLineDn) { break; }
               if (!Cells[k][j + nNextX].bLeftLineDn)
               {
                  break;
               }
            }
            s1.Format(_T("VLine %d - %d : %d , right = %d "), nLineTop,nLineBottom,j+nNextX,nRightCon);
            s1.Format(_T("VLine %d - %d : %d , right = %d "), nLineTop, nLineBottom, j + nNextX, nRightCon);
            DbgLog(s1);
            if (nRightCon == 1) {
               s1.Format(_T(">>>> Go %d : %d , level %d "), nLineTop, j + nNextX, nLevel);
            if (nRightCon == 1)
            {
                s1.Format(_T(">>>> Go %d : %d , level %d "), nLineTop, j + nNextX, nLevel);
               DbgLog(s1);
               CString ProgSec;
               int theSteps = 0;
               stProgSection thisprogsec;
               int r = ScanLDSCells(nStartLine, nEndLine, nLineTop, j + nNextX, nLevel,thisprogsec, ProgSec,theSteps);
               //这有问题,应该是在最高点的时候,单独进行一次转换?
               int r = ScanLDSCells(nStartLine, nEndLine, nLineTop, j + nNextX, nLevel, thisprogsec, ProgSec, theSteps);
               sProgSec += ProgSec;
               nSteps += theSteps;
               progsec += thisprogsec;
               s1.Format(_T("<<<< Re %d : %d , Result %d "), nLineTop, j + nNextX, r);
               s1.Format(_T("<<<< Re %d : %d , Result %d "), nLineTop, j + nNextX, 0);
               DbgLog(s1);
               continue;
            }
            else
            {
@@ -2706,35 +2918,46 @@
               {
                  //s1.Format(_T("VLine %d - %d : %d       %d of %d "), nLineTop, nLineBottom, j + nNextX, k+1,nRightCon);
                  //DbgLog(s1);
                  if (Cells[k][j + nNextX].nType) {
                     s1.Format(_T(" >>> Go %d : %d , level %d "), k, j + nNextX, nLevel +1);
                  if (Cells[k][j + nNextX].nType)
                  {
                     s1.Format(_T(" >>> Go %d : %d , level %d "), k, j + nNextX, nLevel + 1);
                     DbgLog(s1);
                     CString ProgSec;
                     int theSteps = 0;
                     nLevel += 1;
                     stProgSection thisprogsec;
                     res[nRightCount] = ScanLDSCells(nStartLine, nEndLine, k, j + nNextX, nLevel ,thisprogsec,ProgSecs[nRightCount],theSteps);
                     res[nRightCount] = ScanLDSCells(nStartLine, nEndLine, k, j + nNextX, nLevel, thisprogsec, ProgSecs[nRightCount], theSteps);
                     nLastResult = res[nRightCount];
                     nSteps += theSteps;
                     progsec += thisprogsec;
                     //if (res[nRightCount] > 0) nLevel += 1;
                     sProgSec += ProgSec;
                     s1.Format(_T(" <<< Re %d : %d , Result %d Steps %d Last %d"), k, j + nNextX, res[nRightCount],theSteps,nLastSteps);
                     s1.Format(_T(" <<< Re %d : %d , Result %d Steps %d Last %d"), k, j + nNextX, res[nRightCount], theSteps, nLastSteps);
                     DbgLog(s1);
                     if (nRightCount == 0) {
                     if (nRightCount == 0)
                     {
                        //这里是不是应该做点什么
                     }
                     else if (res[nRightCount-1] == 0) {
                     else if (res[nRightCount - 1] == 0)
                     {
                        s1.Format(_T(" POPS"), k, j + nNextX, nLevel + 1);
                        DbgLog(s1);
                        //sProgSec.AppendFormat(_T("POPS \r\n"));
                        if (nLastSteps > 1)
                        if (nLastSteps > 1)
                        {
                           if (sCons[nRightCount - 1] == _T("POPS")) { sCons[nRightCount - 1] = _T("RDS"); }
                           else { sCons[nRightCount - 1] = _T("PSHS"); }
                           if (sCons[nRightCount - 1] == _T("POPS"))
                           {
                              sCons[nRightCount - 1] = _T("RDS");
                           }
                           else
                           {
                              sCons[nRightCount - 1] = _T("PSHS");
                           }
                           sCons[nRightCount] = _T("POPS");
                        }
                     }
                     else {
                     else
                     {
                     }
                     nLastSteps = theSteps;
@@ -2744,17 +2967,704 @@
               nLastResult = 0;
               for (int k = 0; k < nRightCount; k++)
               {
                  if (nLastResult || res[k]) { s1 = _T("ST") + ProgSecs[k];  ProgSecs[k] =s1; }
                  s1= sCons[k] + _T("\r\n") + ProgSecs[k];
                  if (nLastResult || res[k])
                  {
                     s1 = _T("ST") + ProgSecs[k];
                     ProgSecs[k] = s1;
                  }
                  s1 = sCons[k] + _T("\r\n") + ProgSecs[k];
                  sProgSec.Append(s1);
                  nLastResult = res[k];
               }
               if (nLastResult) sProgSec.Append(_T("ANS\r\n"));
               if (nLastResult)
               {
                  sProgSec.Append(_T("ANS\r\n"));
               }
               return 0;
            }
         }
      }
      //如果没有竖线直接翻译
      else
      {
         Translate2Prog(nType, j + nNextX, nLevel, sCellName, progsec, sProgSec, nSteps);
      }
      /*
      #pragma region  根据单元格类型转换为指令和prog
      if (nType == typeNO)
      {
         if (firstCoil && nType != typeLine1 && nType != typeLine2)
         {
            //先看往上面有没有连接
            if (Cells[nCurPosY][j + nNextX].bLeftLineUp)
            {
               // 往上面有连接且有触点连接,才使用OR
               s1.Format(_T("%d %d OR %s"), nCurPosY, nCurPosX, sCellName);
               sProgSec.AppendFormat(_T("OR %s\r\n"), sCellName);
               theprog.nOpType1 = OP_OR;
            }
            else
            {
               s1.Format(_T("%d %d ST %s"), nCurPosY, nCurPosX, sCellName);
               sProgSec.AppendFormat(_T("ST %s\r\n"), sCellName);
               theprog.nOpType1 = OP_ST;
            }
            theprog.nParamCount = 1;
            pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
            theprog.Params[0].nParamType = nCoilType;
            theprog.Params[0].nParamAddr = CoilAddr;
            theprog.Params[0].sParamStr = sCellNameA;
            progsec.Append(theprog);
            firstCoil = false;
         }
         else
         {
            s1.Format(_T("%d %d AN %s"), nCurPosY, nCurPosX, sCellName);
            sProgSec.AppendFormat(_T("NO %s\r\n"), sCellName);
            theprog.nOpType1 = OP_AN;
            theprog.nParamCount = 1;
            pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
            theprog.Params[0].nParamType = nCoilType;
            theprog.Params[0].nParamAddr = CoilAddr;
            theprog.Params[0].sParamStr = sCellNameA;
            progsec.Append(theprog);
         }
         nSteps += 1;
         DbgLog(s1);
         nNextX = 1;
      }
      else if (nType == typeNC)
      {
         if (firstCoil && nType != typeLine1 && nType != typeLine2)
         {
            s1.Format(_T("%d %d ST/ %s"), nCurPosY, nCurPosX, sCellName);
            sProgSec.AppendFormat(_T("ST/ %s\r\n"), sCellName);
            theprog.nOpType1 = OP_ST_;
            theprog.nParamCount = 1;
            pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
            theprog.Params[0].nParamType = nCoilType;
            theprog.Params[0].nParamAddr = CoilAddr;
            theprog.Params[0].sParamStr = sCellNameA;
            progsec.Append(theprog);
            firstCoil = false;
         }
         else
         {
            s1.Format(_T("%d %d AN/ %s"), nCurPosY, nCurPosX, sCellName);
            sProgSec.AppendFormat(_T("AN/ %s\r\n"), sCellName);
            theprog.nOpType1 = OP_AN_;
            theprog.nParamCount = 1;
            pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
            theprog.Params[0].nParamType = nCoilType;
            theprog.Params[0].nParamAddr = CoilAddr;
            theprog.Params[0].sParamStr = sCellNameA;
            progsec.Append(theprog);
         }
         DbgLog(s1);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typePP)
      {
         s1.Format(_T("%d %d PP %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         //progsec.Append(theprog);
         sProgSec.AppendFormat(_T("PP %s\r\n"), sCellName);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typePN)
      {
         s1.Format(_T("%d %d PN %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         //progsec.Append(theprog);
         sProgSec.AppendFormat(_T("PN %s\r\n"), sCellName, sCellName);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typeNOT)
      {
         s1.Format(_T("%d %d NOT %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("NOT %s\r\n"), sCellName);
         theprog.nOpType1 = OP_NOT;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typeDF)
      {
         s1.Format(_T("%d %d DF %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("DF %s\r\n"), sCellName);
         theprog.nOpType1 = OP_DF;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typeDF_)
      {
         s1.Format(_T("%d %d DF/ %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("DF/ %s\r\n"), sCellName);
         theprog.nOpType1 = OP_DF_;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typeOUT)
      {
         s1.Format(_T("%d %d OUT %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("OUT %s\r\n"), sCellName);
         theprog.nOpType1 = OP_OUT;
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typeSET)
      {
         s1.Format(_T("%d %d SET %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("SET %s\r\n"), sCellName);
         theprog.nOpType1 = OP_SET;
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typeRESET)
      {
         s1.Format(_T("%d %d RESET %s"), nCurPosY, nCurPosX, sCellName);
         DbgLog(s1);
         sProgSec.AppendFormat(_T("RESET %s\r\n"), sCellName);
         theprog.nOpType1 = OP_RESET;
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
         nSteps += 1;
         nNextX = 1;
      }
      else if (nType == typeCMP)
      {
         s1.Format(_T("%d %d CMP %s %s %s"), nCurPosY, nCurPosX, sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_ST_GT;
         theprog.nParamCount = 1;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("CMP %s %s %s \r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         nSteps += 1;
         nNextX = 3;
      }
      else if (nType == typeTM)
      {
         s1.Format(_T("%d %d TM %s %d %s"), nCurPosY, nCurPosX, sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_TMX;
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("TM %s %d %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         nSteps += 1;
         nNextX = 3;
      }
      else if (nType == typeFN1)
      {
         s1.Format(_T("%d %d FN1 %s %s"), nCurPosY, nCurPosX, sCellName, Cells[nCurPosY][nCurPosX + 1].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_INC;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("FN1 %s %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam);
         nSteps += 1;
         nNextX = 2;
      }
      else if (nType == typeFN2)
      {
         s1.Format(_T("%d %d FN2 %s %s %s "), nCurPosY, nCurPosX, sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_MV;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("FN2 %s %s %s \r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
         nSteps += 1;
         nNextX = 3;
      }
      else if (nType == typeFN3)
      {
         s1.Format(_T("%d %d FN3 %s %s %s %s"), nCurPosY, nCurPosX, sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam, Cells[nCurPosY][nCurPosX + 3].sParam);
         DbgLog(s1);
         theprog.nOpType1 = OP_ADD3;
         progsec.Append(theprog);
         sProgSec.AppendFormat(_T("FN3 %s %s %s %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam, Cells[nCurPosY][nCurPosX + 3].sParam);
         nSteps += 1;
         nNextX = 4;
      }
      else
      {
         nNextX = 1;
         //continue;
      }
      #pragma endregion
      */
   }
   return 0;
 }
//   记录y,x
std::pair<int, int> popsPoint[100];      int nPSHS = -1;
int CMTerm1View::ScanLDSCells2(int nStartLine, int nEndLine, int nPosY, int nPosX, int nSizeX,
   int nLevel, stProgSection& progsec, CString& sProgSec, int& nSteps)
{
   CString s1;
   int nCurPosX, nCurPosY;
   int nNextX = 0;//步长(到下个线圈起始位置应移动距离
   nCurPosY = nStartLine;
   nCurPosX = nPosX;
   int nCoilType, CoilAddr;
   CMTerm1Doc* pDoc = GetDocument();
   for (int j = nPosX; j < nSizeX; j += nNextX)
   {
      nCurPosX = j;
      //先处理当前单元;
      int nType = Cells[nCurPosY][nCurPosX].nType;
      CString sCellName = Cells[nCurPosY][nCurPosX].sCoilName;
      CMTerm1Doc::stProg theprog;
      CStringA sCellNameA;
      sCellNameA = sCellName;
      CString ProgSec;
      int theSteps = 0;
      stProgSection thisprogsec;
      //判断越界
      if (j + nNextX > m_CellPerLine)
      {
         continue;
      }
      //if (!firstCoil && Cells[nCurPosY][j].bLeftLineUp)
      //{
      //   break;
      //}
      if (Cells[nCurPosY][nCurPosX].nType == typeNone)
      {
         nNextX = 1;
         continue;
      }
      //开始翻译单个单元格,并返回下个单元格位置
      nNextX = Translate2Prog(nType, nCurPosY, nCurPosX, sCellName, progsec, sProgSec, nSteps);
      //1.判断此单元格右侧一格是否有向下的竖线
      if (Cells[nCurPosY][j + nNextX].bLeftLineDn)
      {
         //1.1:有分支,直接开始读取下一行
         if (Cells[nCurPosY +1][j].nType == typeNone)
         {
            if (Cells[nCurPosY + 1][j + nNextX].nType != typeNone)
            {
               firstCoil = true;
            }
            continue;
         }
         firstCoil = true;
         ScanLDSCells2(nCurPosY + 1, nCurPosY + 1, nCurPosY + 1, 0, j + nNextX, ++nLevel, thisprogsec, ProgSec, theSteps);
         //有OR关系且不只一个节点
         if (theSteps > 1 && nLevel > 0)
         {
            // 步数大于1,是复合结果,才使用ORS
            s1.Format(_T("%d %d ORS "), nCurPosY, nCurPosX);
            DbgLog(s1);
            theprog.nOpType1 = OP_ORS;
            //progsec.Append(theprog);
            //sProgSec.AppendFormat(_T("ORS \r\n"));
            thisprogsec.Append(theprog);
            ProgSec.AppendFormat(_T("ORS \r\n"));
            firstCoil = false;
            nSteps += 1;
         }
         //1.2:从后向前查找下一行是否还有向上的竖线(形成闭环)(ORS、ANS)
         for (int k = j; k >= 0; k--)
         {
            if (Cells[nCurPosY + 1][k].nType == typeNone)
            {
               //如果遇到空格,还没搜到,就结束搜索
               break;
            }
            if (Cells[nCurPosY+1][k].bLeftLineUp)
            {
               //如果有一条竖线,说明是形成了环,要用ANS
               if (theSteps >= 1 && nLevel > 0)
               {
                  //步数大于1,是复合结果,使用ANS
                  s1.Format(_T("%d %d ANS "), nCurPosY, nCurPosX);
                  DbgLog(s1);
                  theprog.nOpType1 = OP_ANS;
                  //progsec.Append(theprog);
                  //sProgSec.AppendFormat(_T("ANS \r\n"));
                  thisprogsec.Append(theprog);
                  ProgSec.AppendFormat(_T("ANS \r\n"));
                  nSteps += 1;
               }
            }
         }
         //将转换完成的部分加入到总集中
         nSteps += theSteps;
         progsec += thisprogsec;
         sProgSec += ProgSec;
         //1.3:查询此分支下一级连接点左右均存在节点,存在就PSHS
         if (Cells[nCurPosY + 1][j].nType != typeNone
            && Cells[nCurPosY + 1][j + 1].nType != typeNone)
         {
            ++nPSHS;
            CString push = _T("PSHS \r\n");
            theprog.nOpType1 = OP_PSHS;
            progsec.Append(theprog);
            sProgSec.Append(push);
            popsPoint[nPSHS] = std::make_pair(nCurPosY + 1, j + 1);
         }
      }//end  1.判断此单元格右侧一格是否有向下的竖线
   }
   nLevel--;
   //已回到起始层
   if (nLevel == 0)
   {
      CMTerm1Doc::stProg theprog;
      for (int i = nPSHS; i >= 0; i--)
      {
         //+POP
         CString pop = _T("POPS \r\n");
         theprog.nOpType1 = OP_POPS;
         progsec.Append(theprog);
         sProgSec.Append(pop);
         //+fanyi
         //开始翻译单个单元格,并返回下个单元格位置
         //firstCoil = true;
         ScanLDSCells2(popsPoint[nPSHS].first, popsPoint[nPSHS].first, popsPoint[nPSHS].first, popsPoint[nPSHS].second, 16, nLevel, progsec, sProgSec, nSteps);
         nPSHS--;
      }
      if (nPSHS == -1)
      {
         fill(popsPoint, popsPoint + 100, std::make_pair(0, 0));
      }
   }
   return 0;
}
int CMTerm1View::Translate2Prog(
   int nType, int nCurPosY, int nCurPosX, CString sCellName,
   stProgSection& progsec, CString& sProgSec, int& nSteps)
{
   CString s1;
   int nNextX = 1;//步长
   int nCoilType, CoilAddr;
   CMTerm1Doc::stProg theprog;
   CMTerm1Doc* pDoc = GetDocument();
   CStringA sCellNameA;
   sCellNameA = sCellName;
   //if (nType == typeNone)
   //{
   //   return 0;
   //}
   if (nType == typeNO)
   {
      if (firstCoil && nType != typeLine1 && nType != typeLine2)
      {
         //先看往上面有没有连接
         if (Cells[nCurPosY][nCurPosX + nNextX].bLeftLineUp)
         {
            // 往上面有连接,使用OR
            sProgSec.AppendFormat(_T("OR %s\r\n"), sCellName);
            theprog.nOpType1 = OP_OR;
         }
         else
         {
            sProgSec.AppendFormat(_T("ST %s\r\n"), sCellName);
            theprog.nOpType1 = OP_ST;
         }
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
         firstCoil = false;
      }
      else
      {
         sProgSec.AppendFormat(_T("AN %s\r\n"), sCellName);
         theprog.nOpType1 = OP_AN;
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
      }
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeNC)
   {
      if (firstCoil && nType != typeLine1 && nType != typeLine2)
      {
         sProgSec.AppendFormat(_T("ST/ %s\r\n"), sCellName);
         theprog.nOpType1 = OP_ST_;
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
         firstCoil = false;
      }
      else
      {
         sProgSec.AppendFormat(_T("AN/ %s\r\n"), sCellName);
         theprog.nOpType1 = OP_AN_;
         theprog.nParamCount = 1;
         pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
         theprog.Params[0].nParamType = nCoilType;
         theprog.Params[0].nParamAddr = CoilAddr;
         theprog.Params[0].sParamStr = sCellNameA;
         progsec.Append(theprog);
      }
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typePP)
   {
      //progsec.Append(theprog);
      sProgSec.AppendFormat(_T("PP %s\r\n"), sCellName);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typePN)
   {
      //progsec.Append(theprog);
      sProgSec.AppendFormat(_T("PN %s\r\n"), sCellName, sCellName);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeNOT)
   {
      sProgSec.AppendFormat(_T("NOT %s\r\n"), sCellName);
      theprog.nOpType1 = OP_NOT;
      progsec.Append(theprog);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeDF)
   {
      sProgSec.AppendFormat(_T("DF %s\r\n"), sCellName);
      theprog.nOpType1 = OP_DF;
      progsec.Append(theprog);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeDF_)
   {
      sProgSec.AppendFormat(_T("DF/ %s\r\n"), sCellName);
      theprog.nOpType1 = OP_DF_;
      progsec.Append(theprog);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeOUT)
   {
      sProgSec.AppendFormat(_T("OUT %s\r\n"), sCellName);
      theprog.nOpType1 = OP_OUT;
      theprog.nParamCount = 1;
      pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
      theprog.Params[0].nParamType = nCoilType;
      theprog.Params[0].nParamAddr = CoilAddr;
      theprog.Params[0].sParamStr = sCellNameA;
      progsec.Append(theprog);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeSET)
   {
      sProgSec.AppendFormat(_T("SET %s\r\n"), sCellName);
      theprog.nOpType1 = OP_SET;
      theprog.nParamCount = 1;
      pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
      theprog.Params[0].nParamType = nCoilType;
      theprog.Params[0].nParamAddr = CoilAddr;
      theprog.Params[0].sParamStr = sCellNameA;
      progsec.Append(theprog);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeRESET)
   {
      sProgSec.AppendFormat(_T("RESET %s\r\n"), sCellName);
      theprog.nOpType1 = OP_RESET;
      theprog.nParamCount = 1;
      pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
      theprog.Params[0].nParamType = nCoilType;
      theprog.Params[0].nParamAddr = CoilAddr;
      theprog.Params[0].sParamStr = sCellNameA;
      progsec.Append(theprog);
      nSteps += 1;
      nNextX = 1;
   }
   else if (nType == typeCMP)
   {
      theprog.nOpType1 = OP_ST_GT;
      theprog.nParamCount = 1;
      progsec.Append(theprog);
      sProgSec.AppendFormat(_T("CMP %s %s %s \r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
      nSteps += 1;
      nNextX = 3;
   }
   else if (nType == typeTM)
   {
      theprog.nOpType1 = OP_TMX;
      theprog.nParamCount = 1;
      pDoc->TxtToCoilType(sCellNameA, &nCoilType, &CoilAddr);
      theprog.Params[0].nParamType = nCoilType;
      theprog.Params[0].nParamAddr = CoilAddr;
      theprog.Params[0].sParamStr = sCellNameA;
      progsec.Append(theprog);
      sProgSec.AppendFormat(_T("TM %s %d %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
      nSteps += 1;
      nNextX = 3;
   }
   else if (nType == typeFN1)
   {
      theprog.nOpType1 = OP_INC;
      progsec.Append(theprog);
      sProgSec.AppendFormat(_T("FN1 %s %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam);
      nSteps += 1;
      nNextX = 2;
   }
   else if (nType == typeFN2)
   {
      theprog.nOpType1 = OP_MV;
      progsec.Append(theprog);
      sProgSec.AppendFormat(_T("FN2 %s %s %s \r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam);
      nSteps += 1;
      nNextX = 3;
   }
   else if (nType == typeFN3)
   {
      theprog.nOpType1 = OP_ADD3;
      progsec.Append(theprog);
      sProgSec.AppendFormat(_T("FN3 %s %s %s %s\r\n"), sCellName, Cells[nCurPosY][nCurPosX + 1].sParam, Cells[nCurPosY][nCurPosX + 2].sParam, Cells[nCurPosY][nCurPosX + 3].sParam);
      nSteps += 1;
      nNextX = 4;
   }
   else
   {
      nNextX = 1;
      //continue;
   }
   return nNextX;
}
/// <summary>
/// 全部图形校验
/// </summary>
/// <returns></returns>
/// <remark>
/// 计划在第一个返回值中使用不同的错误代码代表不同的错误类型,
/// 并在第二个返回值中填充错误提示信息
/// </remark>
 std::pair<int, CString> CMTerm1View::LDSCheckRule()
 {
    CString message;
    int nDivCount = 0;
    int Divs[100] = { 0 };
    //以行为单位从上到下遍历(行遍历)
    for (int i = 0; i < m_nTotalRow; i++)
    {
       int nRow = i;
       int bConnected = 0;
       bool checkFlag = false;//0列检验结果
       //本行的0列检查
       if (Cells[nRow][0].nType == 0)
       {
          checkFlag = true;
       }
       //遍历此行的1-15列(确定单元格)
       for (int j = 1; j < m_CellPerLine; j++)
       {
          int nCol = j;
          //如果0列为空
          if (checkFlag)
          {
             //有左侧上竖线
             if (Cells[nRow][nCol].bLeftLineUp)
             {
                //如果上层为空单元格,无效竖线,直接删除-----可以单独判断
                if (nRow - 1 >= 0 && Cells[nRow - 1][nCol].nType == 0)
                {
                   //清理单元格
                   Cells[nRow][nCol].clear();
                }
                //如果是none,错误:短路或回路
                else if (Cells[nRow][nCol].nType == 0)
                {
                   message.Format(_T("((%d,%d) 附近位置产生触点短路或回路!"), nRow, nCol);
                   return std::make_pair(111, message);
                }
                //如果不为none。可以转换,但是提示:无法绘制图形(程序不合理)
                if (Cells[nRow][nCol].nType != 1)
                {
                   message.Format(_T("((%d,%d) 无法绘制图形(程序不合理)"), nRow, nCol);
                   return std::make_pair(111, message);
                }
             }
             //没有左侧上竖线,且此单元格类型 不为空或线
             else if (Cells[nRow][nCol].nType > 2)
             {
                //此单元格为单独的线圈或指令单元,需要触点输入
                message.Format(_T("((%d,%d) 需要触点输入"), nRow, nCol);
                return std::make_pair(111, message);
             }
             //有左侧下竖线,且此单元格类型为空
             if (Cells[nRow][nCol].bLeftLineDn)
             {
                //不支持回路
             }
          }
          //如0列非空
          else
          {
          }
       }
    }
    return std::make_pair(0, message);
 }