📄 edit.c
字号:
EditArithmExpr[ EditDatas.Rung.Element[PosiX][PosiY].VarNum ][0] = '\0'; }}void CheckForAllocatingArithmExpr(int PosiX,int PosiY){ int TypeElement = EditDatas.Rung.Element[PosiX][PosiY].Type; int NumExpr = 0; int Found = FALSE; if ( (TypeElement==ELE_COMPAR) || (TypeElement==ELE_OUTPUT_OPERATE) ) { do { /* Expr free ? */ if (EditArithmExpr[ NumExpr ][0]=='\0') { Found = TRUE; /* Allocate this expr for the operate/compar block ! */ EditDatas.Rung.Element[PosiX][PosiY].VarNum = NumExpr; } NumExpr++; } while( (NumExpr<NBR_ARITHM_EXPR) && (!Found) ); }}void InitBufferRungEdited(){ int x,y; for (y=0;y<RUNG_HEIGHT;y++) { for(x=0;x<RUNG_WIDTH;x++) { EditDatas.Rung.Element[x][y].Type = ELE_FREE; EditDatas.Rung.Element[x][y].ConnectedWithTop = 0; EditDatas.Rung.Element[x][y].VarType = 0; EditDatas.Rung.Element[x][y].VarNum = 0; EditDatas.Rung.Element[x][y].DynamicState = 0; } } EditDatas.Rung.Used = TRUE; EditDatas.Rung.PrevRung = -1; EditDatas.Rung.NextRung = -1;}int FindFreeRung(){ int NumFree = -1; int ScanRung = InfosGene->FirstRung; do { if (!RungArray[ScanRung].Used) NumFree = ScanRung; ScanRung++; } while( (NumFree==-1)&&(ScanRung<NBR_RUNGS) ); return NumFree;}void AddRung(){ InitBufferRungEdited(); EditDatas.DoBeforeFinalCopy = MODE_ADD; EditDatas.NumRung = FindFreeRung(); /* we have found a free rung ? */ if (EditDatas.NumRung>=0) { EditDatas.ModeEdit = TRUE; EditDatas.ElementUnderEdit = NULL; autorize_prevnext_buttons(FALSE); clear_label_comment(); CopyCurrentArithmExpr(); }}void InsertRung(){ /* not really different than adding a rung... */ AddRung(); EditDatas.DoBeforeFinalCopy = MODE_INSERT;}void ModifyCurrentRung(){ CopyRungToRung(&RungArray[InfosGene->CurrentRung],&EditDatas.Rung); EditDatas.DoBeforeFinalCopy = MODE_MODIFY; EditDatas.NumRung = InfosGene->CurrentRung; EditDatas.ModeEdit = TRUE; EditDatas.ElementUnderEdit = NULL; autorize_prevnext_buttons(FALSE); CopyCurrentArithmExpr();}void DeleteCurrentRung(){ int NextDeleted; int PrevDeleted; int NewCurrent; int OldCurrent; int x,y; /* do not destroy the last one ! */ if ( !((InfosGene->CurrentRung==InfosGene->FirstRung) && (InfosGene->CurrentRung==InfosGene->LastRung)) ) { PrevDeleted = RungArray[InfosGene->CurrentRung].PrevRung; NextDeleted = RungArray[InfosGene->CurrentRung].NextRung; NewCurrent = NextDeleted; /* deleting first rung ?*/ if (InfosGene->CurrentRung==InfosGene->FirstRung) { InfosGene->FirstRung = NextDeleted; } else { RungArray[PrevDeleted].NextRung = NextDeleted; } /* deleting last rung ? */ if (InfosGene->CurrentRung==InfosGene->LastRung) { InfosGene->LastRung = PrevDeleted; NewCurrent = InfosGene->LastRung; } else { RungArray[NextDeleted].PrevRung = PrevDeleted; } /* the rung is now free ! */ OldCurrent = InfosGene->CurrentRung; RungArray[InfosGene->CurrentRung].Used = FALSE; InfosGene->CurrentRung = NewCurrent; DrawRung(&RungArray[InfosGene->CurrentRung],TRUE); refresh_label_comment(&RungArray[InfosGene->CurrentRung]); /* kill the expressions used on the rung deleted */ for (y=0;y<RUNG_HEIGHT;y++) { for(x=0;x<RUNG_WIDTH;x++) { if ( (RungArray[OldCurrent].Element[x][y].Type == ELE_COMPAR) || (RungArray[OldCurrent].Element[x][y].Type == ELE_OUTPUT_OPERATE) ) { strcpy(ArithmExpr[ RungArray[OldCurrent].Element[x][y].VarNum ].Expr,""); } } } }}void CancelRungEdited(){ EditDatas.ModeEdit = FALSE; EditDatas.ElementUnderEdit = NULL; EditDatas.NumElementSelectedInToolBar = -1; LoadElementProperties(NULL); DrawRung(&RungArray[InfosGene->CurrentRung],TRUE); refresh_label_comment(&RungArray[InfosGene->CurrentRung]); autorize_prevnext_buttons(TRUE);}void ApplyRungEdited(){ int PrevNew; int NextNew; save_label_comment_edited(); CopyRungToRung(&EditDatas.Rung,&RungArray[EditDatas.NumRung]); ApplyNewArithmExpr(); /* if we have added or inserted, we will have to */ /* modify the links between rungs */ /* order is important when setting all this, if multi-tasking : */ /* calc.c is using only .NextRung to updates all the rungs. */ /* and also global FirstRung & LastRung to start and end */ switch(EditDatas.DoBeforeFinalCopy) { /* Add rung edited after current rung */ case MODE_ADD: PrevNew = InfosGene->CurrentRung; NextNew = RungArray[InfosGene->CurrentRung].NextRung; RungArray[EditDatas.NumRung].PrevRung = PrevNew; /* new added is not the last now ? */ if (InfosGene->CurrentRung!=InfosGene->LastRung) { RungArray[EditDatas.NumRung].NextRung = NextNew; RungArray[NextNew].PrevRung = EditDatas.NumRung; } RungArray[PrevNew].NextRung = EditDatas.NumRung; /* we can now update LastRung */ if (InfosGene->CurrentRung==InfosGene->LastRung) { InfosGene->LastRung = EditDatas.NumRung; } /* Here is the new current ! */ InfosGene->CurrentRung = EditDatas.NumRung; break; /* Insert rung edited before current rung */ case MODE_INSERT: PrevNew = RungArray[InfosGene->CurrentRung].PrevRung; NextNew = InfosGene->CurrentRung; RungArray[EditDatas.NumRung].NextRung = NextNew; /* new added is not the first now ? */ if (InfosGene->CurrentRung!=InfosGene->FirstRung) { RungArray[EditDatas.NumRung].PrevRung = PrevNew; RungArray[PrevNew].NextRung = EditDatas.NumRung; } else { InfosGene->FirstRung = EditDatas.NumRung; } RungArray[NextNew].PrevRung = EditDatas.NumRung; /* Here is the new current ! */ InfosGene->CurrentRung = EditDatas.NumRung; break; } EditDatas.ModeEdit = FALSE; EditDatas.ElementUnderEdit = NULL; EditDatas.NumElementSelectedInToolBar = -1; LoadElementProperties(NULL); DrawRung(&RungArray[InfosGene->CurrentRung],TRUE); autorize_prevnext_buttons(TRUE);}/* When we fall on an "unusable" element of a big one, we return new posix and posiy of the "alive" block */void CheckForBlocksOfBigElement(int * PosiX,int * PosiY){ int ScanX,ScanY; int ScanForRule; /* on an "unusable" ? */ if (EditDatas.Rung.Element[*PosiX][*PosiY].Type==ELE_UNUSABLE) { /* we now will have to check for all the "alive" block of bigs elements */ for (ScanY=0;ScanY<RUNG_HEIGHT;ScanY++) { for(ScanX=0;ScanX<RUNG_WIDTH;ScanX++) { ScanForRule = 0; do { /* Is is an element with a rule ? */ if (EditDatas.Rung.Element[ScanX][ScanY].Type == RulesForSpecialElements[ScanForRule][TYPEELERULE]) { /* Have we clicked in it ? */ if ( (*PosiX>=ScanX-RulesForSpecialElements[ScanForRule][XSIZEELERULE]-1) && (*PosiX<=ScanX) && (*PosiY>=ScanY) && (*PosiY<=ScanY+RulesForSpecialElements[ScanForRule][YSIZEELERULE]-1) ) { /* We've got it ! */ /* We make as we have clicked on the "alive" block ! */ *PosiX = ScanX; *PosiY = ScanY; return; } } ScanForRule++; } while(RulesForSpecialElements[ScanForRule][0]!=-1); } } }}int VerifyRulesForElement(short int NumEle,int PosiX,int PosiY){ int RulePass; int ItIsOk = TRUE; int ItIsAnOutputEle = FALSE; if ( (NumEle==ELE_OUTPUT) || (NumEle==ELE_OUTPUT_NOT) || (NumEle==ELE_OUTPUT_SET) || (NumEle==ELE_OUTPUT_RESET) || (NumEle==ELE_OUTPUT_JUMP) || (NumEle==ELE_OUTPUT_OPERATE) ) ItIsAnOutputEle = TRUE; /* verify for outputs if we are under output zone (right column) */ if ( (PosiX==RUNG_WIDTH-1) && !ItIsAnOutputEle ) { ItIsOk = FALSE; } /* verify for inputs if we are under input zone (not right column) */ if ( (PosiX<RUNG_WIDTH-1) && ItIsAnOutputEle ) { ItIsOk = FALSE; } /* verify if for elements bigger than one block it will fit */ RulePass = 0; do { if ( RulesForSpecialElements[RulePass][TYPEELERULE] == NumEle ) { if ( (PosiX-RulesForSpecialElements[RulePass][XSIZEELERULE]+1 < 0) || (PosiY+RulesForSpecialElements[RulePass][YSIZEELERULE]-1 >= RUNG_HEIGHT) ) ItIsOk = FALSE; } RulePass++; } while(RulesForSpecialElements[RulePass][0]!=-1); /* verify if we are not on another part of a big element ! */ if (EditDatas.Rung.Element[PosiX][PosiY].Type==ELE_UNUSABLE) ItIsOk = FALSE; return ItIsOk;}/* used for destroying or adding a big element *//* when destroying : filling all the blocks with ELE_FREE *//* when adding : filling all the blocks with ELE_UNUSABLE *//* the block "alive" is written elsewhere */void CleanForBigElement(short int NumEle,int PosiX,int PosiY,short int FillWithThis){ int RulePass; int PassX,PassY; RulePass = 0; do { if (RulesForSpecialElements[RulePass][TYPEELERULE] == NumEle ) { for (PassX = PosiX - RulesForSpecialElements[RulePass][XSIZEELERULE] +1 ; PassX<=PosiX ; PassX++) { for (PassY = PosiY ; PassY<=PosiY + RulesForSpecialElements[RulePass][YSIZEELERULE] -1 ; PassY++) { CheckForFreeingArithmExpr(PassX,PassY); EditDatas.Rung.Element[PassX][PassY].Type = FillWithThis; EditDatas.Rung.Element[PassX][PassY].ConnectedWithTop = 0; EditDatas.Rung.Element[PassX][PassY].DynamicOutput = 0; } } } RulePass++; } while(RulesForSpecialElements[RulePass][0]!=-1);}void CheckBigElementTopLeft(short int NumEle,int * PosiX){ int RulePass; RulePass = 0; do { if (RulesForSpecialElements[RulePass][TYPEELERULE] == NumEle ) { *PosiX = *PosiX + RulesForSpecialElements[RulePass][XSIZEELERULE] - 1; } RulePass++; } while(RulesForSpecialElements[RulePass][0]!=-1);}/* return TRUE if contact or coil element */int IsASimpleElement(int Element){ int Res = FALSE; if ( (Element==ELE_INPUT) || (Element==ELE_INPUT_NOT) || (Element==ELE_RISING_INPUT) || (Element==ELE_FALLING_INPUT) || (Element==ELE_OUTPUT) || (Element==ELE_OUTPUT_NOT) || (Element==ELE_OUTPUT_SET) || (Element==ELE_OUTPUT_RESET) ) Res = TRUE; return Res;}/* click with the mouse in x and y pixels of the rung */void EditElementInRung(double x,double y){ int RungX,RungY; short int NumElement; /* correspond to which block ? */ RungX = x/BlockWidth; RungY = y/BlockHeight; if ( (RungX<RUNG_WIDTH) && (RungY<RUNG_HEIGHT) && (EditDatas.NumElementSelectedInToolBar!=-1) ) { /* check for "unusable" blocks */ if (EditDatas.NumElementSelectedInToolBar==EDIT_POINTER) CheckForBlocksOfBigElement(&RungX,&RungY); if (EditDatas.NumElementSelectedInToolBar<ELE_UNUSABLE) { NumElement = EditDatas.NumElementSelectedInToolBar; /* For big element, click insert top-left of the element */ CheckBigElementTopLeft(NumElement,&RungX); /* already the same element ? => if yes kill it! */ if (NumElement==EditDatas.Rung.Element[RungX][RungY].Type) { NumElement = ELE_FREE; } /* apply the new element */ if (NumElement==ELE_FREE) { /* the blocks other than the "alive" are now free... */ CleanForBigElement(EditDatas.Rung.Element[RungX][RungY].Type,RungX,RungY,ELE_FREE); EditDatas.Rung.Element[RungX][RungY].DynamicOutput = 0; EditDatas.Rung.Element[RungX][RungY].Type = NumElement; } else { if (VerifyRulesForElement(NumElement,RungX,RungY)) { /* the blocks other than the "alive" are now free... */ CleanForBigElement(EditDatas.Rung.Element[RungX][RungY].Type,RungX,RungY,ELE_FREE); /* for big element with only one block "alive" we must mark the others */ /* blocks as unusable */ CleanForBigElement(NumElement,RungX,RungY,ELE_UNUSABLE); // if not a simple element (contact/coil) replaced by a simple element, clean VarNum if ( !(IsASimpleElement(NumElement) && IsASimpleElement(EditDatas.Rung.Element[RungX][RungY].Type)) ) { EditDatas.Rung.Element[RungX][RungY].VarNum = 0; } EditDatas.Rung.Element[RungX][RungY].Type = NumElement; CheckForAllocatingArithmExpr(RungX,RungY); } } } if (EditDatas.NumElementSelectedInToolBar==EDIT_CNX_WITH_TOP) { if (EditDatas.Rung.Element[RungX][RungY].ConnectedWithTop) EditDatas.Rung.Element[RungX][RungY].ConnectedWithTop = 0; else EditDatas.Rung.Element[RungX][RungY].ConnectedWithTop = 1; } if (EditDatas.NumElementSelectedInToolBar==EDIT_LONG_CONNECTION) { int ScanX = RungX; while(EditDatas.Rung.Element[ScanX][RungY].Type==ELE_FREE && ScanX<RUNG_WIDTH-1 ) { EditDatas.Rung.Element[ScanX++][RungY].Type = ELE_CONNECTION; } } LoadElementProperties(&EditDatas.Rung.Element[RungX][RungY]); EditDatas.ElementUnderEdit = &EditDatas.Rung.Element[RungX][RungY]; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -