/* Classic Ladder Project */ /* Copyright (C) 2001-2007 Marc Le Douarain */ /* http://membres.lycos.fr/mavati/classicladder/ */ /* http://www.sourceforge.net/projects/classicladder */ /* December 2003 */ /* --------------------------- */ /* Editor for Sequential Pages */ /* --------------------------- */ /* This part of the editor is the one who will not change even if if we use */ /* another gui instead of gtk... who know? */ /* ------------------------------------------------------------- */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Lesser General Public */ /* License as published by the Free Software Foundation; either */ /* version 2.1 of the License, or (at your option) any later version. */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Lesser General Public License for more details. */ /* You should have received a copy of the GNU Lesser General Public */ /* License along with this library; if not, write to the Free Software */ /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "classicladder.h" #include "global.h" #include "drawing.h" #include "edit.h" #include "editproperties_gtk.h" #include "classicladder_gtk.h" #include "calc_sequential.h" #include "vars_names.h" #include "edit_sequential.h" /* We modify the datas in this variable. It is only after clicking on apply that they are used */ StrSequential EditSeqDatas; int TypeSeqEleEdited = -1; int OffsetSeqEleEdited = 0; char TopSeqEleEdited = FALSE; /* for elements requiring many clicks to be done (link, multi-steps, 'Or' in transitions) */ int CptNbrClicksDone = 0; int NumElementSelectedInToolBarBak = -1; void LoadSeqElementProperties( void ) { char TextToWrite[100]; int NumParam; for(NumParam=0;NumParamAskConfirmationToQuit = TRUE; } int SearchStepElement( int PageNumber, int PositionX, int PositionY ) { int ScanStep; StrStep * pStep; int Result = -1; printf("step search posiX=%d, posiY=%d ; ", PositionX, PositionY ); for( ScanStep=0; ScanStepNumPage==PageNumber ) { if ( pStep->PosiX==PositionX && pStep->PosiY==PositionY ) Result = ScanStep; } } printf("found=%d!!!\n", Result ); return Result; } int SearchTransiElement( int PageNumber, int PositionX, int PositionY ) { int ScanTransi; StrTransition * pTransi; int Result = -1; printf("transi search posiX=%d, posiY=%d ; ", PositionX, PositionY ); for( ScanTransi=0; ScanTransiNumPage==PageNumber ) { if ( pTransi->PosiX==PositionX && pTransi->PosiY==PositionY ) Result = ScanTransi; } } printf("found=%d!!!\n", Result ); return Result; } int SearchCommentElement( int PageNumber, int PositionX, int PositionY ) { int ScanComment; StrSeqComment * pComment; int Result = -1; printf("comment search posiX=%d, posiY=%d ; ", PositionX, PositionY ); for( ScanComment=0; ScanCommentNumPage==PageNumber ) { if ( ( pComment->PosiX<=PositionX && PositionXPosiX+4 ) && pComment->PosiY==PositionY ) Result = ScanComment; } } printf("found=%d!!!\n", Result ); return Result; } /* -1 if not found */ int FindFreeStep( void ) { int ScanStep = 0; StrStep * pStep; int Result = -1; do { pStep = &EditSeqDatas.Step[ ScanStep ]; if ( pStep->NumPage==-1 ) Result = ScanStep; else ScanStep++; } while( Result==-1 && ScanStepNumPage==-1 ) Result = ScanTransi; else ScanTransi++; } while( Result==-1 && ScanTransiNumPage ); if ( pComment->NumPage==-1 ) Result = ScanComment; else ScanComment++; } while( Result==-1 && ScanCommentNumPage = -1; } /* -1 if not created */ int CreateStep( int page, int x, int y, char init ) { int TransiAssoc; int OffsetStepCreated = FindFreeStep( ); int TopStepForAutoNumber = -1; int NumStepForAutoNumber = 0; if ( OffsetStepCreated!=-1 ) { StrStep * pStep = &EditSeqDatas.Step[ OffsetStepCreated ]; pStep->NumPage = page; pStep->PosiX = x; pStep->PosiY = y; pStep->InitStep = init; // look if there is a step on the top, to directly give next step number TopStepForAutoNumber = SearchStepElement( page, x, y-2 ); if ( TopStepForAutoNumber==-1 ) { // search next step number available... int ScanStep = 0; for( ScanStep=0; ScanStepNumPage!=-1 ) { // already used ? if ( NumStepForAutoNumber==pScanStep->StepNumber ) NumStepForAutoNumber = pScanStep->StepNumber+1; } } } else { NumStepForAutoNumber = EditSeqDatas.Step[ TopStepForAutoNumber ].StepNumber+1; } pStep->StepNumber = NumStepForAutoNumber; // search top transi to connect with TransiAssoc = SearchTransiElement( page, x, y-1 ); if ( TransiAssoc!=-1 ) EditSeqDatas.Transition[ TransiAssoc ].NumStepToActiv[ 0 ] = OffsetStepCreated; // search bottom transi to connect with TransiAssoc = SearchTransiElement( page, x, y+1 ); if ( TransiAssoc!=-1 ) EditSeqDatas.Transition[ TransiAssoc ].NumStepToDesactiv[ 0 ] = OffsetStepCreated; } return OffsetStepCreated; } void DestroyTransi( int Offset ) { StrTransition * pTransi = &EditSeqDatas.Transition[ Offset ]; pTransi->NumPage = -1; } /* -1 if not created */ int CreateTransi( int page, int x, int y ) { int StepAssoc; int NumSwitch; int OffsetCreated = FindFreeTransi( ); int TopTransiForAutoVar = -1; if ( OffsetCreated!=-1 ) { StrTransition * pTransi = &EditSeqDatas.Transition[ OffsetCreated ]; pTransi->NumPage = page; pTransi->PosiX = x; pTransi->PosiY = y; pTransi->VarTypeCondi = VAR_MEM_BIT; pTransi->VarNumCondi = 0; // look if there is a transition on the top, to directly give next variable number TopTransiForAutoVar = SearchTransiElement( page, x, y-2 ); if ( TopTransiForAutoVar!=-1 ) { pTransi->VarTypeCondi = EditSeqDatas.Transition[ TopTransiForAutoVar ].VarTypeCondi; pTransi->VarNumCondi = EditSeqDatas.Transition[ TopTransiForAutoVar ].VarNumCondi+1; } for( NumSwitch=0; NumSwitchNumStepToActiv[ NumSwitch ] = -1; pTransi->NumStepToDesactiv[ NumSwitch ] = -1; pTransi->NumTransLinkedForStart[ NumSwitch ] = -1; pTransi->NumTransLinkedForEnd[ NumSwitch ] = -1; } // search top step to connect with if ( y>0 ) { StepAssoc = SearchStepElement( page, x, y-1 ); if ( StepAssoc!=-1 ) pTransi->NumStepToDesactiv[ 0 ] = StepAssoc; } // search bottom step to connect with if ( yNumStepToActiv[ 0 ] = StepAssoc; } } return OffsetCreated; } void DestroyComment( int Offset ) { StrSeqComment * pComment = &EditSeqDatas.SeqComment[ Offset ]; pComment->NumPage = -1; } /* -1 if could not be created */ int CreateComment( int page, int x, int y ) { int OffsetCommentCreated = FindFreeComment( ); if ( OffsetCommentCreated!=-1 ) { StrSeqComment * pComment = &EditSeqDatas.SeqComment[ OffsetCommentCreated ]; pComment->Comment[ 0 ] = '\0'; pComment->NumPage = page; pComment->PosiX = x; pComment->PosiY = y; } return OffsetCommentCreated; } void DoLinkTransitionAndStep( int OffsetTransi, char TopOfTransi, int OffsetStep ) { StrTransition * pTransi = &EditSeqDatas.Transition[ OffsetTransi ]; printf("Do link : transi=%d (top=%d), step=%d\n", OffsetTransi, TopOfTransi, OffsetStep); if ( TopOfTransi ) pTransi->NumStepToDesactiv[ 0 ] = OffsetStep; else pTransi->NumStepToActiv[ 0 ] = OffsetStep; } /* return TRUE is okay */ char CommonSearchForManyStepsOrTransi( char ForManySteps, int TypeEle1, int OffEle1, int TypeEle2, int OffEle2, int * pOffsetTransiFound, int * pStepsBaseY, int * pTransitionsBaseY, int * pLeftX, int * pRightX ) { int OffsetTransiFound = -1; int StepsBaseY = -1; int TransitionsBaseY = -1; int Ele1X,Ele2X; int LeftX,RightX; if ( !ForManySteps && (TypeEle1==ELE_SEQ_STEP || TypeEle2==ELE_SEQ_STEP ) ) { ShowMessageBox("Error","Not selected first and last transitions to be joined !!??","Ok"); return FALSE; } if ( TypeEle1==ELE_SEQ_STEP ) { Ele1X = EditSeqDatas.Step[ OffEle1 ].PosiX; StepsBaseY = EditSeqDatas.Step[ OffEle1 ].PosiY; } else if ( TypeEle1==ELE_SEQ_TRANSITION ) { // search transition corresponding... directly clicked on it! OffsetTransiFound = OffEle1; Ele1X = EditSeqDatas.Transition[ OffEle1 ].PosiX; TransitionsBaseY = EditSeqDatas.Transition[ OffEle1 ].PosiY; } else { ShowMessageBox("Error","Unknown element type for Ele1","Ok"); return FALSE; } if ( TypeEle2==ELE_SEQ_STEP ) { Ele2X = EditSeqDatas.Step[ OffEle2 ].PosiX; if ( StepsBaseY==-1 ) { StepsBaseY = EditSeqDatas.Step[ OffEle1 ].PosiY; } else { if ( StepsBaseY!=EditSeqDatas.Step[ OffEle1 ].PosiY ) { ShowMessageBox("Error","First and last steps selected are not on the same line !!??","Ok"); return FALSE; } } } else if ( TypeEle2==ELE_SEQ_TRANSITION ) { OffsetTransiFound = OffEle2; Ele2X = EditSeqDatas.Transition[ OffEle2 ].PosiX; if ( TransitionsBaseY==-1 ) { TransitionsBaseY = EditSeqDatas.Transition[ OffEle1 ].PosiY; } else { if ( TransitionsBaseY!=EditSeqDatas.Transition[ OffEle1 ].PosiY ) { ShowMessageBox("Error","First and last transitions selected are not on the same line !!??","Ok"); return FALSE; } } } else { ShowMessageBox("Error","Unknown element type for Ele2","Ok"); return FALSE; } LeftX = Ele1X; RightX = Ele1X; if ( LeftX>Ele2X ) LeftX = Ele2X; if ( RightX=2 ) { for( ScanTransiArray=0; ScanTransiArrayNumTransLinkedForStart[ ScanTransi ] = -1; else pTheTransi->NumTransLinkedForEnd[ ScanTransi ] = -1; } // put the others transitions than itself ScanTransi = 0; for( ScanTransiArray2=0; ScanTransiArray2storing num transi linked=%d for transi=%d\n", NumTransi, TheTransi ); if ( FlagStart ) { pTheTransi->NumTransLinkedForStart[ ScanTransi++ ] = NumTransi; if ( EditSeqDatas.Transition[ NumTransi ].NumStepToDesactiv[ 0 ]!=-1 ) StepToDesact = EditSeqDatas.Transition[ NumTransi ].NumStepToDesactiv[ 0 ]; } else { pTheTransi->NumTransLinkedForEnd[ ScanTransi++ ] = NumTransi; if ( EditSeqDatas.Transition[ NumTransi ].NumStepToActiv[ 0 ]!=-1 ) StepToAct = EditSeqDatas.Transition[ NumTransi ].NumStepToActiv[ 0 ]; } } } // step to activate / descativate printf("=>step to activ=%d, step to desactiv=%d\n", StepToAct, StepToDesact ); if ( StepToAct!=-1 ) pTheTransi->NumStepToActiv[ 0 ] = StepToAct; if ( StepToDesact!=-1 ) pTheTransi->NumStepToDesactiv[ 0 ] = StepToDesact; } } else { ShowMessageBox("Error","Not found at least 2 transitions linked...","Ok"); } } } void DestroyIt( int Type, int Offset ) { switch( Type ) { case ELE_SEQ_STEP: DestroyStep( Offset ); break; case ELE_SEQ_TRANSITION: DestroyTransi( Offset ); break; case ELE_SEQ_COMMENT: DestroyComment( Offset ); break; } } void SearchIt( int PageNbr, int PosX, int PosY, int * Type, int * Offset ) { int TypeFound = -1; int OffsetFound = -1; /* steps are on odd lines, transitions on even ones */ if ( PosY & 1 ) { OffsetFound = SearchStepElement( PageNbr, PosX, PosY ); if ( OffsetFound!=-1 ) { TypeFound = ELE_SEQ_STEP; TopSeqEleEdited = TypeFound; } } else { OffsetFound = SearchTransiElement( PageNbr, PosX, PosY ); if ( OffsetFound!=-1 ) { TypeFound = ELE_SEQ_TRANSITION; TopSeqEleEdited = TypeFound; } } /* comments can be on any lines */ if ( OffsetFound==-1 ) { OffsetFound = SearchCommentElement( PageNbr, PosX, PosY ); if ( OffsetFound!=-1 ) { TypeFound = ELE_SEQ_COMMENT; TopSeqEleEdited = TypeFound; } } *Type = TypeFound; *Offset = OffsetFound; } /* click with the mouse in x and y pixels of the sequential page */ void EditElementInSeqPage(double x,double y) { int PosX,PosY; /* correspond to which block ? */ PosX = x/SEQ_SIZE_DEF; PosY = y/SEQ_SIZE_DEF; if ( (PosXPosY*SEQ_SIZE_DEF && yCurrentSection ].SequentialPage; // for comments, verify 4 horizontal blocks if ( EditDatas.NumElementSelectedInToolBar!=NumElementSelectedInToolBarBak ) CptNbrClicksDone = 0; NumElementSelectedInToolBarBak = EditDatas.NumElementSelectedInToolBar; //printf("top clicked= %d\n", TopFound ); TypeSeqEleEdited = -1; /* search element selected */ SearchIt( CurrentSeqPage, PosX, PosY, &TypeFound, &OffsetFound ); switch( EditDatas.NumElementSelectedInToolBar ) { case EDIT_POINTER: TypeSeqEleEdited = TypeFound; OffsetSeqEleEdited = OffsetFound; break; case ELE_SEQ_STEP: case EDIT_SEQ_INIT_STEP: case ELE_SEQ_TRANSITION: case EDIT_SEQ_STEP_AND_TRANS: if ( EditDatas.NumElementSelectedInToolBar==ELE_SEQ_STEP || EditDatas.NumElementSelectedInToolBar==EDIT_SEQ_INIT_STEP || EditDatas.NumElementSelectedInToolBar==EDIT_SEQ_STEP_AND_TRANS ) { if ( PosY & 1 ) { if ( TypeFound==ELE_SEQ_STEP ) { DestroyStep( OffsetFound ); } else { if ( TypeFound==-1 ) { OffsetFound = CreateStep( CurrentSeqPage, PosX, PosY, (EditDatas.NumElementSelectedInToolBar==EDIT_SEQ_INIT_STEP)?TRUE:FALSE ); if ( OffsetFound!=-1 ) { TypeSeqEleEdited = ELE_SEQ_STEP; OffsetSeqEleEdited = OffsetFound; } else { ShowMessageBox("Error","Sequential memory full for steps","Ok"); } } else { ShowMessageBox("Error","There is already an element!","Ok"); } } } else { ShowMessageBox("Error","A step can't be placed on even lines","Ok"); } } if ( EditDatas.NumElementSelectedInToolBar==ELE_SEQ_TRANSITION || EditDatas.NumElementSelectedInToolBar==EDIT_SEQ_STEP_AND_TRANS ) { if ( EditDatas.NumElementSelectedInToolBar==EDIT_SEQ_STEP_AND_TRANS ) PosY++; if ( (PosY & 1)==0 ) { if ( TypeFound==ELE_SEQ_TRANSITION ) { DestroyTransi( OffsetFound ); } else { if ( TypeFound==-1 ) { OffsetFound = CreateTransi( CurrentSeqPage, PosX, PosY ); if ( OffsetFound!=-1 ) { TypeSeqEleEdited = ELE_SEQ_TRANSITION; OffsetSeqEleEdited = OffsetFound; } else { ShowMessageBox("Error","Sequential memory full for transition","Ok"); } } else { ShowMessageBox("Error","There is already an element!","Ok"); } } } else { ShowMessageBox("Error","A transition can't be placed on odd lines","Ok"); } } break; case EDIT_SEQ_LINK: if ( TypeFound!=-1 ) CptNbrClicksDone++; if ( CptNbrClicksDone==1 ) { printf("nbr clicks=1!!! (posi=%s), wait next point to link...\n", (TopFound==1)?"top":"bottom" ); TypeSeqEleEdited = TypeFound; OffsetSeqEleEdited = OffsetFound; TopSeqEleEdited = TopFound; //TODO: modify cursor so that it is a little more explicit...? } if ( CptNbrClicksDone==2 ) { printf("nbr clicks=2!!! (posi=%s), TypeBak=%d, TypeNow=%d\n", (TopFound==1)?"top":"bottom", TypeSeqEleEditedBak, TypeFound ); if ( TypeSeqEleEditedBak==ELE_SEQ_TRANSITION && TypeFound==ELE_SEQ_STEP ) DoLinkTransitionAndStep( OffsetSeqEleEditedBak, TopSeqEleEditedBak, OffsetFound ); if ( TypeSeqEleEditedBak==ELE_SEQ_STEP && TypeFound==ELE_SEQ_TRANSITION ) DoLinkTransitionAndStep( OffsetFound, TopFound, OffsetSeqEleEditedBak ); CptNbrClicksDone = 0; } break; case EDIT_ERASER: if ( TypeFound!=-1 ) DestroyIt( TypeFound, OffsetFound ); break; case ELE_SEQ_COMMENT: // a comment takes 4 horizontal blocks if ( PosX<=SEQ_PAGE_WIDTH-4 ) { // verify if elements that would be under it... int ScanHoriX; char SomethingHere = FALSE; for ( ScanHoriX=PosX; ScanHoriX