summaryrefslogtreecommitdiff
path: root/app/bin/misc2.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/bin/misc2.c')
-rw-r--r--app/bin/misc2.c255
1 files changed, 212 insertions, 43 deletions
diff --git a/app/bin/misc2.c b/app/bin/misc2.c
index 19226cc..6334bf2 100644
--- a/app/bin/misc2.c
+++ b/app/bin/misc2.c
@@ -20,50 +20,34 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <stdlib.h>
-#include <stdio.h>
-#ifndef WINDOWS
-#include <unistd.h>
-#include <dirent.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#include <math.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include <stdint.h>
-
#include "cjoin.h"
#include "common.h"
#include "compound.h"
#include "custom.h"
#include "draw.h"
#include "fileio.h"
-#include "i18n.h"
#include "layout.h"
-#include "messages.h"
#include "misc.h"
#include "param.h"
#include "track.h"
-#include "utility.h"
+#include "common-ui.h"
EXPORT long units = 0; /**< measurement units: 0 = English, 1 = metric */
EXPORT long checkPtInterval = 10;
-EXPORT long autosaveChkPoints = 2;
+EXPORT long autosaveChkPoints = 0;
EXPORT DIST_T curScaleRatio;
EXPORT char * curScaleName;
EXPORT DIST_T trackGauge;
EXPORT long labelScale = 8;
EXPORT long labelEnable = (LABELENABLE_ENDPT_ELEV|LABELENABLE_CARS);
+/** @prefs [draw] label-when=2 Unknown */
EXPORT long labelWhen = 2;
EXPORT long colorTrack = 0;
EXPORT long colorDraw = 0;
EXPORT long constrainMain = 0;
+EXPORT long dontHideCursor = 0;
EXPORT long hideSelectionWindow = 0;
EXPORT long angleSystem = 0;
EXPORT DIST_T minLength = 0.1;
@@ -173,6 +157,17 @@ typedef struct {
EXPORT typedef scaleInfo_t * scaleInfo_p;
static dynArr_t scaleInfo_da;
#define scaleInfo(N) DYNARR_N( scaleInfo_t, scaleInfo_da, N )
+
+typedef struct {
+ char *in_scales;
+ SCALE_FIT_TYPE_T type;
+ char *match_scales;
+ SCALE_FIT_T result;
+} scaleComp_t;
+EXPORT typedef scaleComp_t * scaleComp_p;
+static dynArr_t scaleCompatible_da;
+#define scaleComp(N) DYNARR_N( scaleComp_t, scaleCompatible_da, N )
+
static tieData_t tieData_demo = {
96.0/160.0,
16.0/160.0,
@@ -180,6 +175,7 @@ static tieData_t tieData_demo = {
//EXPORT SCALEINX_T curScaleInx = -1;
static scaleInfo_p curScale;
+/** @prefs [misc] include same gauge turnouts=1 Unknown */
EXPORT long includeSameGaugeTurnouts = FALSE;
static SCALEINX_T demoScaleInx = -1;
@@ -243,12 +239,16 @@ EXPORT SCALEINX_T GetScaleInx( SCALEDESCINX_T scaleInx, GAUGEINX_T gaugeInx )
}
EXPORT DIST_T GetScaleTrackGauge( SCALEINX_T si )
{
- return scaleInfo(si).gauge;
+ if (si >=0 && si<scaleInfo_da.cnt)
+ return scaleInfo(si).gauge;
+ else return 1.0;
}
EXPORT DIST_T GetScaleRatio( SCALEINX_T si )
{
- return scaleInfo(si).ratio;
+ if (si >=0 && si<scaleInfo_da.cnt)
+ return scaleInfo(si).ratio;
+ else return 1.0;
}
EXPORT char * GetScaleName( SCALEINX_T si )
@@ -286,9 +286,15 @@ EXPORT tieData_p GetScaleTieData( SCALEINX_T si )
if ( !s->tieDataValid ) {
sprintf( message, "tiedata-%s", s->scale );
defLength = (96.0-54.0)/s->ratio+s->gauge;
+
+ /** @prefs [tiedata-<SCALE>] length, width, spacing Sets tie drawing data.
+ * Example for 6"x8"x6' ties spaced 20" in HOn3 (slash separates 4 lines):
+ * [tiedata-HOn3] \ length=0.83 \ width=0.07 \ spacing=0.23
+ */
wPrefGetFloat( message, "length", &s->tieData.length, defLength );
wPrefGetFloat( message, "width", &s->tieData.width, 16.0/s->ratio );
wPrefGetFloat( message, "spacing", &s->tieData.spacing, 2*s->tieData.width );
+ s->tieDataValid = TRUE;
}
return &scaleInfo(si).tieData;
}
@@ -315,7 +321,7 @@ SetScaleGauge(SCALEDESCINX_T desc, GAUGEINX_T gauge)
dynArr_t gauges_da;
gauges_da = (scaleDesc(desc)).gauges_da;
- SetLayoutCurScale(((gaugeInfo_p)gauges_da.ptr)[gauge].scale);
+ SetLayoutCurScale( DYNARR_N( gaugeInfo_t, gauges_da, gauge).scale);
}
static BOOL_T
@@ -376,29 +382,91 @@ EXPORT SCALEINX_T LookupScale( const char * name )
return si;
}
+/*
+ * Evaluate the fit of a part scale1 to a definition in scale2 for a type.
+ *
+ * The rules differ by type of object.
+ *
+ * Tracks need to be the same gauge to be a fit. If they are the same scale they are exact.
+ * If the gauge is the same, but the scale is different they are compatible.
+ * There are well known exceptions where the scale is not the same but we call them exact.
+ *
+ * Structures need to be the same scale to be exact. If they are within 15% they are compatible.
+ *
+ * Cars need to be the same gauge and scale to be exact.
+ * If they are the same gauge, but within 15% of the scale they are compatible.
+ *
+ *\param type (FIT_TURNOUT,FIT_STRUCTURE,FIT_CAR)
+ *\param scale1 the input scale
+ *\param scale2 the scale to check against
+ *
+ *\return FIT_EXACT, FIT_COMPATIBLE, FIT_NONE
+ */
-EXPORT BOOL_T CompatibleScale(
- BOOL_T isTurnout,
+EXPORT SCALE_FIT_T CompatibleScale(
+ SCALE_FIT_TYPE_T type,
SCALEINX_T scale1,
SCALEINX_T scale2 )
{
+ SCALE_FIT_T rc;
if ( scale1 == scale2 )
- return TRUE;
+ return FIT_EXACT;
if ( scale1 == SCALE_DEMO || scale2 == SCALE_DEMO )
- return FALSE;
+ return FIT_NONE;
if ( scale1 == demoScaleInx || scale2 == demoScaleInx )
- return FALSE;
- if ( isTurnout ) {
+ return FIT_NONE;
+ switch(type) {
+ case FIT_TURNOUT:
+ if ( scale1 == SCALE_ANY )
+ return FIT_EXACT;
+ if (scaleInfo(scale1).gauge == scaleInfo(scale2).gauge &&
+ scaleInfo(scale1).scale == scaleInfo(scale2).scale)
+ return FIT_EXACT;
+
+ rc = FindScaleCompatible(FIT_TURNOUT, scaleInfo(scale1).scale, scaleInfo(scale2).scale);
+ if (rc != FIT_NONE) return rc;
+
if ( includeSameGaugeTurnouts &&
- scaleInfo(scale1).gauge == scaleInfo(scale2).gauge )
- return TRUE;
- } else {
+ scaleInfo(scale1).gauge == scaleInfo(scale2).gauge )
+ return FIT_COMPATIBLE;
+ break;
+ case FIT_STRUCTURE:
if ( scale1 == SCALE_ANY )
- return TRUE;
+ return FIT_EXACT;
if ( scaleInfo(scale1).ratio == scaleInfo(scale2).ratio )
- return TRUE;
+ return FIT_EXACT;
+
+ rc = FindScaleCompatible(FIT_STRUCTURE, scaleInfo(scale1).scale, scaleInfo(scale2).scale);
+ if (rc != FIT_NONE) return rc;
+
+ //15% scale match is compatible for structures
+ if (scaleInfo(scale1).ratio/scaleInfo(scale2).ratio>=0.85 &&
+ scaleInfo(scale1).ratio/scaleInfo(scale2).ratio<=1.15)
+ return FIT_COMPATIBLE;
+ break;
+ case FIT_CAR:
+ if ( scale1 == SCALE_ANY )
+ return FIT_EXACT;
+ if (scaleInfo(scale1).gauge == scaleInfo(scale2).gauge &&
+ scaleInfo(scale1).scale == scaleInfo(scale2).scale)
+ return FIT_EXACT;
+
+ rc = FindScaleCompatible(FIT_CAR, scaleInfo(scale1).scale, scaleInfo(scale2).scale);
+ if (rc != FIT_NONE) return rc;
+
+ //Same gauge and 15% scale match is compatible for cars
+ if (scaleInfo(scale1).gauge == scaleInfo(scale2).gauge) {
+ if (scaleInfo(scale1).ratio/scaleInfo(scale2).ratio>=0.85 &&
+ scaleInfo(scale1).ratio/scaleInfo(scale2).ratio<=1.15)
+ return FIT_COMPATIBLE;
+ }
+ break;
+
+ default:;
}
- return FALSE;
+
+ return FIT_NONE;
+
}
/** Split the scale and the gauge description for a given combination. Eg HOn3 will be
@@ -451,7 +519,7 @@ GetScaleGauge( SCALEINX_T scaleInx, SCALEDESCINX_T *scaleDescInx, GAUGEINX_T *ga
static void
SetScale( SCALEINX_T newScaleInx )
{
- if (newScaleInx < 0 && newScaleInx >= scaleInfo_da.cnt) {
+ if (newScaleInx < 0 || newScaleInx >= scaleInfo_da.cnt) {
NoticeMessage( MSG_BAD_SCALE_INDEX, _("Ok"), NULL, (int)newScaleInx );
return;
}
@@ -530,7 +598,7 @@ EXPORT BOOL_T DoSetScaleDesc( void )
DIST_T ratio;
BOOL_T found;
char buf[ 80 ];
- int len;
+ size_t len;
for( scaleInx = 0; scaleInx < scaleInfo_da.cnt; scaleInx++ ) {
ratio = DYNARR_N( scaleInfo_t, scaleInfo_da, scaleInx ).ratio;
@@ -629,13 +697,113 @@ static BOOL_T AddScale(
return TRUE;
}
+static BOOL_T AddScaleFit(
+ char * line) {
+ char scales[STR_SIZE], matches[STR_SIZE], type[20], result[20];
+ BOOL_T rc;
+ scaleComp_p s;
+
+ if ( (rc=sscanf( line, "SCALEFIT %s %s %s %s",
+ type, result, scales, matches )) != 4) {
+ SyntaxError( "SCALEFIT", rc, 4 );
+ return FALSE;
+ }
+ DYNARR_APPEND( scaleComp_t, scaleCompatible_da, 10 );
+ s = &scaleComp(scaleCompatible_da.cnt-1);
+ s->in_scales = MyStrdup(scales);
+ s->match_scales = MyStrdup(matches);
+ if (strcmp(type,"STRUCTURE") == 0) {
+ s->type = FIT_STRUCTURE;
+ } else if (strcmp(type,"TURNOUT")==0) {
+ s->type = FIT_TURNOUT;
+ } else if (strcmp(type,"CAR")==0) {
+ s->type = FIT_CAR;
+ } else {
+ InputError( "Invalid SCALEFIT type %s", TRUE, type );
+ return FALSE;
+ }
+ if (strcmp(result,"COMPATIBLE")==0) {
+ s->result = FIT_COMPATIBLE;
+ } else if (strcmp(result,"EXACT")==0) {
+ s->result = FIT_EXACT;
+ } else {
+ InputError( "Invalid SCALEFIT result %s", TRUE, result );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+EXPORT SCALE_FIT_T FindScaleCompatible(SCALE_FIT_TYPE_T type, char * scale1, char * scale2) {
+
+ char * cp, * cq;
+
+ if (!scale1 || !scale1[0]) return FIT_NONE;
+ if (!scale2 || !scale2[0]) return FIT_NONE;
+
+ for (int i=0; i<scaleCompatible_da.cnt; i++) {
+ scaleComp_p s;
+ s = &scaleComp(i);
+ if (s->type != type) continue;
+ BOOL_T found = FALSE;
+ cp = s->in_scales;
+ //Match input scale
+ while (cp) {
+ //Next instance of needle in haystack
+ cp = strstr(cp,scale2);
+ if (!cp) break;
+ //Check that this is start of csv string
+ if (cp == s->in_scales || cp[-1] == ',') {
+ //Is this end of haystack?
+ if (strlen(cp) == strlen(scale2)) {
+ found = TRUE;
+ break;
+ }
+ //Is it the same until the next ','
+ cq=strstr(cp,",");
+ if (cq && (cq-cp == strlen(scale2))) {
+ found = TRUE;
+ break;
+ }
+ else cp=cq;
+ } else cp=strstr(cp,",");
+ }
+ if (!found) continue;
+ found = FALSE;
+ cp = s->match_scales;
+ //Match output scale
+ while (cp) {
+ //Next instance of needle in haystack
+ cp = strstr(cp,scale1);
+ if (!cp) break;
+ //Check that this is start of csv string
+ if (cp == s->match_scales || cp[-1] == ',') {
+ //Is this end of haystack?
+ if (strlen(cp) == strlen(scale1)) {
+ found = TRUE;
+ break;
+ }
+ //Is it the same until the next ','
+ cq=strstr(cp,",");
+ if (cq && (cq-cp == strlen(scale1))) {
+ found = TRUE;
+ break;
+ }
+ else cp=cq;
+ } else cp=strstr(cp,",");
+ }
+ if (!found) continue;
+ return s->result;
+ }
+ return FIT_NONE;
+}
EXPORT void ScaleLengthIncrement(
SCALEINX_T scale,
DIST_T length )
{
char * cp;
- int len;
+ size_t len;
if (scaleInfo(scale).length == 0.0) {
if (units == UNITS_METRIC)
cp = "999.99m SCALE Flex Track";
@@ -643,7 +811,7 @@ EXPORT void ScaleLengthIncrement(
cp = "999' 11\" SCALE Flex Track";
len = strlen( cp )+1;
if (len > enumerateMaxDescLen)
- enumerateMaxDescLen = len;
+ enumerateMaxDescLen = (int)len;
}
scaleInfo(scale).length += length;
}
@@ -651,7 +819,7 @@ EXPORT void ScaleLengthIncrement(
EXPORT void ScaleLengthEnd( void )
{
wIndex_t si;
- int count;
+ size_t count;
DIST_T length;
char tmp[STR_SIZE];
FLOAT_T flexLen;
@@ -672,7 +840,7 @@ EXPORT void ScaleLengthEnd( void )
if (flexLen > 0.0) {
count = (int)ceil( length / (flexLen/(flexUnit?2.54:1.00)));
}
- EnumerateList( count, flexCost, tmp );
+ EnumerateList( (long)count, flexCost, tmp, NULL );
}
scaleInfo(si).length = 0;
}
@@ -685,7 +853,7 @@ EXPORT void LoadScaleList( wList_p scaleList )
wIndex_t inx;
for (inx=0; inx<scaleDesc_da.cnt-(extraButtons?0:1); inx++) {
scaleDesc(inx).index =
- wListAddValue( scaleList, scaleDesc(inx).scaleDesc, NULL, (void*)(intptr_t)inx );
+ wListAddValue( scaleList, scaleDesc(inx).scaleDesc, NULL, I2VP(inx) );
}
}
@@ -703,7 +871,7 @@ EXPORT void LoadGaugeList( wList_p gaugeList, SCALEDESCINX_T scale )
wListClear( gaugeList ); /* remove old list in case */
for (inx=0; inx<gauges_da_p->cnt; inx++) {
- (g[inx]).index = wListAddValue( gaugeList, (g[inx]).gauge, NULL, (void*)(intptr_t)(g[inx]).scale );
+ (g[inx]).index = wListAddValue( gaugeList, (g[inx]).gauge, NULL, I2VP(g[inx].scale) );
}
}
@@ -723,6 +891,7 @@ static void ScaleChange( long changes )
EXPORT void Misc2Init( void )
{
AddParam( "SCALE ", AddScale );
+ AddParam( "SCALEFIT", AddScaleFit);
wPrefGetInteger( "draw", "label-when", &labelWhen, labelWhen );
RegisterChangeNotification( ScaleChange );
wPrefGetInteger( "misc", "include same gauge turnouts", &includeSameGaugeTurnouts, 1 );