QuakeGod
2024-12-24 61deef5cdf96cbfdd6ad45be49e80d597c00ca65
MTerm1/MTerm1View.cpp
@@ -82,7 +82,7 @@
//   ON_COMMAND(ID_INDICATOR_MONITOR_STATUS, &CMTerm1View::OnIndicatorMonitorStatus)
//   ON_UPDATE_COMMAND_UI(ID_INDICATOR_MONITOR_STATUS, &CMTerm1View::OnUpdateIndicatorMonitorStatus)
ON_WM_KEYDOWN()
   ON_WM_KEYDOWN()
END_MESSAGE_MAP()
@@ -754,6 +754,15 @@
   {
   }
   else if (nType == typeEND)   {
      if (needReDraw) {
         //画左侧横线
         //DrawLeftRightLine(pDC, x0, y0, 14, 18);
         DrawAngleBracket(pDC, x0, y0, 8, 32);
         DrawCellText1(pDC, _T("ED"), x0 + 16, y0 + m_LinePosY - 8, 24, 14);
      }
   }
   else if (nType == typeLine1)
   {   //Draw Line
      //画直横线
@@ -765,8 +774,8 @@
   else if (nType == typeLine2)
   {   //Draw Line
      //画直竖线
      pDC->MoveTo(x0, y0 + (0.32 * CellTotalHeight));
      pDC->LineTo(x0, y0 - (0.69 * CellTotalHeight));
      pDC->MoveTo(x0, y0 + int(0.32 * CellTotalHeight));
      pDC->LineTo(x0, y0 - int(0.69 * CellTotalHeight));
   }
   else if (nType == typeNO)
   {
@@ -1155,6 +1164,7 @@
            nCol = 0; 
         }
      }
      CellFocusChg(nRow, nCol);
   }
   if (nChar == VK_RIGHT) {
      nCol += 1;
@@ -1167,15 +1177,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;
@@ -1211,7 +1223,7 @@
{
   CString s1;
   stCell & thecell = Cells[nRow][nCol];
   s1.Format(_T("Cell %d %d Type %02X \r\n"), nRow, nCol, thecell.nType);
   s1.Format(_T("Cell %d %d Type %02X OpType %02X \r\n"), nRow, nCol, thecell.nType,thecell.nOpType);
   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);
@@ -1308,8 +1320,10 @@
      m_nCurProgStep = Cells[nRow][nCol].nProgStep;
   }
   if (!pDoc->m_bOnline) return;
   //if (!m_bMonitoring) return;
   if (!m_bMonitoring || !pDoc->m_bOnline) {
   };
   CString sParam;
   sParam = Cells[nRow][nCol].sParam;
   int nDataType, nDataAddr, nStat;
@@ -1445,13 +1459,14 @@
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   CString s1;
   CMTerm1Doc * pDoc = (CMTerm1Doc*)GetDocument();
   static int nCount = 0;
   if (nIDEvent == 0) {
   }
   else if (nIDEvent == 1)
   {
      if (m_bMonitoring) {
      nCount++;
      if (m_bMonitoring && (nCount &1)) {
         //this->RedrawWindow();
         DoReDraw();
      }
@@ -1485,22 +1500,25 @@
void CMTerm1View::OnProgConvert()
{
   //转换前先对LDS的规则进行检验(检验规则与返回参数并未完全确定
    std::pair<int,CString> result = LDSCheckRule();
   if (result.first == 111)
   {
      DbgLog(result.second);
      return;
   }
 //   std::pair<int,CString> result = LDSCheckRule();
   //if (result.first == 111)
   //{
   //   DbgLog(result.second);
   //   return;
   //}
   CString s1;
   s1.Format(_T("Prog Convert"));
   SysLog(s1);
   int r = TransLDSToProg();
    SysLog(s1);
   int r = TransLDSToProgAOV();  //TransLDSToProg();
   s1.Format(_T("LDS To Prog result %d"), r);
   SysLog(s1);
///*
   if (r==0) 
   {
   //   m_bModified = 0;
      GetDocument()->FindProgPair();
      GetDocument()->TransProgToBin();
      int j=TransProgToLDS();
      s1.Format(_T("Porg to LDS retuls %d"), j);
      SysLog(s1);
@@ -1511,6 +1529,7 @@
      s1.Format(_T("Error in Prog Convert"));
      SysLog(s1);
   }
//*/
}
void CMTerm1View::OnUpdateProgConvert(CCmdUI *pCmdUI)
@@ -1591,6 +1610,12 @@
/// <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;
@@ -1614,6 +1639,7 @@
      }
      //添加纵线时同步添加上一行
      Cells[m_FocusRow - 1][m_FocusCol].bLeftLineDn = 1;
   }break;
   case 2:
   {
@@ -1625,13 +1651,18 @@
      }
      //删除纵线时同步删除上一行
      Cells[m_FocusRow - 1][m_FocusCol].bLeftLineDn = 0;
   }break;
   default:
      break;
   }
   //单元格位置后移
   m_FocusCol += 1;
   //如果变化的是竖线,焦点不后移
   if (!changeVLine)
   {
      //单元格位置后移
      m_FocusCol += 1;
   }
   if (m_FocusCol >= 16) 
   { 
      m_FocusCol = 0;
@@ -1951,6 +1982,9 @@
   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;
@@ -1977,6 +2011,34 @@
         switch (nOp)
         {
         case OP_NOP:
            break;
         case OP_END:
            nCellType =  typeEND;
            nCurLine = cy;
            cx = 0;
            if (cx <= m_CellPerLine) {
               int hasData = 1;
               while (hasData) {
                  hasData = 0;
                  for (int j = 0; j < m_CellPerLine; j++) {
                     if (Cells[nCurLine][j].nType != 0) {
                        nCurLine++; hasData = 1; break;
                     }
                  }
               }
               cy = nCurLine;
               for (int j = 0; j < m_CellPerLine; j++)
               {
                  Cells[cy][j].nType = typeLine1;
               }
               Cells[cy][m_CellPerLine - 1].nType = nCellType;
               Cells[cy][cx].nOpType = nOp;
               Cells[cy][m_CellPerLine - 1].nProgStep = i;
            }
            if (cy > maxy) { maxy = cy; }
            //cy++;
            break;
            break;
         case OP_ST:
         case OP_ST_:
@@ -2048,15 +2110,23 @@
               }
               else if (nPairOp == 0) 
               {
                  nCurLine = maxy + 1; //另起一行
                  maxy = nCurLine;
                  cx = 0; cy = nCurLine;
//                  if (i > 0 && nOp == pDoc->Progs[i-1].nOpType1)//如果前面也是ST,那就不换行
//                  {
//                  }
//                  else
//                  {
                     nCurLine = ++maxy;
                     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].nOpType = nOp;
            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;
@@ -2111,6 +2181,7 @@
            StPts[nSts] = POINT{ cx,cy };
            nSts++;
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sParam = OpName;
            Cells[cy][cx].sCoilName = ShowTxt;
@@ -2129,6 +2200,7 @@
         case OP_AN_:
            Cells[cy][cx].nType = nOp == OP_AN ? typeNO : typeNC; //typeNC
            Cells[cy][cx].nOpType = nOp;
            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;
@@ -2143,6 +2215,7 @@
         case OP_AN_LE:
         case OP_AN_GE:
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
@@ -2191,27 +2264,28 @@
            StPts[nSts] = POINT{ cx,cy };//+++
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].nType = nOp == OP_OR ? typeNO : typeNC; //typeNC
            Cells[cy][cx].nOpType = nOp;
            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;
            //   }
            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++)
            {
@@ -2252,6 +2326,7 @@
            }
            cy = nCurLine;
            Cells[cy][cx].nType = typeCMP;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
@@ -2292,6 +2367,7 @@
            break;
         case OP_NOT:
            Cells[cy][cx].nType = typeNOT;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].sCoilName = _T("NOT");
            Cells[cy][cx].nProgStep = i;
@@ -2300,63 +2376,96 @@
         case OP_DF:
         case OP_DF_:
            Cells[cy][cx].nType = nOp == OP_DF ? typeDF : typeDF_;
            Cells[cy][cx].nOpType = nOp;
            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:
            //当前序列与前面的序列合并。
            // 当前序列与前面的序列合并。
            //当前序列的开始结束位置
            //EndPt[nEndPts] = POINT{ cx,cy };
            //nEndPts++;
            //StPts[nSts - 1]; EndPt[nEndPts - 1];
            //前一序列的开始结束位置
            StPts[nSts - 1];
            EndPt[nEndPts - 1];
            StPts[nSts - 1]; EndPt[nEndPts - 1];
            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++)
            //   {
            //      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;
            //判断二者长度
            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;
                  }
               }
            }
            //连接上下线
            for (int j = EndPt[nEndPts - 1].y; j < cy; j++)
            {
               Cells[j][cx].bLeftLineDn = 1;
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            //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:
            EndPt[nEndPts] = POINT{ cx,cy };
            nEndPts++;
/*
            StrPt[nStrPts] = POINT{ EndPt[nEndPts].x,EndPt[nEndPts].y+1 };
            nStrPts++;
*/
            break;
         case OP_RDS:
            cx = EndPt[nEndPts - 1].x;
@@ -2386,7 +2495,11 @@
               Cells[j + 1][cx].bLeftLineUp = 1;
            }
            nEndPts--;
/*
            nStrPts--;
            cy = StrPt[nStrPts].y;
            cx = StrPt[nStrPts].x;
*/
            break;
         case OP_OUT:
         case OP_SET:
@@ -2415,6 +2528,7 @@
                  Cells[cy][j].nType = typeLine1;
               }
               Cells[cy][m_CellPerLine - 1].nType = nCellType;
               Cells[cy][cx].nOpType = nOp;
               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;
@@ -2424,6 +2538,7 @@
            }
            else {
               Cells[cy][cx].nType = nCellType;
               Cells[cy][cx].nOpType = nOp;
               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;
@@ -2438,7 +2553,26 @@
         case OP_TMR:
         case OP_TMX:
         case OP_TMY:
            nCurLine = cy;
            {
               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 = typeTM;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
@@ -2454,6 +2588,7 @@
         case OP_INC:
         case OP_DEC:
            Cells[cy][cx].nType = typeFN1;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
@@ -2467,6 +2602,7 @@
         case OP_ADD2:
         case OP_SUB2:
            Cells[cy][cx].nType = typeFN2;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
@@ -2485,6 +2621,7 @@
         case OP_MUL:
         case OP_DIV:
            Cells[cy][cx].nType = typeFN3;
            Cells[cy][cx].nOpType = nOp;
            Cells[cy][cx].nProgStep = i;
            Cells[cy][cx].sCoilName = ShowTxt;
            Cells[cy][cx + 1].nType = typeExt1;
@@ -2505,6 +2642,7 @@
         default:
            break;
         }
         if (cy > maxy) { maxy = cy; }
      }
   }
   catch (const std::exception&)
@@ -2527,7 +2665,1065 @@
   needReDraw = 1;
   return 0;
}
bool firstCoil = true;//本段第一个单元格
int CMTerm1View::AddNode(int nType, int CellX, int CellY, CString sCoilName, int PrevNode)
{
   node& theNode = nodes[nNodeCount];
   theNode.nId = nNodeCount;
   theNode.bEnable = 1;
   theNode.nType = nType;
   theNode.indegree = 0;
   theNode.outdegree = 0;
   theNode.firstOut = 0;
   theNode.firstIn = 0;
   theNode.input = 0;
   theNode.result = 0;
   theNode.nCellX = CellX;
   theNode.nCellY = CellY;
   theNode.CoilName = sCoilName;
   theNode.InProcCount = 0;
   theNode.OutProcCount = 0;
   theNode.OutProcAllDone = 0;
   theNode.prog1.Progs.clear();
   int nOp = Cells[CellY][CellX].nOpType;
   int nCoilType, nCoilAddr;
   if (nType == typeNO)
    {
      CMTerm1Doc::stProg prog0;
      if (CellX == 0) {
         prog0.nOpType1 = OP_ST; // OP_AN;
      }else
      if (nOp >= 1 && nOp <= 255) {
         //prog0.nOpType1 = nOp; // OP_AN;
         prog0.nOpType1 = OP_AN; // OP_AN;
      }
      else {
         prog0.nOpType1 = OP_AN; // OP_AN;
      }
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = sCoilName;
      CStringA s2A;
      s2A = sCoilName;
      GetDocument()->TxtToCoilType(s2A,&nCoilType,&nCoilAddr);
      prog0.Params[0].nParamType = nCoilType;
      prog0.Params[0].nParamAddr = nCoilAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeNC) {
      CMTerm1Doc::stProg prog0;
      if (CellX == 0) {
         prog0.nOpType1 = OP_ST_; // OP_AN;
      }
      else if (nOp >= 1 && nOp <= 255) {
         //prog0.nOpType1 = nOp; // OP_AN;
         prog0.nOpType1 = OP_AN_; // OP_AN;
      }
      else  {
         prog0.nOpType1 = OP_AN_; // OP_AN;
      }
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = Cells[CellY][CellX].sCoilName;
      CStringA s2A;
      s2A = sCoilName;
      GetDocument()->TxtToCoilType(s2A, &nCoilType, &nCoilAddr);
      prog0.Params[0].nParamType = nCoilType;
      prog0.Params[0].nParamAddr = nCoilAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeEND) {
      theNode.prog1.Append(CMTerm1Doc::stProg(OP_END));
   }
   else if (nType == typePP) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = sCoilName;
      prog0.Params[0].nParamType = Cells[CellY][CellX].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typePN) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = sCoilName;
      prog0.Params[0].nParamType = Cells[CellY][CellX].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeNOT) {
      theNode.prog1.Append(CMTerm1Doc::stProg(OP_NOT));
   }
   else if (nType == typeDF) {
      theNode.prog1.Append(CMTerm1Doc::stProg(OP_DF));
   }
   else if (nType == typeDF_) {
      theNode.prog1.Append(CMTerm1Doc::stProg(OP_DF_));
   }
   else if (nType == typeOUT) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = OP_OUT;
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = sCoilName;
      CStringA s2A;
      s2A = sCoilName;
      GetDocument()->TxtToCoilType(s2A, &nCoilType, &nCoilAddr);
      prog0.Params[0].nParamType = nCoilType;
      prog0.Params[0].nParamAddr = nCoilAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeSET) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = OP_SET;
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = sCoilName;
      CStringA s2A;
      s2A = sCoilName;
      GetDocument()->TxtToCoilType(s2A, &nCoilType, &nCoilAddr);
      prog0.Params[0].nParamType = nCoilType;
      prog0.Params[0].nParamAddr = nCoilAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeRESET) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = OP_RESET;
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = sCoilName;
      CStringA s2A;
      s2A = sCoilName;
      GetDocument()->TxtToCoilType(s2A, &nCoilType, &nCoilAddr);
      prog0.Params[0].nParamType = nCoilType;
      prog0.Params[0].nParamAddr = nCoilAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeCMP) {
      CMTerm1Doc::stProg prog0;
      Cells[CellY][CellX];
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;
      prog0.nParamCount = 2;
      prog0.Params[0].sParamStr = Cells[CellY][CellX + 1].sParam;
      prog0.Params[0].nParamType = Cells[CellY][CellX + 1].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX + 1].nDataAddr;
      prog0.Params[1].sParamStr = Cells[CellY][CellX + 2].sParam;
      prog0.Params[1].nParamType = Cells[CellY][CellX + 2].nDataType;
      prog0.Params[1].nParamAddr = Cells[CellY][CellX + 2].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeTM) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;
      prog0.nParamCount = 2;
      prog0.Params[0].sParamStr = Cells[CellY][CellX + 1].sParam;
      prog0.Params[0].nParamType = Cells[CellY][CellX + 1].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX + 1].nDataAddr;
      prog0.Params[1].sParamStr = Cells[CellY][CellX + 2].sParam;
      prog0.Params[1].nParamType = Cells[CellY][CellX + 2].nDataType;
      prog0.Params[1].nParamAddr = Cells[CellY][CellX + 2].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeFN1) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;;
      prog0.nParamCount = 1;
      prog0.Params[0].sParamStr = Cells[CellY][CellX + 1].sParam;
      prog0.Params[0].nParamType = Cells[CellY][CellX + 1].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX + 1].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeFN2) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;;
      prog0.nParamCount = 2;
      prog0.Params[0].sParamStr = Cells[CellY][CellX + 1].sParam;
      prog0.Params[0].nParamType = Cells[CellY][CellX + 1].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX + 1].nDataAddr;
      prog0.Params[1].sParamStr = Cells[CellY][CellX + 2].sParam;
      prog0.Params[1].nParamType = Cells[CellY][CellX + 2].nDataType;
      prog0.Params[1].nParamAddr = Cells[CellY][CellX + 2].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeFN3) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;;
      prog0.nParamCount = 3;
      prog0.Params[0].sParamStr = Cells[CellY][CellX + 1].sParam;
      prog0.Params[0].nParamType = Cells[CellY][CellX + 1].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX + 1].nDataAddr;
      prog0.Params[1].sParamStr = Cells[CellY][CellX + 2].sParam;
      prog0.Params[1].nParamType = Cells[CellY][CellX + 2].nDataType;
      prog0.Params[1].nParamAddr = Cells[CellY][CellX + 2].nDataAddr;
      prog0.Params[2].sParamStr = Cells[CellY][CellX + 3].sParam;
      prog0.Params[2].nParamType = Cells[CellY][CellX + 3].nDataType;
      prog0.Params[2].nParamAddr = Cells[CellY][CellX + 3].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   else if (nType == typeFN4) {
      CMTerm1Doc::stProg prog0;
      prog0.nOpType1 = Cells[CellY][CellX].nOpType;;
      prog0.nParamCount = 4;
      prog0.Params[0].sParamStr = Cells[CellY][CellX + 1].sParam;
      prog0.Params[0].nParamType = Cells[CellY][CellX + 1].nDataType;
      prog0.Params[0].nParamAddr = Cells[CellY][CellX + 1].nDataAddr;
      prog0.Params[1].sParamStr = Cells[CellY][CellX + 2].sParam;
      prog0.Params[1].nParamType = Cells[CellY][CellX + 2].nDataType;
      prog0.Params[1].nParamAddr = Cells[CellY][CellX + 2].nDataAddr;
      prog0.Params[2].sParamStr = Cells[CellY][CellX + 3].sParam;
      prog0.Params[2].nParamType = Cells[CellY][CellX + 3].nDataType;
      prog0.Params[2].nParamAddr = Cells[CellY][CellX + 3].nDataAddr;
      prog0.Params[3].sParamStr = Cells[CellY][CellX + 4].sParam;
      prog0.Params[3].nParamType = Cells[CellY][CellX + 4].nDataType;
      prog0.Params[3].nParamAddr = Cells[CellY][CellX + 4].nDataAddr;
      theNode.prog1.Append(prog0);
   }
   if (PrevNode > 0) {
      AddArc(PrevNode, nNodeCount);
   }
   nNodeCount++;
   return nNodeCount-1;
}
int SearchLastInArc(int nNodeID)
{
   int ArcId = 0;
   return ArcId;
}
int SearchLastOutArc(int nNodeID)
{
      int ArcId = 0;
      return ArcId;
}
int CMTerm1View::AddArc(int nNodeID1, int nNodeID2)
{
   node& theNode1 = nodes[nNodeID1];
   node& theNode2 = nodes[nNodeID2];
   arc& theArc = arcs[nArcCount];
   theArc.nId = nArcCount;
   theArc.bEnable = 1;
   theNode2.firstIn;
   theArc.headNode = nNodeID2;
   theArc.tailNode = nNodeID1;
   theArc.hlinkId = 0;
   theArc.tlinkId = 0;
   theArc.tailvex = &theNode1;
   theArc.headvex = &theNode2;
   theArc.tlink = 0;
   theArc.hlink = 0;
   theNode1.outdegree++;
   theNode2.indegree++;
   //如果顶点已经有 连接 ,将新的弧加到已有弧的后面。
   if (theNode1.firstOut == 0) {
      theNode1.firstOut = &theArc;
   }else {
      arc * p1 = theNode1.firstOut;
      for (; p1->tlink != 0;) {
          p1 = p1->tlink;
      }
      p1->tlink = &theArc;
      p1->tlinkId = nArcCount;
   }
   if (theNode2.firstIn == 0) {
      theNode2.firstIn = &theArc;
   }else{
      arc* p1 = theNode2.firstIn;
      for (; p1->hlink != 0;) {
         p1 = p1->hlink;
      }
      p1->hlink = &theArc;
      p1->hlinkId = nArcCount;
   }
   nArcCount++;
   return nArcCount;
}
int CMTerm1View::MergeParallelNodeWithinVP(int nVPNodeId1, int nVPNodeId2)      //合并两个串联的虚节点之间所有的并行 Node,并行数量可能大于2个。
{
   node& theNode1 = nodes[nVPNodeId1];         //虚节点1
   node& theNode2 = nodes[nVPNodeId2];         //虚节点2
   // 必须前者 与 后者 之间有两条以上 且连续,其中一方为另一方的子集 才能合并。
   // 先找到两者连接的弧
   if (!theNode1.bEnable || !theNode2.bEnable) return -1;
   if (theNode1.outdegree < 2 || theNode2.indegree < 2 ) return -2;
//   if (theNode1.firstOut != theNode2.firstIn) return -3;
//
//  先找到第一个连接
//
   CString s1;
   //先判断两者大小
   int n1 = theNode1.outdegree;
   int n2 = theNode2.indegree;
   if (n1 <= n2) {         //前者是后的的子集
      int n = 0;
      arc* ptheArc1 = theNode1.firstOut;
      while (ptheArc1)
      {   // 取得连接的实节点地址;
         node* pThisNode1 = ptheArc1->headvex;
         // 取得实节点连接的弧;
         arc* ptheArc2 = pThisNode1->firstOut;
         // 取出弧连接的下一个节点, 目标虚节点
         node* pThatNode1 = ptheArc2->headvex;
         // 判断这个点是不是指定的虚节点
         if (pThatNode1 != &theNode2) { return -3; } // 没连接到第二个虚节点
         n++;
         // 继续下一个连接的弧;
         ptheArc1 = ptheArc1->tlink;
      }
      if (theNode1.outdegree != n ) return -2;
      //node& theNode;
      // 第二次,重来一遍,开始合并程序
      stProgSection prog2;
      ptheArc1 = theNode1.firstOut;
      node* pThisNode1 = ptheArc1->headvex;   // 第一个实节点
      stProgSection prog1 = pThisNode1->prog1;
      if (prog1.Progs[0].nOpType1 == OP_AN) { prog1.Progs[0].nOpType1 = OP_ST; }
      else if (prog1.Progs[0].nOpType1 == OP_AN_) { prog1.Progs[0].nOpType1 = OP_ST_; }
      else if (prog1.Progs[0].nOpType1 == OP_ST || prog1.Progs[0].nOpType1 == OP_ST_ ){
         prog1.Prefix += 1;
         s1.Format(_T(" <+1  %s"),prog1.ToText());   DbgLog(s1);
      }
      else {
         prog1.Prefix += 0;
         s1.Format(_T(" < +0 %s"),prog1.ToText());   DbgLog(s1);
      }
      prog2 = prog1;            // 取得第一个实节点的程序
      ptheArc1 = ptheArc1->tlink;            //下一个弧
      while (ptheArc1)
      {
         //取得相连的实节点地址
         node* pThisNode2 = ptheArc1->headvex;
         stProgSection prog1 = pThisNode2->prog1;
         if (prog1.Progs[0].nOpType1 == OP_AN) { prog1.Progs[0].nOpType1 = OP_ST; }
         else if (prog1.Progs[0].nOpType1 == OP_AN_) { prog1.Progs[0].nOpType1 = OP_ST_; }
         else if (prog1.Progs[0].nOpType1 == OP_ST || prog1.Progs[0].nOpType1 == OP_ST_) {
            prog1.Prefix += 1;
            s1.Format(_T(" < 2 +1 %s"), prog1.ToText());   DbgLog(s1);
            if (theNode1.nType == -1) { prog1.reduce(); }
         }
         else {
            prog1.Prefix += 0;
            s1.Format(_T(" < 2 +0 %s"),prog1.ToText());   DbgLog(s1);
         }
         if (prog1.Progs.size() > 1) {
            prog1.Append(CMTerm1Doc::stProg(OP_ORS));
         }
         else {
            if (pThisNode2->nType == typeNC) prog1.Progs[0].nOpType1 = OP_OR_;
            else if (pThisNode2->nType == typeNO) prog1.Progs[0].nOpType1 = OP_OR;
            else prog1.Progs[0].nOpType1 = OP_OR;
         }
         prog2 += prog1;
         // 取得实节点连接的弧;
         arc* ptheArc2 = pThisNode2->firstOut;
         RemoveArc(ptheArc2->nId);            //删除弧
         arc* pTheNextArc = ptheArc1->tlink;      //取得下一个弧并保存
         RemoveArc(ptheArc1->nId);            //删除当前弧
         pThisNode2->bEnable = 0;            //删除实节点
         ptheArc1 = pTheNextArc;
      }
      if (theNode1.nType == -1 && theNode2.nType == -1) { prog2.Append(CMTerm1Doc::stProg(OP_ANS)); }
      pThisNode1->prog1 = prog2;            //将所有程序汇总到第一个实节点
   //   pThisNode1->prog1.reduce();
   //   s1 = prog2.ToText(GetDocument());
   //   DbgLog(_T("------ ") + s1);
   }
   else {         // n1> n2  // 后者是前者的子集
      int n = 0;
      arc* ptheArc1 = theNode2.firstIn;
      while (ptheArc1)
      {
         //取得相连的虚节点地址
         // 取得连接的实节点地址;
         node* pThisNode1 = ptheArc1->tailvex;
         // 取得实节点连接的弧;
         arc* ptheArc2 = pThisNode1->firstIn;
         // 取出弧连接的下一个节点
         node* pThatNode1 = ptheArc2->tailvex;
         // 判断这个点是不是指定的虚节点
         if (pThatNode1 != &theNode1) { return -3; } // 没连接到第二个虚节点
         n++;
         // 继续下一个连接的弧;
         ptheArc1 = ptheArc1->hlink;
      }
      if (theNode2.indegree != n) return -1;
      //node& theNode;
      // 第二次,重来一遍,开始合并程序
      stProgSection prog2;
      ptheArc1 = theNode2.firstIn;
      node* pThisNode1 = ptheArc1->tailvex;   // 第一个实节点
      stProgSection prog1 = pThisNode1->prog1;
      if (prog1.Progs[0].nOpType1 == OP_AN) { prog1.Progs[0].nOpType1 = OP_ST; }
      else if (prog1.Progs[0].nOpType1 == OP_AN_) { prog1.Progs[0].nOpType1 = OP_ST_; }
      else if (prog1.Progs[0].nOpType1 == OP_ST || prog1.Progs[0].nOpType1 == OP_ST_) {
         prog1.Prefix += 1;
         s1.Format(_T(" > +1 %s"),prog1.ToText());   DbgLog(s1);
      }
      else {
         prog1.Prefix += 0;
         s1.Format(_T(" > +0 %s"), prog1.ToText());   DbgLog(s1);
      }
      prog2 = prog1;            // 取得第一个实节点的程序
      ptheArc1 = ptheArc1->hlink;
      bool NeedANS = 0;
      while (ptheArc1)
      {
         //取得相连的虚节点地址
         node* pThisNode2 = ptheArc1->tailvex;
         stProgSection prog1 = pThisNode2->prog1;
         if (prog1.Progs[0].nOpType1 == OP_AN) { prog1.Progs[0].nOpType1 = OP_ST; }
         else if (prog1.Progs[0].nOpType1 == OP_AN_) { prog1.Progs[0].nOpType1 = OP_ST_; }
         else if (prog1.Progs[0].nOpType1 == OP_ST || prog1.Progs[0].nOpType1 == OP_ST_) {
            prog1.Prefix += 1;
            s1.Format(_T(" > 2 +1 %s"),prog1.ToText());   DbgLog(s1);
         }
         else {
            prog1.Prefix += 0;
            s1.Format(_T(" >2 +0 %s"),prog1.ToText());   DbgLog(s1);
         }
         if (prog1.Progs.size() > 1) {
            prog1.Append(CMTerm1Doc::stProg(OP_ORS));
            NeedANS = 1;
         }
         else {
            if (pThisNode2->nType == typeNC) prog1.Progs[0].nOpType1 = OP_OR_;
            else if (pThisNode2->nType == typeNO) prog1.Progs[0].nOpType1 = OP_OR;
            else prog1.Progs[0].nOpType1 = OP_OR;
            NeedANS = 1;
         }
         prog2 += prog1;
         arc* ptheArc2 = pThisNode2->firstIn;
         RemoveArc(ptheArc2->nId);            //删除弧
         arc* pTheNextArc = ptheArc1->hlink;      //取得下一个弧并保存
         RemoveArc(ptheArc1->nId);            //删除当前弧
         pThisNode2->bEnable = 0;            //删除实节点
         ptheArc1 = pTheNextArc;
      }
      if (theNode1.nType == -1 && theNode2.nType == -1 && NeedANS) { prog2.Append(CMTerm1Doc::stProg(OP_ANS)); }
      pThisNode1->prog1 = prog2;            //将所有程序汇总到第一个实节点
   //   pThisNode1->prog1.reduce();
   //   s1 = prog2.ToText(GetDocument());
   //   DbgLog(_T("------ ") + s1);
   }
   return 0;
}
int CMTerm1View::RemoveArc(int nArcId)
{
   arc& theArc = arcs[nArcId];
   node& theNode1 = *theArc.tailvex;
   node& theNode2 = *theArc.headvex;
   // 先看 Node1 这边,
   // 首弧
   if (theNode1.firstOut == &theArc) {
      theNode1.firstOut = theArc.tlink;
   }
   else {
      arc* thatArc = theNode1.firstOut;
      while (thatArc->tlink !=0){
         if (thatArc->tlink == &theArc) {
            thatArc->tlink = theArc.tlink;
            break;
         }
         thatArc = thatArc->tlink;
      }
   }
   // 再看 Node2 这边,
   // 首弧
   if (theNode2.firstIn == &theArc) {
      theNode2.firstIn = theArc.hlink;
   }
   else {
      arc* thatArc = theNode2.firstIn;
      while (thatArc->hlink != 0) {
         if (thatArc->hlink == &theArc) {
            thatArc->hlink = theArc.hlink;
            break;
         }
         thatArc = thatArc->hlink;
      }
   }
   theNode1.outdegree--;
   theNode2.indegree--;
   return nArcCount;
}
int CMTerm1View::RemoveNode(int nNodeId)
{
   node& theNode = nodes[nNodeId];
   theNode.bEnable = 0;
   if (theNode.indegree) {
   }
   return nNodeCount;
}
int CMTerm1View::MergeNode(int nNodeId1, int nNodeId2)      //合并两个串联的 实 Node
{
   node& theNode1 = nodes[nNodeId1];
   node& theNode2 = nodes[nNodeId2];
   // 必须前者出度 为1 后者 入度 为1, 且 相连, 才能合并。
   // 先找到两者连接的弧
   if (!theNode1.bEnable || !theNode2.bEnable) return -1;
   if (theNode1.outdegree != 1 || theNode2.indegree != 1) return -2;
   if (theNode1.firstOut != theNode2.firstIn) return -3;
   // 删除两者之间的弧。
   RemoveArc(theNode1.firstOut->nId);
   theNode1.firstOut = 0;
   theNode2.firstIn = 0;
   // 将 Node2 的 出 弧, 转移 到 node1 上
   theNode1.CoilName += _T("  ") + theNode2.CoilName;
   theNode1.firstOut = theNode2.firstOut;
   theNode1.outdegree = theNode2.outdegree;
   theNode1.prog1 += theNode2.prog1;         // 段程序合并
   arc* thatArc = theNode2.firstOut;
   while (thatArc != 0)
   {
      thatArc->tailvex = &theNode1;
      thatArc->tailNode = nNodeId1;
      thatArc = thatArc->tlink;
      theNode2.outdegree--;
   }
   //
   // 现在 Node2 的入度和出度 均为 0, 删除 node2
   RemoveNode(nNodeId2);
   return 0;
}
//  合并从 nNodeId 虚节点发出的 各个单行 Nodes; 直到下一个多输出的虚节点
int CMTerm1View::MergeVPSubSerialNodes(int nNodeId)
{
   node& theNode = nodes[nNodeId];
   arc* theArc = theNode.firstOut;
   while (theArc != 0) {
      // 从当前弧 取出一个顶点
      node * thisNode = theArc->headvex;
      // 从这个顶点,找到下一个顶点
      if (thisNode->outdegree == 1 && thisNode->firstOut != 0) {
         node* thatNode = thisNode->firstOut->headvex;
         while (thatNode->indegree == 1 && thatNode->outdegree <= 1 && thatNode->nType != -2) {
            if (thatNode->nType == typeOUT || thatNode->nType == typeSET || thatNode->nType == typeRESET) {
               //break;
            }
            MergeNode(thisNode->nId, thatNode->nId);
            if (thatNode->firstOut) thatNode = thatNode->firstOut->headvex;
            else break;
         }
         if (thatNode->nType == -1) { //找到下一个虚顶点
            if (!thatNode->OutProcAllDone) {
               MergeVPSubSerialNodes(thatNode->nId);   //从虚顶点继续
            }
         }
      }
      // 同一个出发点的 下一条弧
      theArc = theArc->tlink;
   };
   theNode.OutProcAllDone = 1;
   return 0;
}
//  合并从 nNodeId 虚节点发出的 各个单行 Nodes; 直到下一个 多输出的虚节点
int CMTerm1View::MergeVPSerialNodes(int nNodeId)
{
   node& theNode = nodes[nNodeId];
   arc* theArc = theNode.firstOut;
   while (theArc != 0) {
      // 从当前弧 取出一个顶点
      node* thisNode = theArc->headvex;
      // 从这个顶点,找到下一个顶点
      if (thisNode->outdegree == 1 && thisNode->firstOut != 0) {
         node* thatNode = thisNode->firstOut->headvex;
         while (thatNode->nType != -2 && thatNode->indegree ==1 && thatNode->outdegree <= 1) {
            if (thatNode->nType == typeOUT || thatNode->nType == typeSET || thatNode->nType == typeRESET) {
               //break;
            }
            MergeNode(thisNode->nId, thatNode->nId);
            if (thatNode->firstOut) thatNode = thatNode->firstOut->headvex;
            else break;
         }
         if (thatNode->nType == -1) { //找到下一个虚顶点
            if (!thatNode->OutProcAllDone) {
               MergeVPSerialNodes(thatNode->nId);   //从虚顶点继续
            }
         }
      }
      // 同一个出发点的 下一条弧
      theArc = theArc->tlink;
   };
   theNode.OutProcAllDone = 1;
   return 0;
}
//从 X,Y 点,向上查找 虚节点,最多终止于 endy;
int CMTerm1View::FindVPNode(int x, int y, int endy)
{
   int nNodeId = 0;
   for (int i = nNodeCount -1 ; i>=1; i--) {
      if (nodes[i].bEnable && nodes[i].nType == -1 && nodes[i].nCellX == x && nodes[i].nCellY <= y &&nodes[i].nCellY >=endy  )
      {
         nNodeId = i; break;
      }
   }
   return nNodeId;
}
int CMTerm1View::ScanVPAOV(int nVPNodeId1, int nVPNodeId2)
{
   MergeParallelNodeWithinVP(nVPNodeId1, nVPNodeId2);
   return 0;
}
int CMTerm1View::ScanAOV1(int nNodeId)
{
   node& theNode = nodes[nNodeId];
   CString s1;
   int nInput = theNode.indegree;
   int nOutput = theNode.outdegree;
   //   s1.Format(_T("%d type %d op %s coil %s  in %d   out %d"), theNode.nId, theNode.nType, theNode.Op, theNode.CoilName, theNode.indegree, theNode.outdegree);
   //   DbgLog(s1);
   if (theNode.InProcCount < theNode.indegree) return 0;
   // 虚拟结点,完成所有输入。
   stProgSection prog2;
   if (theNode.outdegree > 0) {
      //  一直搜索下去,遇到 输入不为0的 虚节点 时 停止,进行下一个迭代
      arc* theArc = theNode.firstOut;
      int allOutputMerged = 1;
      int allOutputSimple = 1;
      for (int i = 0; i < nOutput && theArc != 0; i++) {
         node* thisNode = theArc->headvex;
         thisNode->InProcCount++;
         s1.Format(_T("- %d type %d op %s coil %s  in %d   out %d"), thisNode->nId, thisNode->nType, thisNode->Op, thisNode->CoilName, thisNode->indegree, thisNode->outdegree);
         DbgLog(s1);
         s1 = thisNode->prog1.ToText();
         DbgLog(_T("------ \r\n") + s1);
         arc* thisArc = thisNode->firstOut;
         if (thisNode->outdegree > 0) { allOutputMerged = 0; }
         if (thisNode->nType == typeOUT || thisNode->nType == typeSET || thisNode->nType == typeRESET) {
            thisNode->prog1.bModifyVal = 0;
         }
         else {
            allOutputSimple = 0;
            thisNode->prog1.bModifyVal = 1;
         }
         while (thisArc) {
            thisNode = thisArc->headvex;
            thisNode->InProcCount++;
            s1.Format(_T("-- %d type %d op %s coil %s  in %d   out %d"), thisNode->nId, thisNode->nType, thisNode->Op, thisNode->CoilName, thisNode->indegree, thisNode->outdegree);
            DbgLog(s1);
            if (thisNode->nType > 0) //thatNode.indegree == 1 && thatNode.outdegree == 1)
            {
             thisArc = thisNode->firstOut;
               //   node* thatNode = thisArc->headvex;
            }
            else {
               ScanVPAOV(nNodeId, thisNode->nId);
               if (thisNode->InProcCount >= thisNode->indegree) {
                  s1.Format(_T("-> %d type %d op %s coil %s  in %d   out %d"), thisNode->nId, thisNode->nType, thisNode->Op, thisNode->CoilName, thisNode->indegree, thisNode->outdegree);
                  DbgLog(s1);
                  ScanAOV1(thisNode->nId);
               }
               break;
            }
         }
         //         if (thatNode.nType > 0) {
         //            prog2.Append(thatNode.prog1);
         //         }
                  //RemoveArc(theArc->nId);
                  // 同一个出发点的 下一条弧
         theArc = theArc->tlink;
      }
      if (theNode.outdegree >= 2 && allOutputMerged) {
         s1.Format(_T(" Merge Output %d  %d  allsimple = %d "), nNodeId,theNode.outdegree,allOutputSimple);
         DbgLog(s1);
         if (allOutputSimple) {
            arc * thisArc = theNode.firstOut;
            node* thisNode = thisArc->headvex;
            thisArc = thisArc->tlink;
            for (int i = 1; i < nOutput && thisArc != 0; i++) {
               node* thatNode = thisArc->headvex;
               thisNode->prog1 += thatNode->prog1;
               arc * tempArc = thisArc->tlink;
               RemoveArc(thisArc->nId);
               thisArc = tempArc;
               RemoveNode(thatNode->nId);
            }
         }
         else {
            arc* thisArc = theNode.firstOut;
            node* thisNode = thisArc->headvex;
            stProgSection prog2;
            prog2.Append(CMTerm1Doc::stProg(OP_PSHS));
            int bLastModify = 1;
            prog2 += thisNode->prog1;
            if (thisNode->prog1.bModifyVal == 0) { bLastModify = 0; s1.Format(_T(" ModifyVal = 0, %s"), thisNode->prog1.ToText()); }
            thisArc = thisArc->tlink;
            for (int i = 1; i < nOutput  && thisArc != 0; i++) {
               node* thatNode = thisArc->headvex;
               if (i == nOutput - 1) { // 最后一个
                  prog2.Append(CMTerm1Doc::stProg(OP_POPS));
               }
               else {
                  if (bLastModify) { prog2.Append(CMTerm1Doc::stProg(OP_RDS)); }
               }
               if (thisNode->prog1.bModifyVal == 0) { bLastModify = 0;s1.Format(_T(" ModifyVal = 0, %s"), thisNode->prog1.ToText()); }
               else { bLastModify = 1; }
               prog2 += thatNode->prog1;
               arc* tempArc = thisArc->tlink;
               RemoveArc(thisArc->nId);
               thisArc = tempArc;
               RemoveNode(thatNode->nId);
            }
            thisNode->prog1 = prog2;
         }
      }
   }
   return 0;
   /*
      node& theNode = nodes[nNodeId];
      arc* theArc = theNode.firstOut;
      while (theArc != 0) {
         // 从当前弧 取出一个顶点
         node* thisNode = theArc->headvex;
         // 从这个顶点,找到下一个顶点
         if (thisNode->outdegree == 1 && thisNode->firstOut != 0) {
            node* thatNode = thisNode->firstOut->headvex;
            while (thatNode->nType != -1) {
               if (thatNode->nType == typeOUT || thatNode->nType == typeSET || thatNode->nType == typeRESET) {
                  break;
               }
               MergeNode(thisNode->nId, thatNode->nId);
               if (thatNode->firstOut) thatNode = thatNode->firstOut->headvex;
               else break;
            }
            if (thatNode->nType == -1) { //找到下一个虚顶点
               if (!thatNode->OutProcAllDone) {
                  MergeSerialNodes(thatNode->nId);   //从虚顶点继续
               }
            }
         }
         // 同一个出发点的 下一条弧
         theArc = theArc->tlink;
      };
      theNode.OutProcAllDone = 1;
   */
}
/// <summary>
/// 试用 AOV 方式 梯形图转Prog
/// </summary>
/// <returns></returns>
int CMTerm1View::TransLDSToProgAOV()
{
   CMTerm1Doc* pDoc = GetDocument();
   CString s1;
   s1.Format(_T("Trans LDS to PRrog"));
   DbgLog(s1);
   s1.Format(_T("AOV 方式 将梯形图转成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+5 ; i++)
   {
      int nRow = i;
      int bConnected = 0;
      //扫描程序,建立十字链表?
      for (int j = 0; j < m_CellPerLine; j++)
      {
         int nCol = j;
         if (Cells[nRow][nCol].bLeftLineDn)
         {
            bConnected = 1;
            //s1.Format(_T("row==%d col==%d 有左下竖线!!!"), nRow, nCol);
            //DbgLog(s1);
            break;
         }
      }
      if (!bConnected)
      {
         //找到一处分界点
         Divs[nDivCount] = i;
         s1.Format(_T("Div at Line %d 是 ::::::::::::分界点"), nRow);
         DbgLog(s1);
         nDivCount++;
      }
   }
   stProgSection allprogs;
   //每段单独处理
   for (int i = 0; i < nDivCount; i++)
   {
      int nStartLine, nEndLine;
      nNodeCount = 0;
      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 };
      int nCounts2[20] = { 0 };
      int nCounts3[20] = { 0 };
      s1.Empty();
      stProgSection section1;
      CString s2;
      int PrevNode = 0;
      nNodeCount = 1;      //清理存储的顶点和弧数据。
      nArcCount = 1;
      AddNode(-2, 0, 0, _T("Mother"));      //增加母线顶点
      for (int j = nStartLine; j <= nEndLine; j++) {
         int nPosX = 0;
         PrevNode = 1;      //从母线开始
         s1.Empty();
         for (int k = 0; k < m_CellPerLine; k++) {
            stCell theCell = Cells[j][k];
            int nNextX = 1;
            int nType;
            int bRightLineUp = 0;
            if (k < m_CellPerLine - 1) { bRightLineUp = Cells[j][k + 1].bLeftLineUp; }
            nType = theCell.nType;
            if (nType == typeNone) { PrevNode = 0;  } // 不连接母线;
            if (nType ) {
               if (nType == typeLine1 && !theCell.bLeftLineUp && !theCell.bLeftLineDn && !bRightLineUp) continue;
               if (nType == typeExt1 || nType == typeExt2 || nType == typeExt3 || nType == typeExt4) continue;
               if (k!=0 && theCell.bLeftLineDn && !theCell.bLeftLineUp) {
                  PrevNode = AddNode(-1, k, j, _T("VP"),PrevNode);
               }
               if (k != 0 && theCell.bLeftLineUp) {
                  int VPNodeId = 0;
                     VPNodeId = FindVPNode(k , j,  nStartLine);
                  PrevNode = VPNodeId;
               }
               switch (nType) {
               case typeLine1:
                  break;
               case typeEND:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeNO:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeNC:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName +_T("/"), PrevNode);
                  break;
               case typePP:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typePN:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeNOT:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeDF:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeDF_:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeOUT:
               case typeSET:
               case typeRESET:
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeCMP:
                  nNextX = 3;
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeExt1:
               case typeExt2:
               case typeExt3:
                  break;
               case typeTM:
                  nNextX = 3;
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeFN1:
                  nNextX = 2;
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeFN2:
                  nNextX = 3;
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeFN3:
                  nNextX = 4;
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeFN4:
                  nNextX = 5;
                  PrevNode = AddNode(nType, k, j, theCell.sCoilName, PrevNode);
                  break;
               case typeCoil:
                  break;
               default:
                  break;
               }
               s2 = Cells[j][k].sCoilName;
               //k += nStep - 1;
               s1 += s2 + _T(" ") + intToString(nNextX) + _T("  ");
               if (bRightLineUp) {
                  int VPNodeId = 0;
                     VPNodeId = FindVPNode(k + 1, j, nStartLine);
                  AddArc(PrevNode, VPNodeId);
                  PrevNode = VPNodeId;
               }
            }
         }
         DbgLog(s1);
      }
      //输出已经生成的 AOV 图 顶点信息
      for (int j = 1; j < nNodeCount; j++) {
         s1.Format(_T("%d    %d %s %s  in %d  out %d  %s "), j, nodes[j].nType,nodes[j].Op, nodes[j].CoilName,nodes[j].indegree,nodes[j].outdegree, nodes[j].prog1.ToText());
         DbgLog(s1);
      }
      //输出AOV图的 弧 数据
      for (int j = 1; j < nArcCount; j++) {
         s1.Format(_T("%3d     %2d - %2d "), j, arcs[j].tailNode, arcs[j].headNode);
//         DbgLog(s1);
      }
      for (int n = 1; n < 8; n++) {
         s1.Format(_T("处理步骤 %d "), n);
         DbgLog(s1);
         for (int j = 1; j < nNodeCount; j++) {
            if (nodes[j].bEnable) nodes[j].OutProcAllDone = 0;
         }
         // 处理 AOV 图
         // 从 母线 开始
         //串联归并 // 归并原则, 普通节点,非虚节点, 两个虚节点之间 多个连续的,归并, 非输出。
         s1.Format(_T("合并串联的节点 %d "), n);
         DbgLog(s1);
         MergeVPSubSerialNodes(1);
         // 处理虚节点
         // 虚节点的多输入处理, 单 OR 或者 多 ORS。
         // 虚节点的输出处理,
         // 对于后续还有共同虚节点的输出, 第一个不处理,
         // 第二个,单不处理,多处理 ST, 后面由虚节点再 ORS, ANS。
         // 对于直接输出的,如果后面没有改变的输出, 直接输出不处理。
         // 对于后面还有改变的, PSHS, RDS, POPS
         // 另外,可以后期简化, ST 后紧跟 ORS 的, 简化为 OR。
         // PSHS RDS POPS 后跟不改变的。 简化
         s1.Format(_T("处理虚节点的输出 %d "), n);
         DbgLog(s1);
         ScanAOV1(1);
         if (nodes[2].outdegree == 0) break;
      }
      // 输出处理完的 AOV 图
      s1.Format(_T("处理完的AOV图"));
      DbgLog(s1);
      for (int j = 2; j < nNodeCount; j++) {
         CStringA s2;
         if (nodes[j].bEnable) {
            s1.Format(_T("%d type %d op %s coil %s  in %d   out %d"), j, nodes[j].nType, nodes[j].Op, nodes[j].CoilName, nodes[j].indegree, nodes[j].outdegree);
            DbgLog(s1);
            s1 = nodes[j].prog1.ToText();
            DbgLog(s1);
         }
      }
      allprogs += nodes[2].prog1;
      nodes[2].prog1.Progs.clear();
   }
   s1.Format(_T("完整的PLC程序 \r\n"));
   s1 += allprogs.ToText();
   DbgLog(s1);
   // 创建 AOV 图
   //输出程序
   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++)
   {
      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);
      pDoc->OpToShowTxt(optype, OpShowTxtA);
      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;
}
/// <summary>
/// 梯形图转Prog
@@ -2586,7 +3782,7 @@
      {
         nStartLine = 0; 
         nEndLine = Divs[i]; 
      }
       }
      else 
      {
         nStartLine = Divs[i - 1]+1;
@@ -2665,13 +3861,21 @@
         {
            firstCoil = true;
            //循环遍历单元格(转换的逻辑在这个函数)
            ScanLDSCells(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec, nSteps);
            //ScanLDSCells(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec, nSteps);
            //ScanLDSCells2(nStartLine, nEndLine, nCurPosY, nCurPosX, 0, thisprogsec, sProgSec, nSteps);
         }
         sProg += sProgSec;
          nAllSteps += nSteps;
         Progsec += thisprogsec;
         //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);
@@ -2702,7 +3906,7 @@
   for (int i = 0; i < n; i++)   
   {
      int optype=allprogs.Progs[i].nOpType1;
      allprogs.Progs[i].PairTo = 0;
      allprogs.Progs[i].PairTo = 0;//??????????
      allprogs.Progs[i].nBinStep = i;
      CStringA OpTxtA,OpShowTxtA;
      CString OpTxt,OpShowTxt;
@@ -2712,7 +3916,7 @@
      OpShowTxt = OpShowTxtA;
      s1.Format(_T("%d %s %s"), optype, OpTxt, OpShowTxt);
      pDoc->Progs[i] = allprogs.Progs[i];
//      DbgLog(s1);
      DbgLog(s1);
   }
   pDoc->m_nProgSteps = n;
   return 0;
@@ -2736,15 +3940,15 @@
{
   CString s1;
   int nCurPosX, nCurPosY;
   int nNextX = 1;//步长
   int nNextX = 1;//步长(下个起始点移动的距离)
   nCurPosY = nPosY;
   nCurPosX = nPosX;
   int nCoilType, CoilAddr;
//   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;
@@ -2761,30 +3965,28 @@
         || Cells[nCurPosY][j + nNextX].bLeftLineDn)
      {
         ////先看往上面有没有连接
         //if (Cells[nCurPosY][j + nNextX].bLeftLineUp)
         //{
         //   // 往上面有连接且有触点连接,才使用ORS
         //   s1.Format(_T("%d %d ORS "), nCurPosY, nCurPosX);
         //   DbgLog(s1);
         //   theprog.nOpType1 = OP_ORS;
         //   //theprog.nOpType1 = OP_ST;
         //   //theprog.PairTo = OP_ORS;
         //   progsec.Append(theprog);
         //   sProgSec.AppendFormat(_T("ORS \r\n"));
         //   firstCoil = false;
         //   nSteps += 1;
         //   nLevel -= 1;
         //}
         //左上是否有链接
         //先看往上面有没有连接
         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++)
         //向下查找,看看竖线的右侧一格的左侧下面还有没有连接其他东西
         int nLeftDnCon = 0;//单元格右侧一格的左侧向下连接数
         for (int k = nCurPosY; k <= nEndLine; k++)
         {
            if (Cells[k][j + nNextX].bLeftLineDn)
            {
@@ -2802,12 +4004,12 @@
         s1.Format(_T("LeftUp %d   LeftDn  %d"), nLeftUpCon, nLeftDnCon);
         DbgLog(s1);
         //左侧下面有连接,那么扫描到这个竖线时返回,继续扫描左侧下面的内容。
         //右侧一格的左侧下面有连接,那么扫描到这个竖线时返回,继续扫描左侧下面的内容。
         if (nLeftDnCon)
         {
            return 1;
         }
         // 左侧下面没有连接,那么这个就是左面最后的单元,开始处理右面的单元。
         //右侧一格的左侧下面没有连接,那么这个就是左面最后的单元,开始处理右面的单元。
         else
         {
            if (nLeftUpCon)
@@ -2854,13 +4056,13 @@
            if (nRightCon == 1)
            {
               s1.Format(_T(">>>> Go %d : %d , level %d "), nLineTop, j + nNextX, nLevel);
                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);
               sProgSec += ProgSec;
@@ -2868,6 +4070,7 @@
               progsec += thisprogsec;
               s1.Format(_T("<<<< Re %d : %d , Result %d "), nLineTop, j + nNextX, 0);
               DbgLog(s1);
               continue;
            }
            else
            {
@@ -2899,7 +4102,7 @@
                     DbgLog(s1);
                     if (nRightCount == 0)
                     {
                        //这里是不是应该做点什么
                     }
                     else if (res[nRightCount - 1] == 0)
                     {
@@ -2948,7 +4151,12 @@
            }
         }
      }
      //如果没有竖线直接翻译
      else
      {
         Translate2Prog(nType, j + nNextX, nLevel, sCellName, progsec, sProgSec, nSteps);
      }
      /*
      #pragma region  根据单元格类型转换为指令和prog
      if (nType == typeNO)
@@ -3180,253 +4388,371 @@
      }
      
      #pragma endregion
      */
   }
   return 0;
 }
 /*
 void CMTerm1View::chuansileitetoprog(int nStartLine, int nEndLine, int nPosY, int nPosX, int nLevel, stProgSection& progsec, CString& sProgSec, int& nSteps)
 {
    CString s1;
    int nCurPosX, nCurPosY;
    int nNextX = 1;//步长
    nCurPosY = nPosY;
    nCurPosX = nPosX;
    int nCoilType, CoilAddr;
    CMTerm1Doc* pDoc = GetDocument();
#pragma region  根据单元格类型转换为指令和prog
//   记录y,x
    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);
               .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;
    }
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();
#pragma endregion
   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>
/// 全部图形校验
@@ -3436,75 +4762,75 @@
/// 计划在第一个返回值中使用不同的错误代码代表不同的错误类型,
/// 并在第二个返回值中填充错误提示信息
/// </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列检验结果
 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;
      }
       //本行的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);
               }
       //遍历此行的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
         {
             }
             //没有左侧上竖线,且此单元格类型 不为空或线
             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);
}
    }
    return std::make_pair(0, message);
 }