/** \file csignal.c * Signals */ /* -*- C -*- **************************************************************** * * System : * Module : * Object Name : $RCSfile$ * Revision : $Revision$ * Date : $Date$ * Author : $Author$ * Created By : Robert Heller * Created : Sun Feb 19 13:11:45 2017 * Last Modified : <170417.1113> * * Description * * Notes * * History * **************************************************************************** * * Copyright (C) 2017 Robert Heller D/B/A Deepwoods Software * 51 Locke Hill Road * Wendell, MA 01379-9728 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * ****************************************************************************/ static const char rcsid[] = "@(#) : $Id$"; #include "compound.h" #include "cselect.h" #include "cundo.h" #include "custom.h" #include "fileio.h" #include "layout.h" #include "param.h" #include "track.h" #include "trackx.h" #include "common-ui.h" #ifdef UTFCONVERT #include "include/utf8convert.h" #endif // UTFCONVERT EXPORT TRKTYP_T T_SIGNAL = -1; static int log_signal = 0; #if 0 static drawCmd_t signalD = { NULL, &screenDrawFuncs, 0, 1.0, 0.0, {0.0,0.0}, {0.0,0.0}, Pix2CoOrd, CoOrd2Pix }; static char signalName[STR_SHORT_SIZE]; static int signalHeadCount; #endif typedef struct signalAspect_t { char * aspectName; char * aspectScript; } signalAspect_t, *signalAspect_p; static dynArr_t signalAspect_da; #define signalAspect(N) DYNARR_N( signalAspect_t, signalAspect_da, N ) typedef struct signalData_t { extraDataBase_t base; coOrd orig; ANGLE_T angle; char * name; wIndex_t numHeads; BOOL_T IsHilite; wIndex_t numAspects; signalAspect_t aspectList; } signalData_t, *signalData_p; static signalData_p GetsignalData ( track_p trk ) { return GET_EXTRA_DATA( trk, T_SIGNAL, signalData_t ); } #define BASEX 6 #define BASEY 0 #define MASTX 0 #define MASTY 12 #define HEADR 4 #define signal_SF (3.0) static void DDrawSignal(drawCmd_p d, coOrd orig, ANGLE_T angle, wIndex_t numHeads, DIST_T scaleRatio, wDrawColor color ) { coOrd p1, p2; ANGLE_T x_angle, y_angle; DIST_T hoffset; wIndex_t ihead; x_angle = 90-(360-angle); if (x_angle < 0) x_angle += 360; y_angle = -(360-angle); if (y_angle < 0) y_angle += 360; Translate (&p1, orig, x_angle, (-BASEX) * signal_SF / scaleRatio); Translate (&p1, p1, y_angle, BASEY * signal_SF / scaleRatio); Translate (&p2, orig, x_angle, BASEX * signal_SF / scaleRatio); Translate (&p2, p2, y_angle, BASEY * signal_SF / scaleRatio); DrawLine(d, p1, p2, 2, color); p1 = orig; Translate (&p2, orig, x_angle, MASTX * signal_SF / scaleRatio); Translate (&p2, p2, y_angle, MASTY * signal_SF / scaleRatio); DrawLine(d, p1, p2, 2, color); hoffset = MASTY; for (ihead = 0; ihead < numHeads; ihead++) { Translate (&p1, orig, x_angle, MASTX * signal_SF / scaleRatio); Translate (&p1, p1, y_angle, (hoffset+HEADR) * signal_SF / scaleRatio); DrawFillCircle(d,p1,HEADR * signal_SF / scaleRatio,color); hoffset += HEADR*2; } } static void DrawSignal (track_p t, drawCmd_p d, wDrawColor color ) { signalData_p xx = GetsignalData(t); DDrawSignal(d,xx->orig, xx->angle, xx->numHeads, GetScaleRatio(GetTrkScale(t)),color); } static void SignalBoundingBox (coOrd orig, ANGLE_T angle,wIndex_t numHeads, DIST_T scaleRatio, coOrd *hi, coOrd *lo) { coOrd p1, p2, headp1, headp2; ANGLE_T x_angle, y_angle; DIST_T hoffset,delta; wIndex_t ihead; x_angle = 90-(360-angle); if (x_angle < 0) x_angle += 360; y_angle = -(360-angle); if (y_angle < 0) y_angle += 360; Translate (&p1, orig, x_angle, (-BASEX) * signal_SF / scaleRatio); Translate (&p1, p1, y_angle, BASEY * signal_SF / scaleRatio); Translate (&p2, orig, x_angle, BASEX * signal_SF / scaleRatio); Translate (&p2, p2, y_angle, BASEY * signal_SF / scaleRatio); *hi = p1; *lo = p1; if (p2.x > hi->x) hi->x = p2.x; if (p2.x < lo->x) lo->x = p2.x; if (p2.y > hi->y) hi->y = p2.y; if (p2.y < lo->y) lo->y = p2.y; p1 = orig; Translate (&p2, orig, x_angle, MASTX * signal_SF / scaleRatio); Translate (&p2, p2, y_angle, MASTY * signal_SF / scaleRatio); if (p1.x > hi->x) hi->x = p1.x; if (p1.x < lo->x) lo->x = p1.x; if (p1.y > hi->y) hi->y = p1.y; if (p1.y < lo->y) lo->y = p1.y; if (p2.x > hi->x) hi->x = p2.x; if (p2.x < lo->x) lo->x = p2.x; if (p2.y > hi->y) hi->y = p2.y; if (p2.y < lo->y) lo->y = p2.y; hoffset = MASTY; for (ihead = 0; ihead < numHeads; ihead++) { Translate (&p1, orig, x_angle, MASTX * signal_SF / scaleRatio); Translate (&p1, p1, y_angle, (hoffset+HEADR) * signal_SF / scaleRatio); delta = HEADR * signal_SF / scaleRatio; headp1.x = p1.x - delta; headp1.y = p1.y - delta; headp2.x = p1.x + delta; headp2.y = p1.y + delta; if (headp1.x > hi->x) hi->x = headp1.x; if (headp1.x < lo->x) lo->x = headp1.x; if (headp1.y > hi->y) hi->y = headp1.y; if (headp1.y < lo->y) lo->y = headp1.y; if (headp2.x > hi->x) hi->x = headp2.x; if (headp2.x < lo->x) lo->x = headp2.x; if (headp2.y > hi->y) hi->y = headp2.y; if (headp2.y < lo->y) lo->y = headp2.y; hoffset += HEADR*2; } } static void ComputeSignalBoundingBox (track_p t ) { coOrd lo, hi; signalData_p xx = GetsignalData(t); SignalBoundingBox(xx->orig, xx->angle, xx->numHeads, GetScaleRatio(GetTrkScale(t)), &hi, &lo); SetBoundingBox(t, hi, lo); } static DIST_T DistanceSignal (track_p t, coOrd * p ) { signalData_p xx = GetsignalData(t); return FindDistance(xx->orig, *p); } static struct { char name[STR_SHORT_SIZE]; coOrd pos; ANGLE_T orient; long heads; } signalProperties; typedef enum { NM, PS, OR, HD } signalDesc_e; static descData_t signalDesc[] = { /* NM */ { DESC_STRING, N_("Name"), &signalProperties.name, sizeof(signalProperties.name) }, /* PS */ { DESC_POS, N_("Position"), &signalProperties.pos }, /* OR */ { DESC_ANGLE, N_("Angle"), &signalProperties.orient }, /* HD */ { DESC_LONG, N_("Number Of Heads"), &signalProperties.heads }, { DESC_NULL } }; static void UpdateSignalProperties ( track_p trk, int inx, descData_p descUpd, BOOL_T needUndoStart ) { signalData_p xx = GetsignalData( trk ); const char *thename; char *newName; BOOL_T changed, nChanged, pChanged, oChanged; switch (inx) { case NM: break; case PS: break; case OR: break; case HD: break; case -1: changed = nChanged = pChanged = oChanged = FALSE; thename = wStringGetValue( (wString_p) signalDesc[NM].control0 ); if (strcmp(thename,xx->name) != 0) { nChanged = changed = TRUE; unsigned int max_str = signalDesc[NM].max_string; if (max_str && strlen(thename)>max_str) { newName = MyMalloc(max_str); newName[max_str-1] = '\0'; strncat(newName,thename, max_str-1); NoticeMessage2(0, MSG_ENTERED_STRING_TRUNCATED, _("Ok"), NULL, max_str-1); } else newName = MyStrdup(thename); } if (signalProperties.pos.x != xx->orig.x || signalProperties.pos.y != xx->orig.y) { pChanged = changed = TRUE; } if (signalProperties.orient != xx->angle) { oChanged = changed = TRUE; } if (!changed) break; if (needUndoStart) UndoStart( _("Change Signal"), "Change Signal" ); UndoModify( trk ); if (nChanged) { MyFree(xx->name); xx->name = newName; } if (pChanged || oChanged) { UndrawNewTrack( trk ); } if (pChanged) { xx->orig = signalProperties.pos; } if (oChanged) { xx->angle = signalProperties.orient; } if (pChanged || oChanged) { ComputeSignalBoundingBox( trk ); DrawNewTrack( trk ); } break; } } static void DescribeSignal (track_p trk, char * str, CSIZE_T len ) { signalData_p xx = GetsignalData(trk); strcpy( str, _(GetTrkTypeName( trk )) ); str++; while (*str) { *str = tolower((unsigned char)*str); str++; } sprintf( str, _("(%d [%s]): Layer=%u, %d heads at %0.3f,%0.3f A%0.3f"), GetTrkIndex(trk), xx->name,GetTrkLayer(trk)+1, xx->numHeads, xx->orig.x, xx->orig.y,xx->angle ); strncpy(signalProperties.name,xx->name,STR_SHORT_SIZE-1); signalProperties.name[STR_SHORT_SIZE-1] = '\0'; signalProperties.pos = xx->orig; signalProperties.orient = xx->angle; signalProperties.heads = xx->numHeads; signalDesc[HD].mode = DESC_RO; signalDesc[NM].mode = DESC_NOREDRAW; DoDescribe( _("Signal"), trk, signalDesc, UpdateSignalProperties ); } static void DeleteSignal ( track_p trk ) { wIndex_t ia; signalData_p xx = GetsignalData(trk); MyFree(xx->name); xx->name = NULL; for (ia = 0; ia < xx->numAspects; ia++) { MyFree((&(xx->aspectList))[ia].aspectName); MyFree((&(xx->aspectList))[ia].aspectScript); } } static BOOL_T WriteSignal ( track_p t, FILE * f ) { BOOL_T rc = TRUE; wIndex_t ia; signalData_p xx = GetsignalData(t); char *signalName = MyStrdup(xx->name); #ifdef UTFCONVERT signalName = Convert2UTF8(signalName); #endif // UTFCONVERT rc &= fprintf(f, "SIGNAL %d %u %s %d %0.6f %0.6f %0.6f %d \"%s\"\n", GetTrkIndex(t), GetTrkLayer(t), GetTrkScaleName(t), GetTrkVisible(t), xx->orig.x, xx->orig.y, xx->angle, xx->numHeads, signalName)>0; for (ia = 0; ia < xx->numAspects; ia++) { rc &= fprintf(f, "\tASPECT \"%s\" \"%s\"\n", (&(xx->aspectList))[ia].aspectName, (&(xx->aspectList))[ia].aspectScript)>0; } rc &= fprintf( f, "\t%s\n",END_SIGNAL )>0; MyFree(signalName); return rc; } static BOOL_T ReadSignal ( char * line ) { /*TRKINX_T trkindex;*/ wIndex_t index; track_p trk; char * cp = NULL; wIndex_t ia; char *name; char *aspname, *aspscript; wIndex_t numHeads; coOrd orig; ANGLE_T angle; BOOL_T visible; char scale[10]; wIndex_t layer; signalData_p xx; if (!GetArgs(line+6,"dLsdpfdq",&index,&layer,scale, &visible, &orig, &angle, &numHeads,&name)) { return FALSE; } #ifdef UTFCONVERT ConvertUTF8ToSystem(name); #endif // UTFCONVERT DYNARR_RESET( signalAspect_p, signalAspect_da ); while ( (cp = GetNextLine()) != NULL ) { if ( IsEND( END_SIGNAL) ) { break; } while (isspace((unsigned char)*cp)) cp++; if ( *cp == '\n' || *cp == '#' ) { continue; } if ( strncmp( cp, "ASPECT", 6 ) == 0 ) { if (!GetArgs(cp+4,"qq",&aspname,&aspscript)) return FALSE; DYNARR_APPEND( signalAspect_p *, signalAspect_da, 10 ); signalAspect(signalAspect_da.cnt-1).aspectName = aspname; signalAspect(signalAspect_da.cnt-1).aspectScript = aspscript; } } trk = NewTrack(index, T_SIGNAL, 0, sizeof(signalData_t)+(sizeof(signalAspect_t)*(signalAspect_da.cnt-1))+1); SetTrkVisible(trk, visible); SetTrkScale(trk, LookupScale( scale )); SetTrkLayer(trk, layer); xx = GetsignalData ( trk ); xx->name = name; xx->numHeads = numHeads; xx->orig = orig; xx->angle = angle; xx->numAspects = signalAspect_da.cnt; for (ia = 0; ia < xx->numAspects; ia++) { (&(xx->aspectList))[ia].aspectName = signalAspect(ia).aspectName; (&(xx->aspectList))[ia].aspectScript = signalAspect(ia).aspectScript; } ComputeSignalBoundingBox(trk); return TRUE; } static void MoveSignal (track_p trk, coOrd orig ) { signalData_p xx = GetsignalData ( trk ); xx->orig.x += orig.x; xx->orig.y += orig.y; ComputeSignalBoundingBox(trk); } static void RotateSignal (track_p trk, coOrd orig, ANGLE_T angle ) { signalData_p xx = GetsignalData ( trk ); Rotate(&(xx->orig), orig, angle); xx->angle = NormalizeAngle(xx->angle + angle); ComputeSignalBoundingBox(trk); } static void RescaleSignal (track_p trk, FLOAT_T ratio ) { } static void FlipSignal (track_p trk, coOrd orig, ANGLE_T angle ) { signalData_p xx = GetsignalData ( trk ); FlipPoint(&(xx->orig), orig, angle); xx->angle = NormalizeAngle(2*angle - xx->angle); ComputeSignalBoundingBox(trk); } static trackCmd_t signalCmds = { "SIGNAL", DrawSignal, DistanceSignal, DescribeSignal, DeleteSignal, WriteSignal, ReadSignal, MoveSignal, RotateSignal, RescaleSignal, NULL, /* audit */ NULL, /* getAngle */ NULL, /* split */ NULL, /* traverse */ NULL, /* enumerate */ NULL, /* redraw */ NULL, /* trim */ NULL, /* merge */ NULL, /* modify */ NULL, /* getLength */ NULL, /* getTrkParams */ NULL, /* moveEndPt */ NULL, /* query */ NULL, /* ungroup */ FlipSignal, /* flip */ NULL, /* drawPositionIndicator */ NULL, /* advancePositionIndicator */ NULL, /* checkTraverse */ NULL, /* makeParallel */ NULL /* drawDesc */ }; static BOOL_T signalCreate_P; static coOrd signalEditOrig; static ANGLE_T signalEditAngle; static track_p signalEditTrack; static char signalEditName[STR_SHORT_SIZE]; static long signalEditHeadCount; static char signalAspectEditName[STR_SHORT_SIZE]; static char signalAspectEditScript[STR_LONG_SIZE]; static long signalAspectEditIndex; static paramIntegerRange_t r1_3 = {1, 3}; static wWinPix_t aspectListWidths[] = { STR_SHORT_SIZE, 150 }; static const char * aspectListTitles[] = { N_("Name"), N_("Script") }; static paramListData_t aspectListData = {10, 400, 2, aspectListWidths, aspectListTitles}; static void AspectEdit( void * action ); static void AspectAdd( void * action ); static void AspectDelete( void * action ); static paramFloatRange_t r_1000_1000 = { -1000.0, 1000.0, 80 }; static paramFloatRange_t r0_360 = { 0.0, 360.0, 80 }; static paramData_t signalEditPLs[] = { #define I_SIGNALNAME (0) /*0*/ { PD_STRING, signalEditName, "name", PDO_NOPREF|PDO_NOTBLANK, I2VP(200), N_("Name"), 0, 0, sizeof(signalEditName)}, #define I_ORIGX (1) /*1*/ { PD_FLOAT, &signalEditOrig.x, "origx", PDO_DIM, &r_1000_1000, N_("Origin X") }, #define I_ORIGY (2) /*2*/ { PD_FLOAT, &signalEditOrig.y, "origy", PDO_DIM, &r_1000_1000, N_("Origin Y") }, #define I_ANGLE (3) /*3*/ { PD_FLOAT, &signalEditAngle, "origa", PDO_ANGLE, &r0_360, N_("Angle") }, #define I_SIGNALHEADCOUNT (4) /*4*/ { PD_LONG, &signalEditHeadCount, "headCount", PDO_NOPREF, &r1_3, N_("Number of Heads") }, #define I_SIGNALASPECTLIST (5) #define aspectSelL ((wList_p)signalEditPLs[I_SIGNALASPECTLIST].control) /*5*/ { PD_LIST, NULL, "inx", PDO_DLGRESETMARGIN|PDO_DLGRESIZE, &aspectListData, NULL, BL_MANY }, #define I_SIGNALASPECTEDIT (6) /*6*/ { PD_BUTTON, AspectEdit, "edit", PDO_DLGCMDBUTTON, NULL, N_("Edit Aspect") }, #define I_SIGNALASPECTADD (7) /*7*/ { PD_BUTTON, AspectAdd, "add", PDO_DLGCMDBUTTON, NULL, N_("Add Aspect") }, #define I_SIGNALASPECTDELETE (8) /*8*/ { PD_BUTTON, AspectDelete, "delete", 0, NULL, N_("Delete Aspect") }, }; static paramGroup_t signalEditPG = { "signalEdit", 0, signalEditPLs, COUNT( signalEditPLs ) }; static wWin_p signalEditW; static paramIntegerRange_t rm1_999999 = { -1, 999999 }; static paramData_t aspectEditPLs[] = { #define I_ASPECTNAME (0) /*0*/ { PD_STRING, signalAspectEditName, "name", PDO_NOPREF|PDO_NOTBLANK, I2VP(200), N_("Name"), 0, 0, sizeof(signalAspectEditName)}, #define I_ASPECTSCRIPT (1) /*1*/ { PD_STRING, signalAspectEditScript, "script", PDO_NOPREF, I2VP(350), N_("Script"), 0, 0, sizeof(signalAspectEditScript)}, #define I_ASPECTINDEX (2) /*2*/ { PD_LONG, &signalAspectEditIndex, "index", PDO_NOPREF, &rm1_999999, N_("Aspect Index"), BO_READONLY }, }; static paramGroup_t aspectEditPG = { "aspectEdit", 0, aspectEditPLs, COUNT( aspectEditPLs ) }; static wWin_p aspectEditW; static void SignalEditOk ( void * junk ) { track_p trk; signalData_p xx; wIndex_t ia; CSIZE_T newsize; if (signalCreate_P) { UndoStart( _("Create Signal"), "Create Signal"); trk = NewTrack(0, T_SIGNAL, 0, sizeof(signalData_t)+(sizeof(signalAspect_t)*(signalAspect_da.cnt-1))+1); xx = GetsignalData(trk); } else { UndoStart( _("Modify Signal"), "Modify Signal"); trk = signalEditTrack; xx = GetsignalData(trk); if (xx->numAspects != signalAspect_da.cnt) { /* We need to reallocate the extra data. */ for (ia = 0; ia < xx->numAspects; ia++) { MyFree((&(xx->aspectList))[ia].aspectName); MyFree((&(xx->aspectList))[ia].aspectScript); (&(xx->aspectList))[ia].aspectName = NULL; (&(xx->aspectList))[ia].aspectScript = NULL; } newsize = sizeof(signalData_t)+(sizeof(signalAspect_t)*(signalAspect_da.cnt-1))+1; trk->extraData = MyRealloc(trk->extraData,newsize); trk->extraSize = newsize; xx = GetsignalData(trk); } } xx->orig = signalEditOrig; xx->angle = signalEditAngle; xx->numHeads = signalEditHeadCount; if ( xx->name == NULL || strncmp (xx->name, signalEditName, STR_SHORT_SIZE) != 0) { MyFree(xx->name); xx->name = MyStrdup(signalEditName); } xx->numAspects = signalAspect_da.cnt; for (ia = 0; ia < xx->numAspects; ia++) { if ((&(xx->aspectList))[ia].aspectName == NULL) { (&(xx->aspectList))[ia].aspectName = signalAspect(ia).aspectName; } else if (strcmp((&(xx->aspectList))[ia].aspectName,signalAspect(ia).aspectName) != 0) { MyFree((&(xx->aspectList))[ia].aspectName); (&(xx->aspectList))[ia].aspectName = signalAspect(ia).aspectName; } else { MyFree(signalAspect(ia).aspectName); } if ((&(xx->aspectList))[ia].aspectScript == NULL) { (&(xx->aspectList))[ia].aspectScript = signalAspect(ia).aspectScript; } else if (strcmp((&(xx->aspectList))[ia].aspectScript,signalAspect(ia).aspectScript) != 0) { MyFree((&(xx->aspectList))[ia].aspectScript); (&(xx->aspectList))[ia].aspectScript = signalAspect(ia).aspectScript; } else { MyFree(signalAspect(ia).aspectScript); } } UndoEnd(); DoRedraw(); ComputeSignalBoundingBox(trk); wHide( signalEditW ); } static void SignalEditCancel ( wWin_p junk ) { wIndex_t ia; for (ia = 0; ia < signalAspect_da.cnt; ia++) { MyFree(signalAspect(ia).aspectName); MyFree(signalAspect(ia).aspectScript); } DYNARR_RESET( signalAspect_p, signalAspect_da ); wHide( signalEditW ); } static void SignalEditDlgUpdate (paramGroup_p pg, int inx, void *valueP ) { wIndex_t selcnt = wListGetSelectedCount( aspectSelL ); if ( inx != I_SIGNALASPECTLIST ) return; ParamControlActive( &signalEditPG, I_SIGNALASPECTEDIT, selcnt>0 ); ParamControlActive( &signalEditPG, I_SIGNALASPECTADD, TRUE ); ParamControlActive( &signalEditPG, I_SIGNALASPECTDELETE, selcnt>0 ); } static void aspectEditOK ( void * junk ) { if (signalAspectEditIndex < 0) { DYNARR_APPEND( signalAspect_p *, signalAspect_da, 10 ); signalAspect(signalAspect_da.cnt-1).aspectName = MyStrdup(signalAspectEditName); signalAspect(signalAspect_da.cnt-1).aspectScript = MyStrdup(signalAspectEditScript); snprintf(message,sizeof(message),"%s\t%s",signalAspectEditName,signalAspectEditScript); wListAddValue( aspectSelL, message, NULL, NULL ); } else { if ( strncmp( signalAspectEditName, signalAspect(signalAspectEditIndex).aspectName,STR_SHORT_SIZE ) != 0 ) { MyFree(signalAspect(signalAspectEditIndex).aspectName); signalAspect(signalAspectEditIndex).aspectName = MyStrdup(signalAspectEditName); } if ( strncmp( signalAspectEditScript, signalAspect(signalAspectEditIndex).aspectScript, STR_LONG_SIZE ) != 0 ) { MyFree(signalAspect(signalAspectEditIndex).aspectScript); signalAspect(signalAspectEditIndex).aspectScript = MyStrdup(signalAspectEditScript); } snprintf(message,sizeof(message),"%s\t%s",signalAspect(signalAspectEditIndex).aspectName,signalAspect(signalAspectEditIndex).aspectScript); wListSetValues( aspectSelL, signalAspectEditIndex, message, NULL, NULL ); } wHide( aspectEditW ); } static void EditAspectDialog ( wIndex_t inx ) { if (inx < 0) { signalAspectEditName[0] = '\0'; signalAspectEditScript[0] = '\0'; } else { strncpy(signalAspectEditName,signalAspect(inx).aspectName,STR_SHORT_SIZE); strncpy(signalAspectEditScript,signalAspect(inx).aspectScript,STR_LONG_SIZE); } signalAspectEditIndex = inx; if ( !aspectEditW ) { ParamRegister( &aspectEditPG ); aspectEditW = ParamCreateDialog (&aspectEditPG, MakeWindowTitle(_("Edit aspect")), _("Ok"), aspectEditOK, wHide, TRUE, NULL,F_BLOCK,NULL); } ParamLoadControls( &aspectEditPG ); wShow( aspectEditW ); } static void AspectEdit( void * action ) { wIndex_t selcnt = wListGetSelectedCount( aspectSelL ); wIndex_t inx, cnt; if ( selcnt != 1) return; cnt = wListGetCount( aspectSelL ); for ( inx=0; inx= cnt ) return; EditAspectDialog(inx); } static void AspectAdd( void * action ) { EditAspectDialog(-1); } static void MoveAspectUp (wIndex_t inx) { wIndex_t cnt = signalAspect_da.cnt; wIndex_t ia; MyFree(signalAspect(inx).aspectName); MyFree(signalAspect(inx).aspectScript); for (ia = inx+1; ia < cnt; ia++) { signalAspect(ia-1).aspectName = signalAspect(ia).aspectName; signalAspect(ia-1).aspectScript = signalAspect(ia).aspectScript; } DYNARR_SET(signalAspect_t,signalAspect_da,cnt-1); } static void AspectDelete( void * action ) { wIndex_t selcnt = wListGetSelectedCount( aspectSelL ); wIndex_t inx, cnt; if ( selcnt <= 0) return; if ( (!NoticeMessage2( 1, _("Are you sure you want to delete the %d aspect(s)"), _("Yes"), _("No"), selcnt ) ) ) return; cnt = wListGetCount( aspectSelL ); for ( inx=0; inxname,STR_SHORT_SIZE); signalEditHeadCount = xx->numHeads; signalEditOrig = xx->orig; signalEditAngle = xx->angle; wListClear( aspectSelL ); DYNARR_RESET( signalAspect_p, signalAspect_da ); for (ia = 0; ia < xx->numAspects; ia++) { snprintf(message,sizeof(message),"%s\t%s",(&(xx->aspectList))[ia].aspectName, (&(xx->aspectList))[ia].aspectScript); wListAddValue( aspectSelL, message, NULL, NULL ); DYNARR_APPEND( signalAspect_p *, signalAspect_da, 10 ); signalAspect(signalAspect_da.cnt-1).aspectName = MyStrdup((&(xx->aspectList))[ia].aspectName); signalAspect(signalAspect_da.cnt-1).aspectScript = MyStrdup((&(xx->aspectList))[ia].aspectScript); } } ParamLoadControls( &signalEditPG ); ParamControlActive( &signalEditPG, I_SIGNALASPECTEDIT, FALSE ); ParamControlActive( &signalEditPG, I_SIGNALASPECTADD, TRUE ); ParamControlActive( &signalEditPG, I_SIGNALASPECTDELETE, FALSE ); wShow( signalEditW ); } static void EditSignal (track_p trk) { signalCreate_P = FALSE; signalEditTrack = trk; EditSignalDialog(); } static void CreateNewSignal (coOrd orig, ANGLE_T angle) { signalCreate_P = TRUE; signalEditOrig = orig; signalEditAngle = angle; EditSignalDialog(); } static coOrd pos0; static ANGLE_T orient; static STATUS_T CmdSignal ( wAction_t action, coOrd pos ) { static BOOL_T create; switch (action) { case C_START: InfoMessage(_("Place base of signal")); create = FALSE; SetAllTrackSelect( FALSE ); return C_CONTINUE; case C_DOWN: SnapPos(&pos); pos0 = pos; create = TRUE; InfoMessage(_("Drag to orient signal")); return C_CONTINUE; case C_MOVE: SnapPos(&pos); orient = FindAngle(pos0,pos); return C_CONTINUE; case C_UP: SnapPos(&pos); orient = FindAngle(pos0,pos); CreateNewSignal(pos0,orient); return C_TERMINATE; case C_REDRAW: if (create) DDrawSignal( &tempD, pos0, orient, 1, GetScaleRatio(GetLayoutCurScale()), wDrawColorBlack ); return C_CONTINUE; case C_CANCEL: create = FALSE; return C_CONTINUE; default: return C_CONTINUE; } } static coOrd sighiliteOrig, sighiliteSize; static POS_T sighiliteBorder; static wDrawColor sighiliteColor = 0; static void DrawSignalTrackHilite( void ) { if (sighiliteColor==0) sighiliteColor = wDrawColorGray(87); DrawRectangle( &tempD, sighiliteOrig, sighiliteSize, sighiliteColor, DRAW_TRANSPARENT ); } static int SignalMgmProc ( int cmd, void * data ) { track_p trk = (track_p) data; signalData_p xx = GetsignalData(trk); /*char msg[STR_SIZE];*/ switch ( cmd ) { case CONTMGM_CAN_EDIT: return TRUE; break; case CONTMGM_DO_EDIT: EditSignal(trk); return TRUE; break; case CONTMGM_CAN_DELETE: return TRUE; break; case CONTMGM_DO_DELETE: DeleteTrack(trk, FALSE); return TRUE; break; case CONTMGM_DO_HILIGHT: if (!xx->IsHilite) { sighiliteBorder = mainD.scale*0.1; if ( sighiliteBorder < trackGauge ) sighiliteBorder = trackGauge; GetBoundingBox( trk, &sighiliteSize, &sighiliteOrig ); sighiliteOrig.x -= sighiliteBorder; sighiliteOrig.y -= sighiliteBorder; sighiliteSize.x -= sighiliteOrig.x-sighiliteBorder; sighiliteSize.y -= sighiliteOrig.y-sighiliteBorder; DrawSignalTrackHilite(); xx->IsHilite = TRUE; } break; case CONTMGM_UN_HILIGHT: if (xx->IsHilite) { sighiliteBorder = mainD.scale*0.1; if ( sighiliteBorder < trackGauge ) sighiliteBorder = trackGauge; GetBoundingBox( trk, &sighiliteSize, &sighiliteOrig ); sighiliteOrig.x -= sighiliteBorder; sighiliteOrig.y -= sighiliteBorder; sighiliteSize.x -= sighiliteOrig.x-sighiliteBorder; sighiliteSize.y -= sighiliteOrig.y-sighiliteBorder; DrawSignalTrackHilite(); xx->IsHilite = FALSE; } break; case CONTMGM_GET_TITLE: sprintf(message,"\t%s\t",xx->name); break; } return FALSE; } #include "bitmaps/signal.xpm" EXPORT void SignalMgmLoad ( void ) { track_p trk; static wIcon_p signalI = NULL; if (signalI == NULL) { signalI = wIconCreatePixMap( signal_xpm[iconSize] ); } TRK_ITERATE(trk) { if (GetTrkType(trk) != T_SIGNAL) continue; ContMgmLoad (signalI, SignalMgmProc, trk ); } } #define ACCL_SIGNAL 0 EXPORT void InitCmdSignal ( wMenu_p menu ) { AddMenuButton( menu, CmdSignal, "cmdSignal", _("Signal"), wIconCreatePixMap( signal_xpm[iconSize] ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_SIGNAL, NULL ); } EXPORT void InitTrkSignal ( void ) { T_SIGNAL = InitObject ( &signalCmds ); log_signal = LogFindIndex ( "signal" ); }