summaryrefslogtreecommitdiff
path: root/app/bin
diff options
context:
space:
mode:
Diffstat (limited to 'app/bin')
-rw-r--r--app/bin/CMakeLists.txt23
-rw-r--r--app/bin/acclkeys.h1
-rw-r--r--app/bin/bitmaps/block.xpm24
-rw-r--r--app/bin/bitmaps/blockdel.xpm52
-rw-r--r--app/bin/bitmaps/blockedit.xpm89
-rw-r--r--app/bin/bitmaps/blocknew.xpm90
-rw-r--r--app/bin/bitmaps/control.xpm24
-rw-r--r--app/bin/bitmaps/sensor.xpm22
-rw-r--r--app/bin/bitmaps/signal.xpm25
-rw-r--r--app/bin/bitmaps/square10.xbm7
-rw-r--r--app/bin/bitmaps/switchm.xpm30
-rw-r--r--app/bin/bitmaps/switchmdel.xpm54
-rw-r--r--app/bin/bitmaps/switchmedit.xpm78
-rw-r--r--app/bin/bitmaps/switchmnew.xpm66
-rw-r--r--app/bin/bitmaps/switchmotormark.xbm6
-rw-r--r--app/bin/cblock.c367
-rw-r--r--app/bin/ccontrol.c597
-rw-r--r--app/bin/cdraw.c156
-rw-r--r--app/bin/cmisc.c1
-rw-r--r--app/bin/cmodify.c8
-rw-r--r--app/bin/cprofile.c13
-rw-r--r--app/bin/csensor.c561
-rw-r--r--app/bin/csignal.c885
-rw-r--r--app/bin/cswitchmotor.c348
-rw-r--r--app/bin/ctext.c69
-rw-r--r--app/bin/cundo.c2
-rw-r--r--app/bin/custom.c5
-rw-r--r--app/bin/custom.h3
-rw-r--r--app/bin/dcontmgm.c312
-rw-r--r--app/bin/dprmfile.c2
-rw-r--r--app/bin/draw.c2
-rw-r--r--app/bin/draw.h1
-rw-r--r--app/bin/dxfformat.c368
-rw-r--r--app/bin/dxfformat.h26
-rw-r--r--app/bin/dxfoutput.c230
-rw-r--r--app/bin/fileio.c193
-rw-r--r--app/bin/helphelper.c146
-rw-r--r--app/bin/misc.c14
-rw-r--r--app/bin/misc.h28
-rw-r--r--app/bin/misc2.c2
-rw-r--r--app/bin/param.c134
-rw-r--r--app/bin/track.c7
-rw-r--r--app/bin/track.h9
-rw-r--r--app/bin/unittest/CMakeLists.txt12
-rw-r--r--app/bin/unittest/dxfformattest.c144
45 files changed, 4224 insertions, 1012 deletions
diff --git a/app/bin/CMakeLists.txt b/app/bin/CMakeLists.txt
index 4bc9fdc..ee0886d 100644
--- a/app/bin/CMakeLists.txt
+++ b/app/bin/CMakeLists.txt
@@ -65,6 +65,7 @@ SET(SOURCES
bllnhlp.c
cblock.c
ccurve.c
+ ccontrol.c
cdraw.c
celev.c
cgroup.c
@@ -81,8 +82,10 @@ SET(SOURCES
cpull.c
cruler.c
cselect.c
+ csensor.c
csnap.c
csplit.c
+ csignal.c
cstraigh.c
cstruct.c
cswitchmotor.c
@@ -98,6 +101,7 @@ SET(SOURCES
dcar.c
dcmpnd.c
dcustmgm.c
+ dcontmgm.c
dease.c
denum.c
dlayer.c
@@ -106,6 +110,8 @@ SET(SOURCES
dprmfile.c
draw.c
drawgeom.c
+ dxfformat.c
+ dxfoutput.c
elev.c
fileio.c
i18n.c
@@ -148,6 +154,7 @@ ADD_EXECUTABLE(xtrkcad WIN32
)
TARGET_LINK_LIBRARIES(xtrkcad xtrkcad-lib)
TARGET_LINK_LIBRARIES(xtrkcad xtrkcad-wlib)
+target_link_libraries(xtrkcad dynstring)
ADD_EXECUTABLE(mkturnout
${LIN_SOURCES}
@@ -169,7 +176,23 @@ ELSE(NOT WIN32)
TARGET_LINK_LIBRARIES(mkturnout xtrkcad-wlib)
ENDIF(NOT WIN32)
+# for testing only, should be IF(APPLE) ...
+IF(APPLE)
+ ADD_EXECUTABLE( helphelper helphelper.c )
+ FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation)
+ FIND_LIBRARY(CARBON_LIBRARY Carbon)
+ TARGET_lINK_LIBRARIES(helphelper ${COREFOUNDATION_LIBRARY} ${CARBON_LIBRARY})
+ INSTALL(
+ TARGETS helphelper
+ RUNTIME DESTINATION ${XTRKCAD_BIN_INSTALL_DIR}
+ )
+ENDIF(APPLE)
+
INSTALL(
TARGETS xtrkcad
RUNTIME DESTINATION ${XTRKCAD_BIN_INSTALL_DIR}
)
+
+if(XTRKCAD_TESTING AND CMOCKA_FOUND)
+ add_subdirectory( unittest )
+endif()
diff --git a/app/bin/acclkeys.h b/app/bin/acclkeys.h
index 2d60510..09bd9bb 100644
--- a/app/bin/acclkeys.h
+++ b/app/bin/acclkeys.h
@@ -113,6 +113,7 @@
#define ACCL_GROUP (WCTL+WSHIFT+'g')
#define ACCL_UNGROUP (WCTL+WSHIFT+'u')
#define ACCL_CUSTMGM (WALT+WCTL+'u')
+#define ACCL_CONTMGM (WALT+WCTL+'c')
#define ACCL_CARINV (WALT+WCTL+'v')
#define ACCL_LAYERS (WALT+WCTL+'y')
#define ACCL_SETCURLAYER (0)
diff --git a/app/bin/bitmaps/block.xpm b/app/bin/bitmaps/block.xpm
new file mode 100644
index 0000000..232d859
--- /dev/null
+++ b/app/bin/bitmaps/block.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char * block_xpm[] = {
+"16 16 5 1",
+" c None",
+". c #2E3436",
+"+ c #00FFFF",
+"@ c #25E100",
+"# c #EF2929",
+".. . ",
+"... ... ",
+" .....++ @@@ ",
+" ...+++ @@@@@ ",
+" ...+++ @@@@@ ",
+"...++++ @@@@@ ",
+" .++++++ @@@ ",
+" ++ +++ ",
+" +++ + ",
+" ### +++ +++ ",
+" ##### +++++..",
+" ##### +++...",
+" ##### +++... ",
+" ### +++.... ",
+" +......",
+" .. ..."};
diff --git a/app/bin/bitmaps/blockdel.xpm b/app/bin/bitmaps/blockdel.xpm
deleted file mode 100644
index 5a02815..0000000
--- a/app/bin/bitmaps/blockdel.xpm
+++ /dev/null
@@ -1,52 +0,0 @@
-/* XPM */
-static char * blockdel_xpm[] = {
-"16 16 33 1",
-" c None",
-". c #FE0C28",
-"+ c #FE102B",
-"@ c #D1FCD1",
-"# c #D2FCD2",
-"$ c #FF0000",
-"% c #FF102A",
-"& c #D3FCD3",
-"* c #FF0101",
-"= c #000000",
-"- c #C38790",
-"; c #FE0D29",
-"> c #B2A8AA",
-", c #ACB5B7",
-"' c #FE122B",
-") c #ACB6B7",
-"! c #DE5162",
-"~ c #B5A0A2",
-"{ c #F51819",
-"] c #FE0A23",
-"^ c #D66070",
-"/ c #FF0202",
-"( c #C67C7E",
-"_ c #B6A0A5",
-": c #FF0303",
-"< c #FFF5F5",
-"[ c #FEEEEE",
-"} c #FFF6F6",
-"| c #FDF1F1",
-"1 c #FE142F",
-"2 c #FFF0F0",
-"3 c #FD102C",
-"4 c #FE0D28",
-" ",
-" .+ @# $$",
-" %.. @& $$ ",
-" .. *$$ ",
-" = .. $$ = ",
-" = -.; $$> = ",
-" = , .'$$ , = ",
-"=== ,)!$$~,, ===",
-"=== ,,{$]^,, ===",
-" = ,/$ +. , = ",
-" = ($ .._ = ",
-" $: < .+ ",
-" $* [}| 1. ",
-" $$ 2} .3 ",
-" *$ 4. ",
-" * . "};
diff --git a/app/bin/bitmaps/blockedit.xpm b/app/bin/bitmaps/blockedit.xpm
deleted file mode 100644
index cfe3e5e..0000000
--- a/app/bin/bitmaps/blockedit.xpm
+++ /dev/null
@@ -1,89 +0,0 @@
-/* XPM */
-static char * blockedit_xpm[] = {
-"16 16 70 1",
-" c None",
-". c #028D05",
-"+ c #008B04",
-"@ c #815C14",
-"# c #C88F21",
-"$ c #6AC66C",
-"% c #94DA95",
-"& c #008C03",
-"* c #008D03",
-"= c #875F15",
-"- c #CA8F22",
-"; c #CB9022",
-"> c #008C04",
-", c #8CD68D",
-"' c #99DD9A",
-") c #008B03",
-"! c #8E6516",
-"~ c #B7821F",
-"{ c #575B0E",
-"] c #976A17",
-"^ c #B07D1D",
-"/ c #6C4C10",
-"( c #000000",
-"_ c #4E610C",
-": c #9F7119",
-"< c #A8781C",
-"[ c #5D420D",
-"} c #00C3FF",
-"| c #63540F",
-"1 c #A7771A",
-"2 c #A0711B",
-"3 c #61450F",
-"4 c #090601",
-"5 c #704E11",
-"6 c #AE7C1C",
-"7 c #956B1B",
-"8 c #5E5526",
-"9 c #34898C",
-"0 c #BA9E58",
-"a c #CE972E",
-"b c #C88E21",
-"c c #8D661B",
-"d c #4C6B4F",
-"e c #00C4FF",
-"f c #01C1FB",
-"g c #7F7C4C",
-"h c #E3D6A3",
-"i c #DDC482",
-"j c #82621C",
-"k c #467461",
-"l c #01C2FC",
-"m c #C9AB64",
-"n c #CBB06D",
-"o c #997C3E",
-"p c #6A4E10",
-"q c #03BEF7",
-"r c #634813",
-"s c #886628",
-"t c #95360D",
-"u c #EE2C2C",
-"v c #F46E6E",
-"w c #EC1C1C",
-"x c #EA0000",
-"y c #F99A9A",
-"z c #F9B3B3",
-"A c #F37E7E",
-"B c #F48080",
-"C c #F16262",
-"D c #EB0000",
-"E c #E90000",
-" .+ @#",
-" $%&* =-;",
-" >,'&) !;;~",
-" *&&&{];;^/",
-" ( &&)_:;;<[ ",
-" ( } |1;;234 ",
-" ( } 56;-78 ( ",
-"((( }}90abcd (((",
-"((( efghijkl (((",
-" ( e mnop } ( ",
-" ( qrst } ( ",
-" uvwx ",
-" yzAx ",
-" BzCx ",
-" DEEx ",
-" "};
diff --git a/app/bin/bitmaps/blocknew.xpm b/app/bin/bitmaps/blocknew.xpm
deleted file mode 100644
index 92685f4..0000000
--- a/app/bin/bitmaps/blocknew.xpm
+++ /dev/null
@@ -1,90 +0,0 @@
-/* XPM */
-static char * blocknew_xpm[] = {
-"16 16 71 1",
-" c None",
-". c #028D05",
-"+ c #3DA505",
-"@ c #C1DB0D",
-"# c #FFF417",
-"$ c #FFF41A",
-"% c #6AC66C",
-"& c #96DC91",
-"* c #7BBE08",
-"= c #C2DB12",
-"- c #FCF427",
-"; c #FFF750",
-"> c #FFF528",
-", c #FFF518",
-"' c #008C04",
-") c #8CD68D",
-"! c #A9E084",
-"~ c #9CCC0B",
-"{ c #E4EA1B",
-"] c #F9F560",
-"^ c #FFFAA5",
-"/ c #FFF864",
-"( c #FFF41E",
-"_ c #008D03",
-": c #40A604",
-"< c #A5CF0D",
-"[ c #EDED1D",
-"} c #FBF676",
-"| c #FFFCD0",
-"1 c #FFFCD1",
-"2 c #FFF878",
-"3 c #FFF51F",
-"4 c #FFF413",
-"5 c #000000",
-"6 c #008C03",
-"7 c #299C05",
-"8 c #95C90A",
-"9 c #E4E919",
-"0 c #FFF756",
-"a c #F4F795",
-"b c #FCFA91",
-"c c #FAF255",
-"d c #D3CA17",
-"e c #00C3FF",
-"f c #FDF215",
-"g c #E6F14D",
-"h c #F4F443",
-"i c #EFE61C",
-"j c #9B940D",
-"k c #A4E36A",
-"l c #D0EC42",
-"m c #C3BA0E",
-"n c #585404",
-"o c #0DC6F2",
-"p c #3ACEC6",
-"q c #49D1B9",
-"r c #7EDB86",
-"s c #4C4901",
-"t c #080700",
-"u c #00C4FF",
-"v c #EE2C2C",
-"w c #F46E6E",
-"x c #EC1C1C",
-"y c #EA0000",
-"z c #F99A9A",
-"A c #F9B3B3",
-"B c #F37E7E",
-"C c #F48080",
-"D c #F16262",
-"E c #EB0000",
-"F c #E90000",
-" .+@#$$# ",
-" %&*=-;;>, ",
-" ')!~{]^^/( ",
-" _:<[}|1234",
-" 5 67890abcd ",
-" 5 e f(ghij ",
-" 5 e 4klmn ",
-"555 eeeeeopqrst5",
-"555 ueeeeeee 555",
-" 5 u e 5 ",
-" 5 e e 5 ",
-" vwxy ",
-" zABy ",
-" CADy ",
-" EFFy ",
-" "};
diff --git a/app/bin/bitmaps/control.xpm b/app/bin/bitmaps/control.xpm
new file mode 100644
index 0000000..bc73a57
--- /dev/null
+++ b/app/bin/bitmaps/control.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char * control_xpm[] = {
+"16 16 5 1",
+" c None",
+". c #05FB0B",
+"+ c #000000",
+"@ c #EF2929",
+"# c #25E100",
+".+ + ",
+"+++ +++",
+" +++ +++ ",
+" +++ +++ +++ ",
+" ++++++++++ ",
+" +++@@@+++ ",
+" ++@@@@@++ ",
+" ++###@@@@++ ",
+" ++####@@@++ ",
+" ++#####@@++ ",
+" ++####@++ ",
+" +++###++++ ",
+" ++++++++++++ ",
+" +++ +++ +++ ",
+"+++ +++",
+"++ ++"};
diff --git a/app/bin/bitmaps/sensor.xpm b/app/bin/bitmaps/sensor.xpm
new file mode 100644
index 0000000..6ed65a3
--- /dev/null
+++ b/app/bin/bitmaps/sensor.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+static char * sensor_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #00FFFF",
+"+ c #FFFFFF",
+" ",
+" ",
+" ..... ",
+" +.......+ ",
+" +++.....+++ ",
+" .+++...+++. ",
+" ...+++.+++... ",
+" ....+++++.... ",
+" .....+++..... ",
+" ....+++++.... ",
+" ...+++.+++... ",
+" .+++...+++. ",
+" +++.....+++ ",
+" +.......+ ",
+" ..... ",
+" "};
diff --git a/app/bin/bitmaps/signal.xpm b/app/bin/bitmaps/signal.xpm
new file mode 100644
index 0000000..521adad
--- /dev/null
+++ b/app/bin/bitmaps/signal.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char * signal_xpm[] = {
+"16 16 6 1",
+" c None",
+". c #000000",
+"+ c #3A000B",
+"@ c #C90328",
+"# c #D9032B",
+"$ c #F30431",
+" .. ",
+" .... ",
+" .+$@+. ",
+" .#$$#. ",
+" .+$@+. ",
+" .... ",
+" .. ",
+" .. ",
+" .. ",
+" .. ",
+" .. ",
+" .. ",
+" .. ",
+" .. ",
+" ............ ",
+" ............ "};
diff --git a/app/bin/bitmaps/square10.xbm b/app/bin/bitmaps/square10.xbm
deleted file mode 100644
index d419974..0000000
--- a/app/bin/bitmaps/square10.xbm
+++ /dev/null
@@ -1,7 +0,0 @@
-#define square10_width 14
-#define square10_height 14
-// static unsigned char square10_bits[] = {
-static char square10_bits[] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff};
diff --git a/app/bin/bitmaps/switchm.xpm b/app/bin/bitmaps/switchm.xpm
new file mode 100644
index 0000000..0230351
--- /dev/null
+++ b/app/bin/bitmaps/switchm.xpm
@@ -0,0 +1,30 @@
+/* XPM */
+static char * switchm_xpm[] = {
+"16 16 11 1",
+" c None",
+". c #EE2828",
+"+ c #EF2828",
+"@ c #EF2929",
+"# c #ED2828",
+"$ c #EE2929",
+"% c #EC2828",
+"& c #E92C2C",
+"* c #D5403F",
+"= c #2E3436",
+"- c #898A83",
+" ",
+" .+@ ",
+" ..@# ",
+" $@$ ",
+" .@@. ",
+" @@. ",
+" .@%. ",
+" &*. ",
+" = ",
+" === ",
+" == == ",
+" == == ",
+" == = ",
+" == == ",
+" === - === ",
+" == == "};
diff --git a/app/bin/bitmaps/switchmdel.xpm b/app/bin/bitmaps/switchmdel.xpm
deleted file mode 100644
index a6dc5ae..0000000
--- a/app/bin/bitmaps/switchmdel.xpm
+++ /dev/null
@@ -1,54 +0,0 @@
-/* XPM */
-static char * switchmdel_xpm[] = {
-"16 16 35 1",
-" c None",
-". c #CC0000",
-"+ c #CB0000",
-"@ c #FF0000",
-"# c #FE0C28",
-"$ c #FE112B",
-"% c #FF0101",
-"& c #F00D21",
-"* c #FE142E",
-"= c #F80E27",
-"- c #D00103",
-"; c #E80306",
-"> c #FF0303",
-", c #FF0611",
-"' c #FF060D",
-") c #FF0202",
-"! c #F51022",
-"~ c #FD132E",
-"{ c #5A5954",
-"] c #E71B32",
-"^ c #FE132D",
-"/ c #595C58",
-"( c #575954",
-"_ c #FE102C",
-": c #61635F",
-"< c #5A5D5A",
-"[ c #545652",
-"} c #5E5F5C",
-"| c #555753",
-"1 c #FE1530",
-"2 c #5B5C58",
-"3 c #626460",
-"4 c #565752",
-"5 c #575854",
-"6 c #575A56",
-" ",
-" .. ",
-" +.+ @ ",
-" #$ ... @@% ",
-" ##&.. %@@ ",
-" *#=-. @@ ",
-" ##;@> ",
-" ,@' ",
-" )@!#~ ",
-" %@ {]#^ ",
-" @@ /( #_ ",
-" @@ :< # ",
-" @@ [ }| 1# ",
-"@@ 2 #$ ",
-" 3 # ",
-" 4 56 | "};
diff --git a/app/bin/bitmaps/switchmedit.xpm b/app/bin/bitmaps/switchmedit.xpm
deleted file mode 100644
index 05168b2..0000000
--- a/app/bin/bitmaps/switchmedit.xpm
+++ /dev/null
@@ -1,78 +0,0 @@
-/* XPM */
-static char * switchmedit_xpm[] = {
-"16 16 59 1",
-" c None",
-". c #6F4D10",
-"+ c #A0711A",
-"@ c #EF2828",
-"# c #EF2929",
-"$ c #704E10",
-"% c #A9781B",
-"& c #CB9022",
-"* c #EE2828",
-"= c #ED2828",
-"- c #B07D1D",
-"; c #EE2929",
-"> c #715010",
-", c #B7821E",
-"' c #CA8F22",
-") c #9B6C1A",
-"! c #71510F",
-"~ c #BC851F",
-"{ c #C98E22",
-"] c #906717",
-"^ c #684A0F",
-"/ c #F02929",
-"( c #755311",
-"_ c #BF8820",
-": c #C68D21",
-"< c #886116",
-"[ c #674A10",
-"} c #D92D24",
-"| c #775511",
-"1 c #C38B21",
-"2 c #C38A21",
-"3 c #7E5B14",
-"4 c #6D4B11",
-"5 c #D03026",
-"6 c #855517",
-"7 c #C68D22",
-"8 c #795613",
-"9 c #815D19",
-"0 c #C88F21",
-"a c #B9831F",
-"b c #725012",
-"c c #896C2E",
-"d c #D3AE5A",
-"e c #CB9124",
-"f c #B4801E",
-"g c #6E4D11",
-"h c #CDB678",
-"i c #E2D29B",
-"j c #BC9746",
-"k c #8A6C2B",
-"l c #D7BC78",
-"m c #AD904F",
-"n c #816632",
-"o c #836C40",
-"p c #65490C",
-"q c #7A5B21",
-"r c #785618",
-"s c #878A85",
-"t c #898B86",
-" .+",
-" @# $%&",
-" *#= $-&&",
-" ;#; >,&')",
-" ## !~&{]^",
-" ##/ (_&:<[ ",
-" *#}|1&234 ",
-" 567&_8 ",
-" 90&ab ",
-" cdefg ",
-" hijg ",
-" klmnog ",
-" pqrg sg ",
-" g ssg ",
-" g tsg ",
-" gggggggg "};
diff --git a/app/bin/bitmaps/switchmnew.xpm b/app/bin/bitmaps/switchmnew.xpm
deleted file mode 100644
index 403a8b7..0000000
--- a/app/bin/bitmaps/switchmnew.xpm
+++ /dev/null
@@ -1,66 +0,0 @@
-/* XPM */
-static char * switchmnew_xpm[] = {
-"16 16 47 1",
-" c None",
-". c #FFF414",
-"+ c #FFF416",
-"@ c #FFF314",
-"# c #EF2828",
-"$ c #EF2929",
-"% c #FFF518",
-"& c #FFF41E",
-"* c #FFF639",
-"= c #FFF52B",
-"- c #FFF41A",
-"; c #FFF512",
-"> c #EE2828",
-", c #ED2828",
-"' c #FFF513",
-") c #FFF521",
-"! c #FFF969",
-"~ c #FFFA92",
-"{ c #FFF97C",
-"] c #FFF63B",
-"^ c #FFF317",
-"/ c #EE2929",
-"( c #FFF417",
-"_ c #FFF63C",
-": c #FFFA95",
-"< c #FFFDE7",
-"[ c #FFFBB3",
-"} c #FFF75C",
-"| c #FFF51B",
-"1 c #FFF531",
-"2 c #FFF980",
-"3 c #FFFBB5",
-"4 c #FFFA98",
-"5 c #FFF64C",
-"6 c #F35820",
-"7 c #FFF63E",
-"8 c #FFF74D",
-"9 c #FFF51F",
-"0 c #FFF515",
-"a c #EC2828",
-"b c #FFF312",
-"c c #FFF319",
-"d c #E92C2C",
-"e c #D5403F",
-"f c #898A83",
-"g c #8B7247",
-"h c #8A8577",
-" .+@ ",
-" #$ %&*=-; ",
-" >$, ')!~{]^ ",
-" /$/ (_:<[}| ",
-" $$ (12345- ",
-" $$6 |7}890 ",
-" >$a bc|-0 ",
-" de ",
-" f ",
-" g ",
-" gg ",
-" ghf ",
-" g fg ",
-" g f g ",
-" g f g ",
-" gggggggg "};
diff --git a/app/bin/bitmaps/switchmotormark.xbm b/app/bin/bitmaps/switchmotormark.xbm
deleted file mode 100644
index 7a476d9..0000000
--- a/app/bin/bitmaps/switchmotormark.xbm
+++ /dev/null
@@ -1,6 +0,0 @@
-#define switchmotormark_width 16
-#define switchmotormark_height 16
-static char switchmotormark_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x3F,
- 0xC8, 0x3F, 0xFC, 0x3F, 0xFC, 0x3F, 0xC8, 0x3F, 0xC8, 0x3F, 0x08, 0x00,
- 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, };
diff --git a/app/bin/cblock.c b/app/bin/cblock.c
index 5b728d0..3c627e9 100644
--- a/app/bin/cblock.c
+++ b/app/bin/cblock.c
@@ -1,6 +1,7 @@
/** \file cblock.c
* Implement blocks: a group of trackwork with a single occ. detector
- * Created by Robert Heller on Thu Mar 12 09:43:02 2009
+ */
+/* Created by Robert Heller on Thu Mar 12 09:43:02 2009
* ------------------------------------------------------------------
* Modification History: $Log: not supported by cvs2svn $
* Modification History: Revision 1.4 2009/09/16 18:32:24 m_fischer
@@ -47,17 +48,14 @@
#include <ctype.h>
#include "track.h"
+#include "trackx.h"
#include "compound.h"
#include "i18n.h"
EXPORT TRKTYP_T T_BLOCK = -1;
-#define BLOCKCMD
-
static int log_block = 0;
-#ifdef BLOCKCMD
-
static void NoDrawLine(drawCmd_p d, coOrd p0, coOrd p1, wDrawWidth width,
wDrawColor color ) {}
static void NoDrawArc(drawCmd_p d, coOrd p, DIST_T r, ANGLE_T angle0,
@@ -99,17 +97,37 @@ static paramData_t blockPLs[] = {
/*1*/ { PD_STRING, blockScript, "script", PDO_NOPREF, (void*)350, N_("Script") }
};
static paramGroup_t blockPG = { "block", 0, blockPLs, sizeof blockPLs/sizeof blockPLs[0] };
-static dynArr_t blockTrk_da;
-#define blockTrk(N) DYNARR_N( track_p , blockTrk_da, N )
static wWin_p blockW;
-#endif
+
+static char blockEditName[STR_SHORT_SIZE];
+static char blockEditScript[STR_LONG_SIZE];
+static char blockEditSegs[STR_LONG_SIZE];
+static track_p blockEditTrack;
+
+static paramData_t blockEditPLs[] = {
+/*0*/ { PD_STRING, blockEditName, "name", PDO_NOPREF, (void*)200, N_("Name") },
+/*1*/ { PD_STRING, blockEditScript, "script", PDO_NOPREF, (void*)350, N_("Script") },
+/*2*/ { PD_STRING, blockEditSegs, "segments", PDO_NOPREF, (void*)350, N_("Segments"), BO_READONLY },
+};
+static paramGroup_t blockEditPG = { "block", 0, blockEditPLs, sizeof blockEditPLs/sizeof blockEditPLs[0] };
+static wWin_p blockEditW;
+
+typedef struct btrackinfo_t {
+ track_p t;
+ TRKINX_T i;
+} btrackinfo_t, *btrackinfo_p;
+
+static dynArr_t blockTrk_da;
+#define blockTrk(N) DYNARR_N( btrackinfo_t , blockTrk_da, N )
+
typedef struct blockData_t {
- char * name;
- char * script;
- wIndex_t numTracks;
- track_p trackList;
+ char * name;
+ char * script;
+ BOOL_T IsHilite;
+ wIndex_t numTracks;
+ btrackinfo_t trackList;
} blockData_t, *blockData_p;
static blockData_p GetblockData ( track_p trk )
@@ -179,9 +197,9 @@ static DIST_T DistanceBlock (track_p t, coOrd * p )
DIST_T closest, current;
int iTrk = 1;
- closest = GetTrkDistance ((&(xx->trackList))[0], *p);
+ closest = GetTrkDistance ((&(xx->trackList))[0].t, *p);
for (; iTrk < xx->numTracks; iTrk++) {
- current = GetTrkDistance ((&(xx->trackList))[iTrk], *p);
+ current = GetTrkDistance ((&(xx->trackList))[iTrk].t, *p);
if (current < closest) closest = current;
}
return closest;
@@ -212,11 +230,12 @@ static void DescribeBlock (track_p trk, char * str, CSIZE_T len )
blockData.script[STR_LONG_SIZE-1] = '\0';
blockData.length = 0;
if (xx->numTracks > 0) {
- blockData.endPt[0] = GetTrkEndPos((&(xx->trackList))[0],0);
+ blockData.endPt[0] = GetTrkEndPos((&(xx->trackList))[0].t,0);
}
for (tcount = 0; tcount < xx->numTracks; tcount++) {
- blockData.length += GetTrkLength((&(xx->trackList))[tcount],0,1);
- lastTrk = (&(xx->trackList))[tcount];
+ if ((&(xx->trackList))[tcount].t == NULL) continue;
+ blockData.length += GetTrkLength((&(xx->trackList))[tcount].t,0,1);
+ lastTrk = (&(xx->trackList))[tcount].t;
}
if (lastTrk != NULL) blockData.endPt[1] = GetTrkEndPos(lastTrk,1);
blockDesc[E0].mode =
@@ -228,7 +247,7 @@ static void DescribeBlock (track_p trk, char * str, CSIZE_T len )
}
-static blockDebug (track_p trk)
+static int blockDebug (track_p trk)
{
wIndex_t iTrack;
blockData_p xx = GetblockData(trk);
@@ -238,10 +257,11 @@ static blockDebug (track_p trk)
LOG( log_block, 1, ("*** blockDebug(): script = \"%s\"\n",xx->script))
LOG( log_block, 1, ("*** blockDebug(): numTracks = %d\n",xx->numTracks))
for (iTrack = 0; iTrack < xx->numTracks; iTrack++) {
- LOG( log_block, 1, ("*** blockDebug(): trackList[%d] = T%d, ",iTrack,GetTrkIndex((&(xx->trackList))[iTrack])))
- LOG( log_block, 1, ("%s\n",GetTrkTypeName((&(xx->trackList))[iTrack])))
+ if ((&(xx->trackList))[iTrack].t == NULL) continue;
+ LOG( log_block, 1, ("*** blockDebug(): trackList[%d] = T%d, ",iTrack,GetTrkIndex((&(xx->trackList))[iTrack].t)))
+ LOG( log_block, 1, ("%s\n",GetTrkTypeName((&(xx->trackList))[iTrack].t)))
}
-
+ return(0);
}
static BOOL_T blockCheckContigiousPath()
@@ -251,14 +271,14 @@ static BOOL_T blockCheckContigiousPath()
track_p trk, trk1;
DIST_T dist;
ANGLE_T angle;
- int pathElemStart = 0;
+ /*int pathElemStart = 0;*/
coOrd endPtOrig = zero;
BOOL_T IsConnectedP;
trkEndPt_p endPtP;
DYNARR_RESET( trkEndPt_t, tempEndPts_da );
for ( inx=0; inx<blockTrk_da.cnt; inx++ ) {
- trk = blockTrk(inx);
+ trk = blockTrk(inx).t;
epCnt = GetTrkEndPtCnt(trk);
IsConnectedP = FALSE;
for ( ep=0; ep<epCnt; ep++ ) {
@@ -297,7 +317,11 @@ static BOOL_T blockCheckContigiousPath()
static void DeleteBlock ( track_p t )
{
- blockData_p xx = GetblockData(t);
+ LOG( log_block, 1, ("*** DeleteBlock(%p)\n",t))
+ blockData_p xx = GetblockData(t);
+ LOG( log_block, 1, ("*** DeleteBlock(): index is %d\n",GetTrkIndex(t)))
+ LOG( log_block, 1, ("*** DeleteBlock(): xx = %p, xx->name = %p, xx->script = %p\n",
+ xx,xx->name,xx->script))
MyFree(xx->name); xx->name = NULL;
MyFree(xx->script); xx->script = NULL;
}
@@ -311,8 +335,9 @@ static BOOL_T WriteBlock ( track_p t, FILE * f )
rc &= fprintf(f, "BLOCK %d \"%s\" \"%s\"\n",
GetTrkIndex(t), xx->name, xx->script)>0;
for (iTrack = 0; iTrack < xx->numTracks && rc; iTrack++) {
+ if ((&(xx->trackList))[iTrack].t == NULL) continue;
rc &= fprintf(f, "\tTRK %d\n",
- GetTrkIndex((&(xx->trackList))[iTrack]))>0;
+ GetTrkIndex((&(xx->trackList))[iTrack].t))>0;
}
rc &= fprintf( f, "\tEND\n" )>0;
return rc;
@@ -334,7 +359,7 @@ static void ReadBlock ( char * line )
if (!GetArgs(line+6,"dqq",&index,&name,&script)) {
return;
}
- DYNARR_RESET( track_p , blockTrk_da );
+ DYNARR_RESET( btrackinfo_p , blockTrk_da );
while ( (cp = GetNextLine()) != NULL ) {
while (isspace((unsigned char)*cp)) cp++;
if ( strncmp( cp, "END", 3 ) == 0 ) {
@@ -345,28 +370,49 @@ static void ReadBlock ( char * line )
}
if ( strncmp( cp, "TRK", 3 ) == 0 ) {
if (!GetArgs(cp+4,"d",&trkindex)) return;
- trk = FindTrack(trkindex);
- DYNARR_APPEND( track_p *, blockTrk_da, 10 );
- blockTrk(blockTrk_da.cnt-1) = trk;
+ /*trk = FindTrack(trkindex);*/
+ DYNARR_APPEND( btrackinfo_p *, blockTrk_da, 10 );
+ blockTrk(blockTrk_da.cnt-1).i = trkindex;
}
}
- blockCheckContigiousPath();
- trk = NewTrack(index, T_BLOCK, tempEndPts_da.cnt, sizeof(blockData_t)+(sizeof(track_p)*(blockTrk_da.cnt-1))+1);
+ /*blockCheckContigiousPath(); save for ResolveBlockTracks */
+ trk = NewTrack(index, T_BLOCK, tempEndPts_da.cnt, sizeof(blockData_t)+(sizeof(btrackinfo_t)*(blockTrk_da.cnt-1))+1);
for ( ep=0; ep<tempEndPts_da.cnt; ep++) {
endPtP = &tempEndPts(ep);
SetTrkEndPoint( trk, ep, endPtP->pos, endPtP->angle );
}
- xx = GetblockData( trk );
- xx->name = name;
- xx->script = script;
+ xx = GetblockData( trk );
+ LOG( log_block, 1, ("*** ReadBlock(): trk = %p (%d), xx = %p\n",trk,GetTrkIndex(trk),xx))
+ LOG( log_block, 1, ("*** ReadBlock(): name = %p, script = %p\n",name,script))
+ xx->name = name;
+ xx->script = script;
+ xx->IsHilite = FALSE;
xx->numTracks = blockTrk_da.cnt;
for (iTrack = 0; iTrack < blockTrk_da.cnt; iTrack++) {
- LOG( log_block, 1, ("*** ReadBlock(): copying track T%d\n",GetTrkIndex(blockTrk(iTrack))))
- (&(xx->trackList))[iTrack] = blockTrk(iTrack);
+ LOG( log_block, 1, ("*** ReadBlock(): copying track T%d\n",GetTrkIndex(blockTrk(iTrack).t)))
+ memcpy((void*)&((&(xx->trackList))[iTrack]),(void*)&(blockTrk(iTrack)),sizeof(btrackinfo_t));
}
blockDebug(trk);
}
+EXPORT void ResolveBlockTrack ( track_p trk )
+{
+ LOG( log_block, 1, ("*** ResolveBlockTrack(%p)\n",trk))
+ blockData_p xx;
+ track_p t_trk;
+ wIndex_t iTrack;
+ if (GetTrkType(trk) != T_BLOCK) return;
+ LOG( log_block, 1, ("*** ResolveBlockTrack(%d)\n",GetTrkIndex(trk)))
+ xx = GetblockData(trk);
+ for (iTrack = 0; iTrack < xx->numTracks; iTrack++) {
+ t_trk = FindTrack((&(xx->trackList))[iTrack].i);
+ if (t_trk == NULL) {
+ NoticeMessage( _("resolveBlockTrack: T%d[%d]: T%d doesn't exist"), _("Continue"), NULL, GetTrkIndex(trk), iTrack, (&(xx->trackList))[iTrack].i );
+ }
+ (&(xx->trackList))[iTrack].t = t_trk;
+ LOG( log_block, 1, ("*** ResolveBlockTrack(): %d (%d): %p\n",iTrack,(&(xx->trackList))[iTrack].i,t_trk))
+ }
+}
static void MoveBlock (track_p trk, coOrd orig ) {}
static void RotateBlock (track_p trk, coOrd orig, ANGLE_T angle ) {}
@@ -407,12 +453,11 @@ static trackCmd_t blockCmds = {
-#ifdef BLOCKCMD
static BOOL_T TrackInBlock (track_p trk, track_p blk) {
wIndex_t iTrack;
blockData_p xx = GetblockData(blk);
for (iTrack = 0; iTrack < xx->numTracks; iTrack++) {
- if (trk == (&(xx->trackList))[iTrack]) return TRUE;
+ if (trk == (&(xx->trackList))[iTrack].t) return TRUE;
}
return FALSE;
}
@@ -435,11 +480,11 @@ static void BlockOk ( void * junk )
trkEndPt_p endPtP;
LOG( log_block, 1, ("*** BlockOk()\n"))
- DYNARR_RESET( track_p *, blockTrk_da );
+ DYNARR_RESET( btrackinfo_p *, blockTrk_da );
ParamUpdate( &blockPG );
if ( blockName[0]==0 ) {
- NoticeMessage( 0, "Block must have a name!", _("Ok"));
+ NoticeMessage( _("Block must have a name!"), _("Ok"), NULL);
return;
}
wDrawDelayUpdate( mainD.d, TRUE );
@@ -450,9 +495,10 @@ static void BlockOk ( void * junk )
while ( TrackIterate( &trk ) ) {
if ( GetTrkSelected( trk ) ) {
if ( IsTrack(trk) ) {
- DYNARR_APPEND( track_p *, blockTrk_da, 10 );
+ DYNARR_APPEND( btrackinfo_p *, blockTrk_da, 10 );
LOG( log_block, 1, ("*** BlockOk(): adding track T%d\n",GetTrkIndex(trk)))
- blockTrk(blockTrk_da.cnt-1) = trk;
+ blockTrk(blockTrk_da.cnt-1).t = trk;
+ blockTrk(blockTrk_da.cnt-1).i = GetTrkIndex(trk);
}
}
}
@@ -474,18 +520,21 @@ static void BlockOk ( void * junk )
UndoStart( _("Create block"), "Create block" );
/* Create a block object */
LOG( log_block, 1, ("*** BlockOk(): %d tracks in block\n",blockTrk_da.cnt))
- trk = NewTrack(0, T_BLOCK, tempEndPts_da.cnt, sizeof(blockData_t)+(sizeof(track_p)*(blockTrk_da.cnt-1))+1);
+ trk = NewTrack(0, T_BLOCK, tempEndPts_da.cnt, sizeof(blockData_t)+(sizeof(btrackinfo_t)*(blockTrk_da.cnt-1))+1);
for ( ep=0; ep<tempEndPts_da.cnt; ep++) {
endPtP = &tempEndPts(ep);
SetTrkEndPoint( trk, ep, endPtP->pos, endPtP->angle );
}
- xx = GetblockData( trk );
+
+ xx = GetblockData( trk );
+ LOG(log_block, 1, ("*** BlockOk(): trk = %p (%d), xx = %p\n", trk, GetTrkIndex(trk), xx))
xx->name = MyStrdup(blockName);
xx->script = MyStrdup(blockScript);
+ xx->IsHilite = FALSE;
xx->numTracks = blockTrk_da.cnt;
for (iTrack = 0; iTrack < blockTrk_da.cnt; iTrack++) {
- LOG( log_block, 1, ("*** BlockOk(): copying track T%d\n",GetTrkIndex(blockTrk(iTrack))))
- (&(xx->trackList))[iTrack] = blockTrk(iTrack);
+ LOG( log_block, 1, ("*** BlockOk(): copying track T%d\n",GetTrkIndex(blockTrk(iTrack).t)))
+ memcpy((void*)&(&(xx->trackList))[iTrack],(void*)&blockTrk(iTrack),sizeof(btrackinfo_t));
}
blockDebug(trk);
UndoEnd();
@@ -534,7 +583,7 @@ static STATUS_T CmdBlockCreate( wAction_t action, coOrd pos )
LOG( log_block, 1, ("*** CmdBlockAction(%08x,{%f,%f})\n",action,pos.x,pos.y))
switch (action & 0xFF) {
case C_START:
- fprintf(stderr,"*** CmdBlockCreate(): C_START\n");
+ LOG( log_block, 1,("*** CmdBlockCreate(): C_START\n"))
NewBlockDialog();
return C_TERMINATE;
default:
@@ -542,6 +591,7 @@ static STATUS_T CmdBlockCreate( wAction_t action, coOrd pos )
}
}
+#if 0
extern BOOL_T inDescribeCmd;
static STATUS_T CmdBlockEdit( wAction_t action, coOrd pos )
@@ -613,14 +663,13 @@ static STATUS_T CmdBlockDelete( wAction_t action, coOrd pos )
}
-
#define BLOCK_CREATE 0
#define BLOCK_EDIT 1
#define BLOCK_DELETE 2
static STATUS_T CmdBlock (wAction_t action, coOrd pos )
{
- fprintf(stderr,"*** CmdBlock(%08x,{%f,%f})\n",action,pos.x,pos.y);
+ LOG( log_block, 1, ("*** CmdBlock(%08x,{%f,%f})\n",action,pos.x,pos.y))
switch ((long)commandContext) {
case BLOCK_CREATE: return CmdBlockCreate(action,pos);
@@ -629,23 +678,225 @@ static STATUS_T CmdBlock (wAction_t action, coOrd pos )
default: return C_TERMINATE;
}
}
+#endif
-#include "bitmaps/blocknew.xpm"
-#include "bitmaps/blockedit.xpm"
-#include "bitmaps/blockdel.xpm"
+EXPORT void CheckDeleteBlock (track_p t)
+{
+ track_p blk;
+ blockData_p xx;
+
+ blk = FindBlock(t);
+ if (blk == NULL) return;
+ xx = GetblockData(blk);
+ NoticeMessage(_("Deleting block %s"),_("Ok"),NULL,xx->name);
+ DeleteTrack(blk,FALSE);
+}
+
+static void BlockEditOk ( void * junk )
+{
+ blockData_p xx;
+ track_p trk;
+
+ LOG( log_block, 1, ("*** BlockEditOk()\n"))
+ ParamUpdate (&blockEditPG );
+ if ( blockEditName[0]==0 ) {
+ NoticeMessage( _("Block must have a name!"), _("Ok"), NULL);
+ return;
+ }
+ wDrawDelayUpdate( mainD.d, TRUE );
+ UndoStart( _("Modify Block"), "Modify Block" );
+ trk = blockEditTrack;
+ xx = GetblockData( trk );
+ xx->name = MyStrdup(blockEditName);
+ xx->script = MyStrdup(blockEditScript);
+ blockDebug(trk);
+ UndoEnd();
+ wHide( blockEditW );
+}
+
+
+static void EditBlock (track_p trk)
+{
+ blockData_p xx = GetblockData(trk);
+ wIndex_t iTrack;
+ BOOL_T needComma = FALSE;
+ char temp[32];
+
+ strncpy(blockEditName,xx->name,STR_SHORT_SIZE);
+ strncpy(blockEditScript,xx->script,STR_LONG_SIZE);
+ blockEditSegs[0] = '\0';
+ for (iTrack = 0; iTrack < xx->numTracks ; iTrack++) {
+ if ((&(xx->trackList))[iTrack].t == NULL) continue;
+ sprintf(temp,"%d",GetTrkIndex((&(xx->trackList))[iTrack].t));
+ if (needComma) strcat(blockEditSegs,", ");
+ strcat(blockEditSegs,temp);
+ needComma = TRUE;
+ }
+ blockEditTrack = trk;
+ if ( !blockEditW ) {
+ ParamRegister( &blockEditPG );
+ blockEditW = ParamCreateDialog (&blockEditPG,
+ MakeWindowTitle(_("Edit block")),
+ _("Ok"), BlockEditOk,
+ wHide, TRUE, NULL, F_BLOCK,
+ NULL );
+ }
+ ParamLoadControls( &blockEditPG );
+ sprintf( message, _("Edit block %d"), GetTrkIndex(trk) );
+ wWinSetTitle( blockEditW, message );
+ wShow (blockEditW);
+}
+
+static coOrd blkhiliteOrig, blkhiliteSize;
+static POS_T blkhiliteBorder;
+static wDrawColor blkhiliteColor = 0;
+static void DrawBlockTrackHilite( void )
+{
+ wPos_t x, y, w, h;
+ if (blkhiliteColor==0)
+ blkhiliteColor = wDrawColorGray(87);
+ w = (wPos_t)((blkhiliteSize.x/mainD.scale)*mainD.dpi+0.5);
+ h = (wPos_t)((blkhiliteSize.y/mainD.scale)*mainD.dpi+0.5);
+ mainD.CoOrd2Pix(&mainD,blkhiliteOrig,&x,&y);
+ wDrawFilledRectangle( mainD.d, x, y, w, h, blkhiliteColor, wDrawOptTemp );
+}
+
+
+static int BlockMgmProc ( int cmd, void * data )
+{
+ track_p trk = (track_p) data;
+ blockData_p xx = GetblockData(trk);
+ wIndex_t iTrack;
+ BOOL_T needComma = FALSE;
+ char temp[32];
+ /*char msg[STR_SIZE];*/
+ coOrd tempOrig, tempSize;
+ BOOL_T first = TRUE;
+
+ switch ( cmd ) {
+ case CONTMGM_CAN_EDIT:
+ return TRUE;
+ break;
+ case CONTMGM_DO_EDIT:
+ EditBlock (trk);
+ /*inDescribeCmd = TRUE;*/
+ /*DescribeTrack (trk, msg, sizeof msg );*/
+ /*InfoMessage( msg );*/
+ 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) {
+ blkhiliteBorder = mainD.scale*0.1;
+ if ( blkhiliteBorder < trackGauge ) blkhiliteBorder = trackGauge;
+ first = TRUE;
+ for (iTrack = 0; iTrack < xx->numTracks ; iTrack++) {
+ if ((&(xx->trackList))[iTrack].t == NULL) continue;
+ GetBoundingBox( (&(xx->trackList))[iTrack].t, &tempSize, &tempOrig );
+ if (first) {
+ blkhiliteOrig = tempOrig;
+ blkhiliteSize = tempSize;
+ first = FALSE;
+ } else {
+ if (tempSize.x > blkhiliteSize.x)
+ blkhiliteSize.x = tempSize.x;
+ if (tempSize.y > blkhiliteSize.y)
+ blkhiliteSize.y = tempSize.y;
+ if (tempOrig.x < blkhiliteOrig.x)
+ blkhiliteOrig.x = tempOrig.x;
+ if (tempOrig.y < blkhiliteOrig.y)
+ blkhiliteOrig.y = tempOrig.y;
+ }
+ }
+ blkhiliteOrig.x -= blkhiliteBorder;
+ blkhiliteOrig.y -= blkhiliteBorder;
+ blkhiliteSize.x -= blkhiliteOrig.x-blkhiliteBorder;
+ blkhiliteSize.y -= blkhiliteOrig.y-blkhiliteBorder;
+ DrawBlockTrackHilite();
+ xx->IsHilite = TRUE;
+ }
+ break;
+ case CONTMGM_UN_HILIGHT:
+ if (xx->IsHilite) {
+ blkhiliteBorder = mainD.scale*0.1;
+ if ( blkhiliteBorder < trackGauge ) blkhiliteBorder = trackGauge;
+ first = TRUE;
+ for (iTrack = 0; iTrack < xx->numTracks ; iTrack++) {
+ if ((&(xx->trackList))[iTrack].t == NULL) continue;
+ GetBoundingBox( (&(xx->trackList))[iTrack].t, &tempSize, &tempOrig );
+ if (first) {
+ blkhiliteOrig = tempOrig;
+ blkhiliteSize = tempSize;
+ first = FALSE;
+ } else {
+ if (tempSize.x > blkhiliteSize.x)
+ blkhiliteSize.x = tempSize.x;
+ if (tempSize.y > blkhiliteSize.y)
+ blkhiliteSize.y = tempSize.y;
+ if (tempOrig.x < blkhiliteOrig.x)
+ blkhiliteOrig.x = tempOrig.x;
+ if (tempOrig.y < blkhiliteOrig.y)
+ blkhiliteOrig.y = tempOrig.y;
+ }
+ }
+ blkhiliteOrig.x -= blkhiliteBorder;
+ blkhiliteOrig.y -= blkhiliteBorder;
+ blkhiliteSize.x -= blkhiliteOrig.x-blkhiliteBorder;
+ blkhiliteSize.y -= blkhiliteOrig.y-blkhiliteBorder;
+ DrawBlockTrackHilite();
+ xx->IsHilite = FALSE;
+ }
+ break;
+ case CONTMGM_GET_TITLE:
+ sprintf( message, "\t%s\t", xx->name);
+ for (iTrack = 0; iTrack < xx->numTracks ; iTrack++) {
+ if ((&(xx->trackList))[iTrack].t == NULL) continue;
+ sprintf(temp,"%d",GetTrkIndex((&(xx->trackList))[iTrack].t));
+ if (needComma) strcat(message,", ");
+ strcat(message,temp);
+ needComma = TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+//#include "bitmaps/blocknew.xpm"
+//#include "bitmaps/blockedit.xpm"
+//#include "bitmaps/blockdel.xpm"
+#include "bitmaps/block.xpm"
+
+EXPORT void BlockMgmLoad( void )
+{
+ track_p trk;
+ static wIcon_p blockI = NULL;
+
+ if ( blockI == NULL)
+ blockI = wIconCreatePixMap( block_xpm );
+
+ TRK_ITERATE(trk) {
+ if (GetTrkType(trk) != T_BLOCK) continue;
+ ContMgmLoad( blockI, BlockMgmProc, (void *)trk );
+ }
+
+}
EXPORT void InitCmdBlock( wMenu_p menu )
{
blockName[0] = '\0';
blockScript[0] = '\0';
- ButtonGroupBegin( _("Block"), "cmdBlockSetCmd", _("Blocks") );
- AddMenuButton( menu, CmdBlock, "cmdBlockCreate", _("Create Block"), wIconCreatePixMap(blocknew_xpm), LEVEL0_50, IC_CANCEL|IC_POPUP, ACCL_BLOCK1, (void*)BLOCK_CREATE );
- AddMenuButton( menu, CmdBlock, "cmdBlockEdit", _("Edit Block"), wIconCreatePixMap(blockedit_xpm), LEVEL0_50, IC_CANCEL|IC_POPUP, ACCL_BLOCK2, (void*)BLOCK_EDIT );
- AddMenuButton( menu, CmdBlock, "cmdBlockDelete", _("Delete Block"), wIconCreatePixMap(blockdel_xpm), LEVEL0_50, IC_CANCEL|IC_POPUP, ACCL_BLOCK3, (void*)BLOCK_DELETE );
- ButtonGroupEnd();
+ AddMenuButton( menu, CmdBlockCreate, "cmdBlockCreate", _("Block"),
+ wIconCreatePixMap( block_xpm ), LEVEL0_50,
+ IC_STICKY|IC_POPUP2, ACCL_BLOCK1, NULL );
ParamRegister( &blockPG );
}
-#endif
EXPORT void InitTrkBlock( void )
diff --git a/app/bin/ccontrol.c b/app/bin/ccontrol.c
new file mode 100644
index 0000000..9428e1a
--- /dev/null
+++ b/app/bin/ccontrol.c
@@ -0,0 +1,597 @@
+/** \file ccontrol.c
+ * Controls
+ */
+
+/* -*- C -*- ****************************************************************
+ *
+ * System :
+ * Module :
+ * Object Name : $RCSfile$
+ * Revision : $Revision$
+ * Date : $Date$
+ * Author : $Author$
+ * Created By : Robert Heller
+ * Created : Sun Mar 5 16:01:37 2017
+ * Last Modified : <170314.1418>
+ *
+ * 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 <ctype.h>
+#include "track.h"
+#include "trackx.h"
+#include "compound.h"
+#include "i18n.h"
+
+EXPORT TRKTYP_T T_CONTROL = -1;
+
+static int log_control = 0;
+
+
+#if 0
+static drawCmd_t controlD = {
+ NULL,
+ &screenDrawFuncs,
+ 0,
+ 1.0,
+ 0.0,
+ {0.0,0.0}, {0.0,0.0},
+ Pix2CoOrd, CoOrd2Pix };
+
+static char controlName[STR_SHORT_SIZE];
+static char controlOnScript[STR_LONG_SIZE];
+static char controlOffScript[STR_LONG_SIZE];
+#endif
+
+typedef struct controlData_t {
+ coOrd orig;
+ BOOL_T IsHilite;
+ char * name;
+ char * onscript;
+ char * offscript;
+} controlData_t, *controlData_p;
+
+static controlData_p GetcontrolData ( track_p trk )
+{
+ return (controlData_p) GetTrkExtraData(trk);
+}
+
+#define RADIUS 6
+#define LINE 8
+
+#define control_SF (3.0)
+
+static void DDrawControl(drawCmd_p d, coOrd orig, DIST_T scaleRatio,
+ wDrawColor color )
+{
+ coOrd p1, p2;
+
+ p1 = orig;
+ DrawFillCircle(d,p1, RADIUS * control_SF / scaleRatio,color);
+ Translate (&p1, orig, 45, RADIUS * control_SF / scaleRatio);
+ Translate (&p2, p1, 45, LINE * control_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, color);
+ Translate (&p1, orig, 45+90, RADIUS * control_SF / scaleRatio);
+ Translate (&p2, p1, 45+90, LINE * control_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, color);
+ Translate (&p1, orig, 45+180, RADIUS * control_SF / scaleRatio);
+ Translate (&p2, p1, 45+180, LINE * control_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, color);
+ Translate (&p1, orig, 45+270, RADIUS * control_SF / scaleRatio);
+ Translate (&p2, p1, 45+270, LINE * control_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, color);
+}
+
+static void DrawControl (track_p t, drawCmd_p d, wDrawColor color )
+{
+ controlData_p xx = GetcontrolData(t);
+ DDrawControl(d,xx->orig,GetScaleRatio(GetTrkScale(t)),color);
+}
+
+static void ControlBoundingBox (coOrd orig, DIST_T scaleRatio, coOrd *hi,
+ coOrd *lo)
+{
+ coOrd p1, p2;
+
+ p1 = orig;
+ Translate (&p1, orig, 0, -(RADIUS+LINE) * control_SF / scaleRatio);
+ Translate (&p2, orig, 0, (RADIUS+LINE) * control_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;
+}
+
+
+static void ComputeControlBoundingBox (track_p t )
+{
+ coOrd lo, hi;
+ controlData_p xx = GetcontrolData(t);
+ ControlBoundingBox(xx->orig, GetScaleRatio(GetTrkScale(t)), &hi, &lo);
+ SetBoundingBox(t, hi, lo);
+}
+
+static DIST_T DistanceControl (track_p t, coOrd * p )
+{
+ controlData_p xx = GetcontrolData(t);
+ return FindDistance(xx->orig, *p);
+}
+
+static struct {
+ char name[STR_SHORT_SIZE];
+ coOrd pos;
+ char onscript[STR_LONG_SIZE];
+ char offscript[STR_LONG_SIZE];
+} controlProperties;
+
+typedef enum { NM, PS, ON, OF } controlDesc_e;
+static descData_t controlDesc[] = {
+ /* NM */ { DESC_STRING, N_("Name"), &controlProperties.name },
+ /* PS */ { DESC_POS, N_("Position"), &controlProperties.pos },
+ /* ON */ { DESC_STRING, N_("On Script"), &controlProperties.onscript },
+ /* OF */ { DESC_STRING, N_("Off Script"),&controlProperties.offscript },
+ { DESC_NULL } };
+
+static void UpdateControlProperties ( track_p trk, int inx, descData_p
+ descUpd, BOOL_T needUndoStart )
+{
+ controlData_p xx = GetcontrolData(trk);
+ const char *thename, *theonscript, *theoffscript;
+ char *newName, *newOnScript, *newOffScript;
+ BOOL_T changed, nChanged, pChanged, onChanged, offChanged;
+
+ switch (inx) {
+ case NM:
+ break;
+ case PS:
+ break;
+ case ON:
+ break;
+ case OF:
+ break;
+ case -1:
+ changed = nChanged = pChanged = onChanged = offChanged = FALSE;
+ thename = wStringGetValue( (wString_p) controlDesc[NM].control0 );
+ if (strcmp(thename,xx->name) != 0) {
+ nChanged = changed = TRUE;
+ newName = MyStrdup(thename);
+ }
+ theonscript = wStringGetValue( (wString_p) controlDesc[ON].control0 );
+ if (strcmp(theonscript,xx->onscript) != 0) {
+ onChanged = changed = TRUE;
+ newOnScript = MyStrdup(theonscript);
+ }
+ theoffscript = wStringGetValue( (wString_p) controlDesc[OF].control0 );
+ if (strcmp(theoffscript,xx->offscript) != 0) {
+ offChanged = changed = TRUE;
+ newOffScript = MyStrdup(theoffscript);
+ }
+ if (controlProperties.pos.x != xx->orig.x ||
+ controlProperties.pos.y != xx->orig.y) {
+ pChanged = changed = TRUE;
+ }
+ if (!changed) break;
+ if (needUndoStart)
+ UndoStart( _("Change Control"), "Change Control" );
+ UndoModify( trk );
+ if (nChanged) {
+ MyFree(xx->name);
+ xx->name = newName;
+ }
+ if (pChanged) {
+ UndrawNewTrack( trk );
+ }
+ if (pChanged) {
+ xx->orig = controlProperties.pos;
+ }
+ if (onChanged) {
+ MyFree(xx->onscript);
+ xx->onscript = newOnScript;
+ }
+ if (offChanged) {
+ MyFree(xx->offscript);
+ xx->offscript = newOffScript;
+ }
+ if (pChanged) {
+ ComputeControlBoundingBox( trk );
+ DrawNewTrack( trk );
+ }
+ break;
+ }
+}
+
+
+
+
+
+static void DescribeControl (track_p trk, char * str, CSIZE_T len )
+{
+ controlData_p xx = GetcontrolData(trk);
+
+ strcpy( str, _(GetTrkTypeName( trk )) );
+ str++;
+ while (*str) {
+ *str = tolower((unsigned char)*str);
+ str++;
+ }
+ sprintf( str, _("(%d [%s]): Layer=%d, at %0.3f,%0.3f"),
+ GetTrkIndex(trk),
+ xx->name,GetTrkLayer(trk)+1, xx->orig.x, xx->orig.y);
+ strncpy(controlProperties.name,xx->name,STR_SHORT_SIZE-1);
+ controlProperties.name[STR_SHORT_SIZE-1] = '\0';
+ strncpy(controlProperties.onscript,xx->onscript,STR_LONG_SIZE-1);
+ controlProperties.onscript[STR_LONG_SIZE-1] = '\0';
+ strncpy(controlProperties.offscript,xx->offscript,STR_LONG_SIZE-1);
+ controlProperties.offscript[STR_LONG_SIZE-1] = '\0';
+ controlProperties.pos = xx->orig;
+ controlDesc[NM].mode =
+ controlDesc[ON].mode =
+ controlDesc[OF].mode = DESC_NOREDRAW;
+ DoDescribe( _("Control"), trk, controlDesc, UpdateControlProperties );
+
+}
+
+static void DeleteControl ( track_p trk )
+{
+ controlData_p xx = GetcontrolData(trk);
+ MyFree(xx->name); xx->name = NULL;
+ MyFree(xx->onscript); xx->onscript = NULL;
+ MyFree(xx->offscript); xx->offscript = NULL;
+}
+
+static BOOL_T WriteControl ( track_p t, FILE * f )
+{
+ BOOL_T rc = TRUE;
+ controlData_p xx = GetcontrolData(t);
+ rc &= fprintf(f, "CONTROL %d %d %s %d %0.6f %0.6f \"%s\" \"%s\" \"%s\"\n",
+ GetTrkIndex(t), GetTrkLayer(t), GetTrkScaleName(t),
+ GetTrkVisible(t), xx->orig.x, xx->orig.y, xx->name,
+ xx->onscript, xx->offscript)>0;
+ return rc;
+}
+
+static void ReadControl ( char * line )
+{
+ wIndex_t index;
+ /*TRKINX_T trkindex;*/
+ track_p trk;
+ /*char * cp = NULL;*/
+ char *name;
+ char *onscript, *offscript;
+ coOrd orig;
+ BOOL_T visible;
+ char scale[10];
+ wIndex_t layer;
+ controlData_p xx;
+ if (!GetArgs(line+7,"dLsdpqqq",&index,&layer,scale, &visible, &orig,&name,&onscript,&offscript)) {
+ return;
+ }
+ trk = NewTrack(index, T_CONTROL, 0, sizeof(controlData_t));
+ SetTrkVisible(trk, visible);
+ SetTrkScale(trk, LookupScale( scale ));
+ SetTrkLayer(trk, layer);
+ xx = GetcontrolData ( trk );
+ xx->name = name;
+ xx->orig = orig;
+ xx->onscript = onscript;
+ xx->offscript = offscript;
+ ComputeControlBoundingBox(trk);
+}
+
+static void MoveControl (track_p trk, coOrd orig )
+{
+ controlData_p xx = GetcontrolData ( trk );
+ xx->orig.x += orig.x;
+ xx->orig.y += orig.y;
+ ComputeControlBoundingBox(trk);
+}
+
+static void RotateControl (track_p trk, coOrd orig, ANGLE_T angle )
+{
+}
+
+static void RescaleControl (track_p trk, FLOAT_T ratio )
+{
+}
+
+static void FlipControl (track_p trk, coOrd orig, ANGLE_T angle )
+{
+ controlData_p xx = GetcontrolData ( trk );
+ FlipPoint(&(xx->orig), orig, angle);
+ ComputeControlBoundingBox(trk);
+}
+
+static trackCmd_t controlCmds = {
+ "CONTROL",
+ DrawControl,
+ DistanceControl,
+ DescribeControl,
+ DeleteControl,
+ WriteControl,
+ ReadControl,
+ MoveControl,
+ RotateControl,
+ RescaleControl,
+ 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 */
+ FlipControl, /* flip */
+ NULL, /* drawPositionIndicator */
+ NULL, /* advancePositionIndicator */
+ NULL, /* checkTraverse */
+ NULL, /* makeParallel */
+ NULL /* drawDesc */
+};
+
+static coOrd controlEditOrig;
+static track_p controlEditTrack;
+static char controlEditName[STR_SHORT_SIZE];
+static char controlEditOnScript[STR_LONG_SIZE];
+static char controlEditOffScript[STR_LONG_SIZE];
+
+static paramFloatRange_t r_1000_1000 = { -1000.0, 1000.0, 80 };
+static paramData_t controlEditPLs[] = {
+#define I_CONTROLNAME (0)
+ /*0*/ { PD_STRING, controlEditName, "name", PDO_NOPREF, (void*)200, N_("Name") },
+#define I_ORIGX (1)
+ /*1*/ { PD_FLOAT, &controlEditOrig.x, "origx", PDO_DIM, &r_1000_1000, N_("Orgin X") },
+#define I_ORIGY (2)
+ /*2*/ { PD_FLOAT, &controlEditOrig.y, "origy", PDO_DIM, &r_1000_1000, N_("Origin Y") },
+#define I_CONTROLONSCRIPT (3)
+ /*3*/ { PD_STRING, controlEditOnScript, "script", PDO_NOPREF, (void*)350, N_("On Script") },
+#define I_CONTROLOFFSCRIPT (4)
+ /*4*/ { PD_STRING, controlEditOffScript, "script", PDO_NOPREF, (void*)350, N_("Off Script") },
+};
+
+static paramGroup_t controlEditPG = { "controlEdit", 0, controlEditPLs, sizeof controlEditPLs/sizeof controlEditPLs[0] };
+static wWin_p controlEditW;
+
+static void ControlEditOk ( void * junk )
+{
+ track_p trk;
+ controlData_p xx;
+
+ if (controlEditTrack == NULL) {
+ UndoStart( _("Create Control"), "Create Control");
+ trk = NewTrack(0, T_CONTROL, 0, sizeof(controlData_t));
+ } else {
+ UndoStart( _("Modify Control"), "Modify Control");
+ trk = controlEditTrack;
+ }
+ xx = GetcontrolData(trk);
+ xx->orig = controlEditOrig;
+ if ( xx->name == NULL || strncmp (xx->name, controlEditName, STR_SHORT_SIZE) != 0) {
+ MyFree(xx->name);
+ xx->name = MyStrdup(controlEditName);
+ }
+ if ( xx->onscript == NULL || strncmp (xx->onscript, controlEditOnScript, STR_LONG_SIZE) != 0) {
+ MyFree(xx->onscript);
+ xx->onscript = MyStrdup(controlEditOnScript);
+ }
+ if ( xx->offscript == NULL || strncmp (xx->offscript, controlEditOffScript, STR_LONG_SIZE) != 0) {
+ MyFree(xx->offscript);
+ xx->offscript = MyStrdup(controlEditOffScript);
+ }
+ UndoEnd();
+ ComputeControlBoundingBox(trk);
+ DoRedraw();
+ wHide( controlEditW );
+}
+
+#if 0
+static void ControlEditCancel ( wWin_p junk )
+{
+ wHide( controlEditW );
+}
+#endif
+
+static void EditControlDialog()
+{
+ controlData_p xx;
+
+ if ( !controlEditW ) {
+ ParamRegister( &controlEditPG );
+ controlEditW = ParamCreateDialog (&controlEditPG,
+ MakeWindowTitle(_("Edit control")),
+ _("Ok"), ControlEditOk,
+ wHide, TRUE, NULL,
+ F_BLOCK,
+ NULL );
+ }
+ if (controlEditTrack == NULL) {
+ controlEditName[0] = '\0';
+ controlEditOnScript[0] = '\0';
+ controlEditOffScript[0] = '\0';
+ } else {
+ xx = GetcontrolData ( controlEditTrack );
+ strncpy(controlEditName,xx->name,STR_SHORT_SIZE);
+ strncpy(controlEditOnScript,xx->onscript,STR_LONG_SIZE);
+ strncpy(controlEditOffScript,xx->offscript,STR_LONG_SIZE);
+ controlEditOrig = xx->orig;
+ }
+ ParamLoadControls( &controlEditPG );
+ wShow( controlEditW );
+}
+
+static void EditControl (track_p trk)
+{
+ controlEditTrack = trk;
+ EditControlDialog();
+}
+
+static void CreateNewControl (coOrd orig)
+{
+ controlEditOrig = orig;
+ controlEditTrack = NULL;
+ EditControlDialog();
+}
+
+static STATUS_T CmdControl ( wAction_t action, coOrd pos )
+{
+
+
+ switch (action) {
+ case C_START:
+ InfoMessage(_("Place control"));
+ return C_CONTINUE;
+ case C_DOWN:
+ SnapPos(&pos);
+ DDrawControl( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ case C_MOVE:
+ SnapPos(&pos);
+ DDrawControl( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ case C_UP:
+ SnapPos(&pos);
+ DDrawControl( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ CreateNewControl(pos);
+ return C_TERMINATE;
+ case C_REDRAW:
+ case C_CANCEL:
+ DDrawControl( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ default:
+ return C_CONTINUE;
+ }
+}
+
+static coOrd ctlhiliteOrig, ctlhiliteSize;
+static POS_T ctlhiliteBorder;
+static wDrawColor ctlhiliteColor = 0;
+static void DrawControlTrackHilite( void )
+{
+ wPos_t x, y, w, h;
+ if (ctlhiliteColor==0)
+ ctlhiliteColor = wDrawColorGray(87);
+ w = (wPos_t)((ctlhiliteSize.x/mainD.scale)*mainD.dpi+0.5);
+ h = (wPos_t)((ctlhiliteSize.y/mainD.scale)*mainD.dpi+0.5);
+ mainD.CoOrd2Pix(&mainD,ctlhiliteOrig,&x,&y);
+ wDrawFilledRectangle( mainD.d, x, y, w, h, ctlhiliteColor, wDrawOptTemp );
+}
+
+static int ControlMgmProc ( int cmd, void * data )
+{
+ track_p trk = (track_p) data;
+ controlData_p xx = GetcontrolData(trk);
+ /*char msg[STR_SIZE];*/
+
+ switch ( cmd ) {
+ case CONTMGM_CAN_EDIT:
+ return TRUE;
+ break;
+ case CONTMGM_DO_EDIT:
+ EditControl(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) {
+ ctlhiliteBorder = mainD.scale*0.1;
+ if ( ctlhiliteBorder < trackGauge ) ctlhiliteBorder = trackGauge;
+ GetBoundingBox( trk, &ctlhiliteSize, &ctlhiliteOrig );
+ ctlhiliteOrig.x -= ctlhiliteBorder;
+ ctlhiliteOrig.y -= ctlhiliteBorder;
+ ctlhiliteSize.x -= ctlhiliteOrig.x-ctlhiliteBorder;
+ ctlhiliteSize.y -= ctlhiliteOrig.y-ctlhiliteBorder;
+ DrawControlTrackHilite();
+ xx->IsHilite = TRUE;
+ }
+ break;
+ case CONTMGM_UN_HILIGHT:
+ if (xx->IsHilite) {
+ ctlhiliteBorder = mainD.scale*0.1;
+ if ( ctlhiliteBorder < trackGauge ) ctlhiliteBorder = trackGauge;
+ GetBoundingBox( trk, &ctlhiliteSize, &ctlhiliteOrig );
+ ctlhiliteOrig.x -= ctlhiliteBorder;
+ ctlhiliteOrig.y -= ctlhiliteBorder;
+ ctlhiliteSize.x -= ctlhiliteOrig.x-ctlhiliteBorder;
+ ctlhiliteSize.y -= ctlhiliteOrig.y-ctlhiliteBorder;
+ DrawControlTrackHilite();
+ xx->IsHilite = FALSE;
+ }
+ break;
+ case CONTMGM_GET_TITLE:
+ sprintf(message,"\t%s\t",xx->name);
+ break;
+ }
+ return FALSE;
+}
+
+#include "bitmaps/control.xpm"
+
+EXPORT void ControlMgmLoad ( void )
+{
+ track_p trk;
+ static wIcon_p controlI = NULL;
+
+ if (controlI == NULL) {
+ controlI = wIconCreatePixMap( control_xpm );
+ }
+
+ TRK_ITERATE(trk) {
+ if (GetTrkType(trk) != T_CONTROL) continue;
+ ContMgmLoad (controlI, ControlMgmProc, (void *) trk );
+ }
+}
+
+#define ACCL_CONTROL 0
+
+EXPORT void InitCmdControl ( wMenu_p menu )
+{
+ AddMenuButton( menu, CmdControl, "cmdControl", _("Control"),
+ wIconCreatePixMap( control_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_CONTROL, NULL );
+}
+
+EXPORT void InitTrkControl ( void )
+{
+ T_CONTROL = InitObject ( &controlCmds );
+ log_control = LogFindIndex ( "control" );
+}
diff --git a/app/bin/cdraw.c b/app/bin/cdraw.c
index 59e45b8..efdb51a 100644
--- a/app/bin/cdraw.c
+++ b/app/bin/cdraw.c
@@ -2,23 +2,23 @@
* Drawing of geometric elements
*/
-/* XTrkCad - Model Railroad CAD
- * Copyright (C) 2005 Dave Bullis
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
+ /* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
#include "track.h"
#include "ccurve.h"
@@ -35,31 +35,49 @@ static long fontSizeList[] = {
200, 250, 300, 350, 400, 450, 500 };
EXPORT void LoadFontSizeList(
- wList_p list,
- long curFontSize )
+ wList_p list,
+ long curFontSize)
{
- wIndex_t curInx=0, inx1;
+ wIndex_t curInx = 0, inx1;
int inx;
- wListClear( list );
- for ( inx=0; inx<sizeof fontSizeList/sizeof fontSizeList[0]; inx++ ) {
- if ( ( inx==0 || curFontSize > fontSizeList[inx-1] ) &&
- ( curFontSize < fontSizeList[inx] ) ) {
- sprintf( message, "%ld", curFontSize );
- curInx = wListAddValue( list, message, NULL, (void*)curFontSize );
+ wListClear(list);
+ for (inx = 0; inx < sizeof fontSizeList / sizeof fontSizeList[0]; inx++)
+ {
+ if ((inx == 0 || curFontSize > fontSizeList[inx - 1]) &&
+ (curFontSize < fontSizeList[inx]))
+ {
+ sprintf(message, "%ld", curFontSize);
+ curInx = wListAddValue(list, message, NULL, (void*)curFontSize);
}
- sprintf( message, "%ld", fontSizeList[inx] );
- inx1 = wListAddValue( list, message, NULL, (void*)fontSizeList[inx] );
- if ( curFontSize == fontSizeList[inx] )
+ sprintf(message, "%ld", fontSizeList[inx]);
+ inx1 = wListAddValue(list, message, NULL, (void*)fontSizeList[inx]);
+ if (curFontSize == fontSizeList[inx])
curInx = inx1;
}
- if ( curFontSize > fontSizeList[(sizeof fontSizeList/sizeof fontSizeList[0])-1] ) {
- sprintf( message, "%ld", curFontSize );
- curInx = wListAddValue( list, message, NULL, (void*)curFontSize );
+ if (curFontSize > fontSizeList[(sizeof fontSizeList / sizeof fontSizeList[0]) - 1])
+ {
+ sprintf(message, "%ld", curFontSize);
+ curInx = wListAddValue(list, message, NULL, (void*)curFontSize);
}
- wListSetIndex( list, curInx );
+ wListSetIndex(list, curInx);
wFlush();
}
+long GetFontSize(wIndex_t inx)
+{
+ return(fontSizeList[inx]);
+}
+
+long GetFontSizeIndex(long size)
+{
+ int i;
+ for (i = 0; i < sizeof fontSizeList / sizeof fontSizeList[0]; i++)
+ {
+ if (fontSizeList[i] == size)
+ return(i);
+ }
+ return(-1);
+}
EXPORT void UpdateFontSizeList(
long * fontSizeR,
@@ -232,7 +250,8 @@ static void UpdateDraw( track_p trk, int inx, descData_p descUpd, BOOL_T final )
return;
segPtr = &xx->segs[drawSegInx];
MainRedraw();
- //UndrawNewTrack( trk );
+ MapRedraw();
+ UndrawNewTrack( trk );
switch ( inx ) {
case LW:
segPtr->width = drawData.lineWidth/mainD.dpi;
@@ -371,6 +390,7 @@ static void UpdateDraw( track_p trk, int inx, descData_p descUpd, BOOL_T final )
}
ComputeDrawBoundingBox( trk );
DrawNewTrack( trk );
+ DoCurCommand( C_REDRAW, zero );
}
static void DescribeDraw( track_p trk, char * str, CSIZE_T len )
@@ -391,6 +411,7 @@ static void DescribeDraw( track_p trk, char * str, CSIZE_T len )
drawDesc[inx].control0 = NULL;
}
drawData.color = segPtr->color;
+ drawData.layer = GetTrkLayer(trk);
drawDesc[CO].mode = 0;
drawData.lineWidth = (long)floor(segPtr->width*mainD.dpi+0.5);
drawDesc[LW].mode = 0;
@@ -759,43 +780,10 @@ static drawContext_t drawCmdContext = {
static void DrawRedraw( void )
{
MainRedraw();
+ MapRedraw();
}
-#ifdef LATER
-static void DrawOk( void * context )
-{
- track_p t;
- struct extraData * xx;
- trkSeg_p sp;
- wIndex_t cnt;
-
- for ( cnt=0,sp=&DrawLineSegs(0); sp < &DrawLineSegs(drawCmdContext.Segs_da.cnt); sp++ )
- if (sp->type != ' ')
- cnt++;
- if (cnt == 0)
- return;
- UndoStart( _("Create Lines"), "newDraw" );
- for ( sp=&DrawLineSegs(0); sp < &DrawLineSegs(drawCmdContext.Segs_da.cnt); sp++ ) {
- if (sp->type != ' ') {
- t = NewTrack( 0, T_DRAW, 0, sizeof *xx + sizeof *(trkSeg_p)0 );
- xx = GetTrkExtraData( t );
- xx->orig = zero;
- xx->angle = 0.0;
- xx->segCnt = 1;
- memcpy( xx->segs, sp, sizeof *(trkSeg_p)0 );
- ComputeDrawBoundingBox( t );
- DrawNewTrack(t);
- }
- }
- UndoEnd();
- DYNARR_RESET( trkSeg_t, drawCmdContext.Segs_da );
- Reset();
-}
-#endif
-
-
-
static wIndex_t benchChoice;
static wIndex_t benchOrient;
static wIndex_t dimArrowSize;
@@ -914,10 +902,7 @@ static STATUS_T CmdDraw( wAction_t action, coOrd pos )
labels[2] = N_("Color");
if ( wListGetCount( (wList_p)drawBenchChoicePD.control ) == 0 )
BenchLoadLists( (wList_p)drawBenchChoicePD.control, (wList_p)drawBenchOrientPD.control );
-#ifdef LATER
- if ( benchInx >= 0 && benchInx < wListGetCount( (wList_p)drawBenchChoicePD.control ) )
- wListSetIndex( (wList_p)drawBenchChoicePD.control, benchInx );
-#endif
+
ParamLoadControls( &drawPG );
BenchUpdateOrientationList( (long)wListGetItemContext( (wList_p)drawBenchChoicePD.control, benchChoice ), (wList_p)drawBenchOrientPD.control );
wListSetIndex( (wList_p)drawBenchOrientPD.control, benchOrient );
@@ -959,9 +944,7 @@ static STATUS_T CmdDraw( wAction_t action, coOrd pos )
if ( drawCmdContext.Op == OP_BENCH ) {
drawCmdContext.benchOption = GetBenchData( (long)wListGetItemContext((wList_p)drawBenchChoicePD.control, benchChoice ), benchOrient );
drawCmdContext.Color = benchColor;
-#ifdef LATER
- benchInx = wListGetIndex( (wList_p)drawBenchChoicePD.control );
-#endif
+
} else if ( drawCmdContext.Op == OP_DIMLINE ) {
drawCmdContext.benchOption = dimArrowSize;
} else {
@@ -1074,29 +1057,6 @@ static drawStuff_t drawStuff[4] = {
{ "cmdDrawShapeSetCmd", N_("Shapes"), N_("Draw Shapes"), 4, dshapeCmds} };
-#ifdef LATER
-static void SetDrawMode( char * modeName )
-{
- wButton_p bb;
- int inx1, inx2;
- drawData_t * dp;
-
- for ( inx1=0; inx1<4; inx1++ ) {
- for ( inx2=0; inx2<drawStuff[inx1].cnt; inx2++ ) {
- dp = &drawStuff[inx1].data[inx2];
- if (strncmp( modeName, dp->modeS, strlen(dp->modeS) ) == 0 ) {
- bb = GetCommandButton(drawStuff[inx1].cmdInx);
- wButtonSetLabel( bb, (char*)(dp->icon) );
- wControlSetHelp( (wControl_p)bb, dp->help );
- drawStuff[inx1].curr = inx2;
- DoCommandB( (void*)(drawStuff[inx1].cmdInx) );
- return;
- }
- }
- }
-}
-#endif
-
static void ChangeDraw( long changes )
{
diff --git a/app/bin/cmisc.c b/app/bin/cmisc.c
index bb6e700..1e2ea39 100644
--- a/app/bin/cmisc.c
+++ b/app/bin/cmisc.c
@@ -153,6 +153,7 @@ static void DescribeUpdate(
UndoStart( _("Change Track"), "Change Track" );
descUndoStarted = TRUE;
}
+ if (!descTrk) return; // In case timer pops after OK
UndoModify( descTrk );
descUpdateFunc( descTrk, ddp-descData, descData, FALSE );
if ( descTrk ) {
diff --git a/app/bin/cmodify.c b/app/bin/cmodify.c
index 89fd548..6828ff9 100644
--- a/app/bin/cmodify.c
+++ b/app/bin/cmodify.c
@@ -138,6 +138,7 @@ static STATUS_T CmdModify(
}
DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack );
MainRedraw();
+ MapRedraw();
return rc;
case C_MOVE:
@@ -155,6 +156,7 @@ static STATUS_T CmdModify(
}
DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack );
MainRedraw();
+ MapRedraw();
return rc;
@@ -173,7 +175,7 @@ static STATUS_T CmdModify(
//changeTrackMode = FALSE;
Dex.Trk = NULL;
MainRedraw();
-
+ MapRedraw();
return rc;
case C_RDOWN:
@@ -209,6 +211,7 @@ LOG( log_modify, 1, ("extend endPt[%d] = [%0.3f %0.3f] A%0.3f\n",
}
Dex.first = TRUE;
MainRedraw();
+ MapRedraw();
#ifdef LATER
return C_CONTINUE;
#endif
@@ -327,6 +330,7 @@ LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) )
}
DrawSegs( &tempD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, trackGauge, wDrawColorBlack );
MainRedraw();
+ MapRedraw();
return C_CONTINUE;
case C_RUP:
@@ -348,6 +352,7 @@ LOG( log_modify, 2, ("A=%0.3f X=%0.3f\n", a0, Dex.jointD.x ) )
UndoEnd();
DrawNewTrack(Dex.Trk );
MainRedraw();
+ MapRedraw();
return C_TERMINATE;
}
trk = NewStraightTrack( Dex.pos01, Dex.curveData.pos1 );
@@ -373,6 +378,7 @@ LOG( log_modify, 1, ("A0 = %0.3f, A1 = %0.3f\n",
DrawNewTrack( Dex.Trk );
Dex.Trk = NULL;
MainRedraw();
+ MapRedraw();
return C_TERMINATE;
case C_REDRAW:
diff --git a/app/bin/cprofile.c b/app/bin/cprofile.c
index 99a3a6d..d8bbc24 100644
--- a/app/bin/cprofile.c
+++ b/app/bin/cprofile.c
@@ -716,6 +716,7 @@ static void DoProfileDone( void * junk )
wHide( profileW );
ClrAllTrkBits( TB_PROFILEPATH );
MainRedraw();
+ MapRedraw();
#endif
Reset();
}
@@ -725,8 +726,10 @@ static void DoProfileClear( void * junk )
{
profElem_da.cnt = 0;
station_da.cnt = 0;
- if (ClrAllTrkBits( TB_PROFILEPATH ))
+ if (ClrAllTrkBits( TB_PROFILEPATH )) {
MainRedraw();
+ MapRedraw();
+ }
pathStartTrk = pathEndTrk = NULL;
RedrawProfileW();
}
@@ -1277,8 +1280,10 @@ static STATUS_T CmdProfile( wAction_t action, coOrd pos )
profElem_da.cnt = 0;
station_da.cnt = 0;
RedrawProfileW();
- if ( ClrAllTrkBits( TB_PROFILEPATH ) )
+ if ( ClrAllTrkBits( TB_PROFILEPATH ) ) {
MainRedraw();
+ MapRedraw();
+ }
pathStartTrk = NULL;
SetAllTrackSelect( FALSE );
profileUndo = FALSE;
@@ -1333,8 +1338,10 @@ static STATUS_T CmdProfile( wAction_t action, coOrd pos )
case C_CANCEL:
wHide(profileW);
HilightProfileElevations( FALSE );
- if (ClrAllTrkBits(TB_PROFILEPATH))
+ if (ClrAllTrkBits(TB_PROFILEPATH)) {
MainRedraw();
+ MapRedraw();
+ }
return C_TERMINATE;
case C_REDRAW:
if ( wWinIsVisible(profileW) ) {
diff --git a/app/bin/csensor.c b/app/bin/csensor.c
new file mode 100644
index 0000000..e962089
--- /dev/null
+++ b/app/bin/csensor.c
@@ -0,0 +1,561 @@
+/** \file csensor.c
+ * Sensors
+ */
+
+/* -*- C -*- ****************************************************************
+ *
+ * System :
+ * Module :
+ * Object Name : $RCSfile$
+ * Revision : $Revision$
+ * Date : $Date$
+ * Author : $Author$
+ * Created By : Robert Heller
+ * Created : Sun Mar 5 16:01:37 2017
+ * Last Modified : <170314.1407>
+ *
+ * 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 <ctype.h>
+#include "track.h"
+#include "trackx.h"
+#include "compound.h"
+#include "i18n.h"
+
+EXPORT TRKTYP_T T_SENSOR = -1;
+
+static int log_sensor = 0;
+
+
+#if 0
+static drawCmd_t sensorD = {
+ NULL,
+ &screenDrawFuncs,
+ 0,
+ 1.0,
+ 0.0,
+ {0.0,0.0}, {0.0,0.0},
+ Pix2CoOrd, CoOrd2Pix };
+
+static char sensorName[STR_SHORT_SIZE];
+static char sensorScript[STR_LONG_SIZE];
+#endif
+
+typedef struct sensorData_t {
+ coOrd orig;
+ BOOL_T IsHilite;
+ char * name;
+ char * script;
+} sensorData_t, *sensorData_p;
+
+static sensorData_p GetsensorData ( track_p trk )
+{
+ return (sensorData_p) GetTrkExtraData(trk);
+}
+
+#define RADIUS 6
+
+#define sensor_SF (3.0)
+
+static void DDrawSensor(drawCmd_p d, coOrd orig, DIST_T scaleRatio,
+ wDrawColor color )
+{
+ coOrd p1, p2;
+
+ p1 = orig;
+ DrawFillCircle(d,p1, RADIUS * sensor_SF / scaleRatio,color);
+ Translate (&p2, orig, 45, RADIUS * sensor_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, wDrawColorWhite);
+ Translate (&p2, orig, 45+90, RADIUS * sensor_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, wDrawColorWhite);
+ Translate (&p2, orig, 45+180, RADIUS * sensor_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, wDrawColorWhite);
+ Translate (&p2, orig, 45+270, RADIUS * sensor_SF / scaleRatio);
+ DrawLine(d, p1, p2, 2, wDrawColorWhite);
+}
+
+static void DrawSensor (track_p t, drawCmd_p d, wDrawColor color )
+{
+ sensorData_p xx = GetsensorData(t);
+ DDrawSensor(d,xx->orig,GetScaleRatio(GetTrkScale(t)),color);
+}
+
+static void SensorBoundingBox (coOrd orig, DIST_T scaleRatio, coOrd *hi,
+ coOrd *lo)
+{
+ coOrd p1, p2;
+
+ p1 = orig;
+ Translate (&p1, orig, 0, -RADIUS * sensor_SF / scaleRatio);
+ Translate (&p2, orig, 0, RADIUS * sensor_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;
+}
+
+
+static void ComputeSensorBoundingBox (track_p t )
+{
+ coOrd lo, hi;
+ sensorData_p xx = GetsensorData(t);
+ SensorBoundingBox(xx->orig, GetScaleRatio(GetTrkScale(t)), &hi, &lo);
+ SetBoundingBox(t, hi, lo);
+}
+
+static DIST_T DistanceSensor (track_p t, coOrd * p )
+{
+ sensorData_p xx = GetsensorData(t);
+ return FindDistance(xx->orig, *p);
+}
+
+static struct {
+ char name[STR_SHORT_SIZE];
+ coOrd pos;
+ char script[STR_LONG_SIZE];
+} sensorProperties;
+
+typedef enum { NM, PS, SC } sensorDesc_e;
+static descData_t sensorDesc[] = {
+ /* NM */ { DESC_STRING, N_("Name"), &sensorProperties.name },
+ /* PS */ { DESC_POS, N_("Position"), &sensorProperties.pos },
+ /* SC */ { DESC_STRING, N_("Script"), &sensorProperties.script },
+ { DESC_NULL } };
+
+static void UpdateSensorProperties ( track_p trk, int inx, descData_p
+ descUpd, BOOL_T needUndoStart )
+{
+ sensorData_p xx = GetsensorData(trk);
+ const char *thename, *thescript;
+ char *newName, *newScript;
+ BOOL_T changed, nChanged, pChanged, sChanged;
+
+ switch (inx) {
+ case NM:
+ break;
+ case PS:
+ break;
+ case SC:
+ break;
+ case -1:
+ changed = nChanged = pChanged = sChanged = FALSE;
+ thename = wStringGetValue( (wString_p) sensorDesc[NM].control0 );
+ if (strcmp(thename,xx->name) != 0) {
+ nChanged = changed = TRUE;
+ newName = MyStrdup(thename);
+ }
+ thescript = wStringGetValue( (wString_p) sensorDesc[SC].control0 );
+ if (strcmp(thescript,xx->script) != 0) {
+ sChanged = changed = TRUE;
+ newScript = MyStrdup(thescript);
+ }
+ if (sensorProperties.pos.x != xx->orig.x ||
+ sensorProperties.pos.y != xx->orig.y) {
+ pChanged = changed = TRUE;
+ }
+ if (!changed) break;
+ if (needUndoStart)
+ UndoStart( _("Change Sensor"), "Change Sensor" );
+ UndoModify( trk );
+ if (nChanged) {
+ MyFree(xx->name);
+ xx->name = newName;
+ }
+ if (pChanged) {
+ UndrawNewTrack( trk );
+ }
+ if (pChanged) {
+ xx->orig = sensorProperties.pos;
+ }
+ if (sChanged) {
+ MyFree(xx->script);
+ xx->script = newScript;
+ }
+ if (pChanged) {
+ ComputeSensorBoundingBox( trk );
+ DrawNewTrack( trk );
+ }
+ break;
+ }
+}
+
+
+
+static void DescribeSensor (track_p trk, char * str, CSIZE_T len )
+{
+ sensorData_p xx = GetsensorData(trk);
+
+ strcpy( str, _(GetTrkTypeName( trk )) );
+ str++;
+ while (*str) {
+ *str = tolower((unsigned char)*str);
+ str++;
+ }
+ sprintf( str, _("(%d [%s]): Layer=%d, at %0.3f,%0.3f"),
+ GetTrkIndex(trk),
+ xx->name,GetTrkLayer(trk)+1, xx->orig.x, xx->orig.y);
+ strncpy(sensorProperties.name,xx->name,STR_SHORT_SIZE-1);
+ sensorProperties.name[STR_SHORT_SIZE-1] = '\0';
+ strncpy(sensorProperties.script,xx->script,STR_LONG_SIZE-1);
+ sensorProperties.script[STR_LONG_SIZE-1] = '\0';
+ sensorProperties.pos = xx->orig;
+ sensorDesc[NM].mode =
+ sensorDesc[SC].mode = DESC_NOREDRAW;
+ DoDescribe( _("Sensor"), trk, sensorDesc, UpdateSensorProperties );
+}
+
+static void DeleteSensor ( track_p trk )
+{
+ sensorData_p xx = GetsensorData(trk);
+ MyFree(xx->name); xx->name = NULL;
+ MyFree(xx->script); xx->script = NULL;
+}
+
+static BOOL_T WriteSensor ( track_p t, FILE * f )
+{
+ BOOL_T rc = TRUE;
+ sensorData_p xx = GetsensorData(t);
+ rc &= fprintf(f, "SENSOR %d %d %s %d %0.6f %0.6f \"%s\" \"%s\"\n",
+ GetTrkIndex(t), GetTrkLayer(t), GetTrkScaleName(t),
+ GetTrkVisible(t), xx->orig.x, xx->orig.y, xx->name,
+ xx->script)>0;
+ return rc;
+}
+
+static void ReadSensor ( char * line )
+{
+ wIndex_t index;
+ /*TRKINX_T trkindex;*/
+ track_p trk;
+ /*char * cp = NULL;*/
+ char *name;
+ char *script;
+ coOrd orig;
+ BOOL_T visible;
+ char scale[10];
+ wIndex_t layer;
+ sensorData_p xx;
+ if (!GetArgs(line+7,"dLsdpqq",&index,&layer,scale, &visible, &orig,&name,&script)) {
+ return;
+ }
+ trk = NewTrack(index, T_SENSOR, 0, sizeof(sensorData_t));
+ SetTrkVisible(trk, visible);
+ SetTrkScale(trk, LookupScale( scale ));
+ SetTrkLayer(trk, layer);
+ xx = GetsensorData ( trk );
+ xx->name = name;
+ xx->orig = orig;
+ xx->script = script;
+ ComputeSensorBoundingBox(trk);
+}
+
+static void MoveSensor (track_p trk, coOrd orig )
+{
+ sensorData_p xx = GetsensorData ( trk );
+ xx->orig.x += orig.x;
+ xx->orig.y += orig.y;
+ ComputeSensorBoundingBox(trk);
+}
+
+static void RotateSensor (track_p trk, coOrd orig, ANGLE_T angle )
+{
+}
+
+static void RescaleSensor (track_p trk, FLOAT_T ratio )
+{
+}
+
+static void FlipSensor (track_p trk, coOrd orig, ANGLE_T angle )
+{
+ sensorData_p xx = GetsensorData ( trk );
+ FlipPoint(&(xx->orig), orig, angle);
+ ComputeSensorBoundingBox(trk);
+}
+
+
+static trackCmd_t sensorCmds = {
+ "SENSOR",
+ DrawSensor,
+ DistanceSensor,
+ DescribeSensor,
+ DeleteSensor,
+ WriteSensor,
+ ReadSensor,
+ MoveSensor,
+ RotateSensor,
+ RescaleSensor,
+ 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 */
+ FlipSensor, /* flip */
+ NULL, /* drawPositionIndicator */
+ NULL, /* advancePositionIndicator */
+ NULL, /* checkTraverse */
+ NULL, /* makeParallel */
+ NULL /* drawDesc */
+};
+
+static coOrd sensorEditOrig;
+static track_p sensorEditTrack;
+static char sensorEditName[STR_SHORT_SIZE];
+static char sensorEditScript[STR_LONG_SIZE];
+
+static paramFloatRange_t r_1000_1000 = { -1000.0, 1000.0, 80 };
+static paramData_t sensorEditPLs[] = {
+#define I_SENSORNAME (0)
+ /*0*/ { PD_STRING, sensorEditName, "name", PDO_NOPREF, (void*)200, N_("Name") },
+#define I_ORIGX (1)
+ /*1*/ { PD_FLOAT, &sensorEditOrig.x, "origx", PDO_DIM, &r_1000_1000, N_("Orgin X") },
+#define I_ORIGY (2)
+ /*2*/ { PD_FLOAT, &sensorEditOrig.y, "origy", PDO_DIM, &r_1000_1000, N_("Origin Y") },
+#define I_SENSORSCRIPT (3)
+ /*3*/ { PD_STRING, sensorEditScript, "script", PDO_NOPREF, (void*)350, N_("Script") },
+};
+
+static paramGroup_t sensorEditPG = { "sensorEdit", 0, sensorEditPLs, sizeof sensorEditPLs/sizeof sensorEditPLs[0] };
+static wWin_p sensorEditW;
+
+static void SensorEditOk ( void * junk )
+{
+ track_p trk;
+ sensorData_p xx;
+
+ if (sensorEditTrack == NULL) {
+ UndoStart( _("Create Sensor"), "Create Sensor");
+ trk = NewTrack(0, T_SENSOR, 0, sizeof(sensorData_t));
+ } else {
+ UndoStart( _("Modify Sensor"), "Modify Sensor");
+ trk = sensorEditTrack;
+ }
+ xx = GetsensorData(trk);
+ xx->orig = sensorEditOrig;
+ if ( xx->name == NULL || strncmp (xx->name, sensorEditName, STR_SHORT_SIZE) != 0) {
+ MyFree(xx->name);
+ xx->name = MyStrdup(sensorEditName);
+ }
+ if ( xx->script == NULL || strncmp (xx->script, sensorEditScript, STR_LONG_SIZE) != 0) {
+ MyFree(xx->script);
+ xx->script = MyStrdup(sensorEditScript);
+ }
+ UndoEnd();
+ DoRedraw();
+ ComputeSensorBoundingBox(trk);
+ wHide( sensorEditW );
+}
+
+#if 0
+static void SensorEditCancel ( wWin_p junk )
+{
+ wHide( sensorEditW );
+}
+#endif
+
+static void EditSensorDialog()
+{
+ sensorData_p xx;
+
+ if ( !sensorEditW ) {
+ ParamRegister( &sensorEditPG );
+ sensorEditW = ParamCreateDialog (&sensorEditPG,
+ MakeWindowTitle(_("Edit sensor")),
+ _("Ok"), SensorEditOk,
+ wHide, TRUE, NULL,
+ F_BLOCK,
+ NULL );
+ }
+ if (sensorEditTrack == NULL) {
+ sensorEditName[0] = '\0';
+ sensorEditScript[0] = '\0';
+ } else {
+ xx = GetsensorData ( sensorEditTrack );
+ strncpy(sensorEditName,xx->name,STR_SHORT_SIZE);
+ strncpy(sensorEditScript,xx->script,STR_LONG_SIZE);
+ sensorEditOrig = xx->orig;
+ }
+ ParamLoadControls( &sensorEditPG );
+ wShow( sensorEditW );
+}
+
+static void EditSensor (track_p trk)
+{
+ sensorEditTrack = trk;
+ EditSensorDialog();
+}
+
+static void CreateNewSensor (coOrd orig)
+{
+ sensorEditOrig = orig;
+ sensorEditTrack = NULL;
+ EditSensorDialog();
+}
+
+static STATUS_T CmdSensor ( wAction_t action, coOrd pos )
+{
+
+
+ switch (action) {
+ case C_START:
+ InfoMessage(_("Place sensor"));
+ return C_CONTINUE;
+ case C_DOWN:
+ SnapPos(&pos);
+ DDrawSensor( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ case C_MOVE:
+ SnapPos(&pos);
+ DDrawSensor( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ case C_UP:
+ SnapPos(&pos);
+ DDrawSensor( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ CreateNewSensor(pos);
+ return C_TERMINATE;
+ case C_REDRAW:
+ case C_CANCEL:
+ DDrawSensor( &tempD, pos, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ default:
+ return C_CONTINUE;
+ }
+}
+
+static coOrd ctlhiliteOrig, ctlhiliteSize;
+static POS_T ctlhiliteBorder;
+static wDrawColor ctlhiliteColor = 0;
+static void DrawSensorTrackHilite( void )
+{
+ wPos_t x, y, w, h;
+ if (ctlhiliteColor==0)
+ ctlhiliteColor = wDrawColorGray(87);
+ w = (wPos_t)((ctlhiliteSize.x/mainD.scale)*mainD.dpi+0.5);
+ h = (wPos_t)((ctlhiliteSize.y/mainD.scale)*mainD.dpi+0.5);
+ mainD.CoOrd2Pix(&mainD,ctlhiliteOrig,&x,&y);
+ wDrawFilledRectangle( mainD.d, x, y, w, h, ctlhiliteColor, wDrawOptTemp );
+}
+
+static int SensorMgmProc ( int cmd, void * data )
+{
+ track_p trk = (track_p) data;
+ sensorData_p xx = GetsensorData(trk);
+ /*char msg[STR_SIZE];*/
+
+ switch ( cmd ) {
+ case CONTMGM_CAN_EDIT:
+ return TRUE;
+ break;
+ case CONTMGM_DO_EDIT:
+ EditSensor(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) {
+ ctlhiliteBorder = mainD.scale*0.1;
+ if ( ctlhiliteBorder < trackGauge ) ctlhiliteBorder = trackGauge;
+ GetBoundingBox( trk, &ctlhiliteSize, &ctlhiliteOrig );
+ ctlhiliteOrig.x -= ctlhiliteBorder;
+ ctlhiliteOrig.y -= ctlhiliteBorder;
+ ctlhiliteSize.x -= ctlhiliteOrig.x-ctlhiliteBorder;
+ ctlhiliteSize.y -= ctlhiliteOrig.y-ctlhiliteBorder;
+ DrawSensorTrackHilite();
+ xx->IsHilite = TRUE;
+ }
+ break;
+ case CONTMGM_UN_HILIGHT:
+ if (xx->IsHilite) {
+ ctlhiliteBorder = mainD.scale*0.1;
+ if ( ctlhiliteBorder < trackGauge ) ctlhiliteBorder = trackGauge;
+ GetBoundingBox( trk, &ctlhiliteSize, &ctlhiliteOrig );
+ ctlhiliteOrig.x -= ctlhiliteBorder;
+ ctlhiliteOrig.y -= ctlhiliteBorder;
+ ctlhiliteSize.x -= ctlhiliteOrig.x-ctlhiliteBorder;
+ ctlhiliteSize.y -= ctlhiliteOrig.y-ctlhiliteBorder;
+ DrawSensorTrackHilite();
+ xx->IsHilite = FALSE;
+ }
+ break;
+ case CONTMGM_GET_TITLE:
+ sprintf(message,"\t%s\t",xx->name);
+ break;
+ }
+ return FALSE;
+}
+
+#include "bitmaps/sensor.xpm"
+
+EXPORT void SensorMgmLoad ( void )
+{
+ track_p trk;
+ static wIcon_p sensorI = NULL;
+
+ if (sensorI == NULL) {
+ sensorI = wIconCreatePixMap( sensor_xpm );
+ }
+
+ TRK_ITERATE(trk) {
+ if (GetTrkType(trk) != T_SENSOR) continue;
+ ContMgmLoad (sensorI, SensorMgmProc, (void *) trk );
+ }
+}
+
+#define ACCL_SENSOR 0
+
+EXPORT void InitCmdSensor ( wMenu_p menu )
+{
+ AddMenuButton( menu, CmdSensor, "cmdSensor", _("Sensor"),
+ wIconCreatePixMap( sensor_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_SENSOR, NULL );
+}
+
+EXPORT void InitTrkSensor ( void )
+{
+ T_SENSOR = InitObject ( &sensorCmds );
+ log_sensor = LogFindIndex ( "sensor" );
+}
diff --git a/app/bin/csignal.c b/app/bin/csignal.c
new file mode 100644
index 0000000..06adb19
--- /dev/null
+++ b/app/bin/csignal.c
@@ -0,0 +1,885 @@
+/** \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 : <170314.1311>
+ *
+ * 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 <ctype.h>
+#include "track.h"
+#include "trackx.h"
+#include "compound.h"
+#include "i18n.h"
+
+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 {
+ 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 (signalData_p) GetTrkExtraData(trk);
+}
+
+#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 },
+ /* 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;
+ 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=%d, %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);
+ rc &= fprintf(f, "SIGNAL %d %d %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, xx->name)>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, "\tEND\n" )>0;
+ return rc;
+}
+
+static void 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;
+ }
+ DYNARR_RESET( signalAspect_p, signalAspect_da );
+ while ( (cp = GetNextLine()) != NULL ) {
+ while (isspace((unsigned char)*cp)) cp++;
+ if ( strncmp( cp, "END", 3 ) == 0 ) {
+ break;
+ }
+ if ( *cp == '\n' || *cp == '#' ) {
+ continue;
+ }
+ if ( strncmp( cp, "ASPECT", 6 ) == 0 ) {
+ if (!GetArgs(cp+4,"qq",&aspname,&aspscript)) return;
+ 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);
+}
+
+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 wPos_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, (void*)200, N_("Name") },
+#define I_ORIGX (1)
+ /*1*/ { PD_FLOAT, &signalEditOrig.x, "origx", PDO_DIM, &r_1000_1000, N_("Orgin 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, (void*)AspectEdit, "edit", PDO_DLGCMDBUTTON, NULL, N_("Edit Aspect") },
+#define I_SIGNALASPECTADD (7)
+ /*7*/ { PD_BUTTON, (void*)AspectAdd, "add", PDO_DLGCMDBUTTON, NULL, N_("Add Aspect") },
+#define I_SIGNALASPECTDELETE (8)
+ /*8*/ { PD_BUTTON, (void*)AspectDelete, "delete", 0, NULL, N_("Delete Aspect") },
+};
+static paramGroup_t signalEditPG = { "signalEdit", 0, signalEditPLs, sizeof signalEditPLs/sizeof signalEditPLs[0] };
+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, (void*)200, N_("Name") },
+#define I_ASPECTSCRIPT (1)
+ /*1*/ { PD_STRING, signalAspectEditScript, "script", PDO_NOPREF, (void*)350, N_("Script") },
+#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, sizeof aspectEditPLs/sizeof aspectEditPLs[0] };
+static wWin_p aspectEditW;
+
+
+static void SignalEditOk ( void * junk )
+{
+ track_p trk;
+ signalData_p xx;
+ wIndex_t ia;
+
+ 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. */
+ /* We will delete the Signal and re-create it. */
+ BOOL_T visible = GetTrkVisible(trk);
+ SCALEINX_T scale = GetTrkScale(trk);
+ LAYER_T layer = GetTrkLayer(trk);
+ wIndex_t tindx = GetTrkIndex(trk);
+ FreeTrack(trk);
+ trk = NewTrack(tindx, T_SIGNAL, 0, sizeof(signalData_t)+(sizeof(signalAspect_t)*(signalAspect_da.cnt-1))+1);
+ SetTrkVisible(trk,visible);
+ SetTrkScale(trk,scale);
+ SetTrkLayer(trk,layer);
+ 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 && wListGetItemSelected( aspectSelL, inx ) != TRUE;
+ inx++ );
+ if ( 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; inx<cnt; inx++ ) {
+ if ( !wListGetItemSelected( aspectSelL, inx ) ) continue;
+ wListDelete( aspectSelL, inx );
+ MoveAspectUp(inx);
+ inx--;
+ cnt--;
+ }
+ DoChangeNotification( CHANGE_PARAMS );
+}
+
+static void EditSignalDialog()
+{
+ signalData_p xx;
+ wIndex_t ia;
+
+ if ( !signalEditW ) {
+ ParamRegister( &signalEditPG );
+ signalEditW = ParamCreateDialog (&signalEditPG,
+ MakeWindowTitle(_("Edit signal")),
+ _("Ok"), SignalEditOk,
+ SignalEditCancel, TRUE, NULL,
+ F_RESIZE|F_RECALLSIZE|F_BLOCK,
+ SignalEditDlgUpdate );
+ }
+ if (signalCreate_P) {
+ signalEditName[0] = '\0';
+ signalEditHeadCount = 1;
+ wListClear( aspectSelL );
+ DYNARR_RESET( signalAspect_p, signalAspect_da );
+ } else {
+ xx = GetsignalData ( signalEditTrack );
+ strncpy(signalEditName,xx->name,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 )
+{
+
+
+ switch (action) {
+ case C_START:
+ InfoMessage(_("Place base of signal"));
+ return C_CONTINUE;
+ case C_DOWN:
+ SnapPos(&pos);
+ pos0 = pos;
+ InfoMessage(_("Drag to orient signal"));
+ return C_CONTINUE;
+ case C_MOVE:
+ SnapPos(&pos);
+ orient = FindAngle(pos0,pos);
+ DDrawSignal( &tempD, pos0, orient, 1, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ case C_UP:
+ SnapPos(&pos);
+ orient = FindAngle(pos0,pos);
+ CreateNewSignal(pos0,orient);
+ return C_TERMINATE;
+ case C_REDRAW:
+ case C_CANCEL:
+ DDrawSignal( &tempD, pos0, orient, 1, GetScaleRatio(curScaleInx), wDrawColorBlack );
+ return C_CONTINUE;
+ default:
+ return C_CONTINUE;
+ }
+}
+
+static coOrd sighiliteOrig, sighiliteSize;
+static POS_T sighiliteBorder;
+static wDrawColor sighiliteColor = 0;
+static void DrawSignalTrackHilite( void )
+{
+ wPos_t x, y, w, h;
+ if (sighiliteColor==0)
+ sighiliteColor = wDrawColorGray(87);
+ w = (wPos_t)((sighiliteSize.x/mainD.scale)*mainD.dpi+0.5);
+ h = (wPos_t)((sighiliteSize.y/mainD.scale)*mainD.dpi+0.5);
+ mainD.CoOrd2Pix(&mainD,sighiliteOrig,&x,&y);
+ wDrawFilledRectangle( mainD.d, x, y, w, h, sighiliteColor, wDrawOptTemp );
+}
+
+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 );
+ }
+
+ TRK_ITERATE(trk) {
+ if (GetTrkType(trk) != T_SIGNAL) continue;
+ ContMgmLoad (signalI, SignalMgmProc, (void *) trk );
+ }
+}
+
+#define ACCL_SIGNAL 0
+
+EXPORT void InitCmdSignal ( wMenu_p menu )
+{
+ AddMenuButton( menu, CmdSignal, "cmdSignal", _("Signal"),
+ wIconCreatePixMap( signal_xpm ), LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_SIGNAL, NULL );
+}
+
+EXPORT void InitTrkSignal ( void )
+{
+ T_SIGNAL = InitObject ( &signalCmds );
+ log_signal = LogFindIndex ( "signal" );
+}
diff --git a/app/bin/cswitchmotor.c b/app/bin/cswitchmotor.c
index 7b948a8..dbe006c 100644
--- a/app/bin/cswitchmotor.c
+++ b/app/bin/cswitchmotor.c
@@ -1,6 +1,8 @@
/** \file cswitchmotor.c
* Switch Motors
- * Created by Robert Heller on Sat Mar 14 10:39:56 2009
+ */
+
+/* Created by Robert Heller on Sat Mar 14 10:39:56 2009
* ------------------------------------------------------------------
* Modification History: $Log: not supported by cvs2svn $
* Modification History: Revision 1.5 2009/11/23 19:46:16 rheller
@@ -49,16 +51,15 @@
#include <ctype.h>
#include "track.h"
+#include "trackx.h"
#include "compound.h"
#include "i18n.h"
EXPORT TRKTYP_T T_SWITCHMOTOR = -1;
-#define SWITCHMOTORCMD
-
static int log_switchmotor = 0;
-#ifdef SWITCHMOTORCMD
+
static drawCmd_t switchmotorD = {
NULL,
&screenDrawFuncs,
@@ -82,19 +83,41 @@ static paramData_t switchmotorPLs[] = {
};
static paramGroup_t switchmotorPG = { "switchmotor", 0, switchmotorPLs, sizeof switchmotorPLs/sizeof switchmotorPLs[0] };
+static wWin_p switchmotorW;
+
+static char switchmotorEditName[STR_SHORT_SIZE];
+static char switchmotorEditNormal[STR_LONG_SIZE];
+static char switchmotorEditReverse[STR_LONG_SIZE];
+static char switchmotorEditPointSense[STR_LONG_SIZE];
+static long int switchmotorEditTonum;
+static track_p switchmotorEditTrack;
+
+static paramIntegerRange_t r0_999999 = { 0, 999999 };
+
+static paramData_t switchmotorEditPLs[] = {
+/*0*/ { PD_STRING, switchmotorEditName, "name", PDO_NOPREF, (void*)200, N_("Name") },
+/*1*/ { PD_STRING, switchmotorEditNormal, "normal", PDO_NOPREF, (void*)350, N_("Normal") },
+/*2*/ { PD_STRING, switchmotorEditReverse, "reverse", PDO_NOPREF, (void*)350, N_("Reverse") },
+/*3*/ { PD_STRING, switchmotorEditPointSense, "pointSense", PDO_NOPREF, (void*)350, N_("Point Sense") },
+/*4*/ { PD_LONG, &switchmotorEditTonum, "turnoutNumber", PDO_NOPREF, &r0_999999, N_("Turnout Number"), BO_READONLY },
+};
+
+static paramGroup_t switchmotorEditPG = { "switchmotorEdit", 0, switchmotorEditPLs, sizeof switchmotorEditPLs/sizeof switchmotorEditPLs[0] };
+static wWin_p switchmotorEditW;
+
/*
static dynArr_t switchmotorTrk_da;
#define switchmotorTrk(N) DYNARR_N( track_p , switchmotorTrk_da, N )
*/
-static wWin_p switchmotorW;
-#endif
typedef struct switchmotorData_t {
- char * name;
- char * normal;
- char * reverse;
- char * pointsense;
- track_p turnout;
+ char * name;
+ char * normal;
+ char * reverse;
+ char * pointsense;
+ BOOL_T IsHilite;
+ TRKINX_T turnindx;
+ track_p turnout;
} switchmotorData_t, *switchmotorData_p;
static switchmotorData_p GetswitchmotorData ( track_p trk )
@@ -102,27 +125,75 @@ static switchmotorData_p GetswitchmotorData ( track_p trk )
return (switchmotorData_p) GetTrkExtraData(trk);
}
+#if 0
#include "bitmaps/switchmotormark.xbm"
static wDrawBitMap_p switchmotormark_bm = NULL;
+#endif
+
+static coOrd switchmotorPoly_Pix[] = {
+ {6,0}, {6,13}, {4,13}, {4,19}, {6,19}, {6,23}, {9,23}, {9,19}, {13,19},
+ {13,23}, {27,23}, {27,10}, {13,10}, {13,13}, {9,13}, {9,0}, {6,0} };
+#define switchmotorPoly_CNT (sizeof(switchmotorPoly_Pix)/sizeof(switchmotorPoly_Pix[0]))
+#define switchmotorPoly_SF (3.0)
+static void ComputeSwitchMotorBoundingBox (track_p t)
+{
+ coOrd hi, lo, p;
+ switchmotorData_p data_p = GetswitchmotorData(t);
+ struct extraData *xx = GetTrkExtraData(data_p->turnout);
+ coOrd orig = xx->orig;
+ ANGLE_T angle = xx->angle;
+ SCALEINX_T s = GetTrkScale(data_p->turnout);
+ DIST_T scaleRatio = GetScaleRatio(s);
+ int iPoint;
+ ANGLE_T x_angle, y_angle;
+
+ x_angle = 90-(360-angle);
+ if (x_angle < 0) x_angle += 360;
+ y_angle = -(360-angle);
+ if (y_angle < 0) y_angle += 360;
+
+
+ for (iPoint = 0; iPoint < switchmotorPoly_CNT; iPoint++) {
+ Translate (&p, orig, x_angle, switchmotorPoly_Pix[iPoint].x * switchmotorPoly_SF / scaleRatio );
+ Translate (&p, p, y_angle, (10+switchmotorPoly_Pix[iPoint].y) * switchmotorPoly_SF / scaleRatio );
+ if (iPoint == 0) {
+ lo = p;
+ hi = p;
+ } else {
+ if (p.x < lo.x) lo.x = p.x;
+ if (p.y < lo.y) lo.y = p.y;
+ if (p.x > hi.x) hi.x = p.x;
+ if (p.y > hi.y) hi.y = p.y;
+ }
+ }
+ SetBoundingBox(t, hi, lo);
+}
+
+
static void DrawSwitchMotor (track_p t, drawCmd_p d, wDrawColor color )
{
- coOrd p;
- switchmotorData_p data_p = GetswitchmotorData(t);
- struct extraData *xx = GetTrkExtraData(data_p->turnout);
- coOrd orig = xx->orig;
- ANGLE_T angle = xx->angle;
-
- if (switchmotormark_bm == NULL) {
- switchmotormark_bm =
- wDrawBitMapCreate( mainD.d,
- switchmotormark_width,
- switchmotormark_height, 16, 16,
- switchmotormark_bits);
- }
- Translate (&p, orig, -angle , 2 );
- Translate (&p, p, 90-angle, 2);
- DrawBitMap(d, p, switchmotormark_bm, color);
+ coOrd p[switchmotorPoly_CNT];
+ switchmotorData_p data_p = GetswitchmotorData(t);
+ struct extraData *xx = GetTrkExtraData(data_p->turnout);
+ coOrd orig = xx->orig;
+ ANGLE_T angle = xx->angle;
+ SCALEINX_T s = GetTrkScale(data_p->turnout);
+ DIST_T scaleRatio = GetScaleRatio(s);
+ int iPoint;
+ ANGLE_T x_angle, y_angle;
+
+ x_angle = 90-(360-angle);
+ if (x_angle < 0) x_angle += 360;
+ y_angle = -(360-angle);
+ if (y_angle < 0) y_angle += 360;
+
+
+ for (iPoint = 0; iPoint < switchmotorPoly_CNT; iPoint++) {
+ Translate (&p[iPoint], orig, x_angle, switchmotorPoly_Pix[iPoint].x * switchmotorPoly_SF / scaleRatio );
+ Translate (&p[iPoint], p[iPoint], y_angle, (10+switchmotorPoly_Pix[iPoint].y) * switchmotorPoly_SF / scaleRatio );
+ }
+ DrawFillPoly(d, switchmotorPoly_CNT, p, wDrawColorBlack);
}
static struct {
@@ -199,6 +270,7 @@ static void UpdateSwitchMotor (track_p trk, int inx, descData_p descUpd, BOOL_T
static DIST_T DistanceSwitchMotor (track_p t, coOrd * p )
{
switchmotorData_p xx = GetswitchmotorData(t);
+ if (xx->turnout == NULL) return 0;
return GetTrkDistance(xx->turnout,*p);
}
@@ -227,7 +299,8 @@ static void DescribeSwitchMotor (track_p trk, char * str, CSIZE_T len )
switchmotorData.reverse[STR_LONG_SIZE-1] = '\0';
strncpy(switchmotorData.pointsense,xx->pointsense,STR_LONG_SIZE-1);
switchmotorData.pointsense[STR_LONG_SIZE-1] = '\0';
- switchmotorData.turnout = GetTrkIndex(xx->turnout);
+ if (xx->turnout == NULL) switchmotorData.turnout = 0;
+ else switchmotorData.turnout = GetTrkIndex(xx->turnout);
switchmotorDesc[TO].mode = DESC_RO;
switchmotorDesc[NM].mode =
switchmotorDesc[NOR].mode =
@@ -245,13 +318,20 @@ static void switchmotorDebug (track_p trk)
LOG( log_switchmotor, 1, ("*** switchmotorDebug(): normal = \"%s\"\n",xx->normal))
LOG( log_switchmotor, 1, ("*** switchmotorDebug(): reverse = \"%s\"\n",xx->reverse))
LOG( log_switchmotor, 1, ("*** switchmotorDebug(): pointsense = \"%s\"\n",xx->pointsense))
- LOG( log_switchmotor, 1, ("*** switchmotorDebug(): turnout = T%d, %s\n",
- GetTrkIndex(xx->turnout), GetTrkTypeName(xx->turnout)))
+ LOG( log_switchmotor, 1, ("*** switchmotorDebug(): turnindx = %d\n",xx->turnindx))
+ if (xx->turnout != NULL) {
+ LOG( log_switchmotor, 1, ("*** switchmotorDebug(): turnout = T%d, %s\n",
+ GetTrkIndex(xx->turnout), GetTrkTypeName(xx->turnout)))
+ }
}
static void DeleteSwitchMotor ( track_p trk )
{
- switchmotorData_p xx = GetswitchmotorData(trk);
+ LOG( log_switchmotor, 1,("*** DeleteSwitchMotor(%p)\n",trk))
+ LOG( log_switchmotor, 1,("*** DeleteSwitchMotor(): index is %d\n",GetTrkIndex(trk)))
+ switchmotorData_p xx = GetswitchmotorData(trk);
+ LOG( log_switchmotor, 1,("*** DeleteSwitchMotor(): xx = %p, xx->name = %p, xx->normal = %p, xx->reverse = %p, xx->pointsense = %p\n",
+ xx,xx->name,xx->normal,xx->reverse,xx->pointsense))
MyFree(xx->name); xx->name = NULL;
MyFree(xx->normal); xx->normal = NULL;
MyFree(xx->reverse); xx->reverse = NULL;
@@ -262,7 +342,8 @@ static BOOL_T WriteSwitchMotor ( track_p t, FILE * f )
{
BOOL_T rc = TRUE;
switchmotorData_p xx = GetswitchmotorData(t);
-
+
+ if (xx->turnout == NULL) return FALSE;
rc &= fprintf(f, "SWITCHMOTOR %d %d \"%s\" \"%s\" \"%s\" \"%s\"\n",
GetTrkIndex(t), GetTrkIndex(xx->turnout), xx->name,
xx->normal, xx->reverse, xx->pointsense)>0;
@@ -287,8 +368,28 @@ static void ReadSwitchMotor ( char * line )
xx->normal = normal;
xx->reverse = reverse;
xx->pointsense = pointsense;
- xx->turnout = FindTrack(trkindex);
- switchmotorDebug(trk);
+ xx->turnindx = trkindex;
+ LOG( log_switchmotor, 1,("*** ReadSwitchMotor(): trk = %p (%d), xx = %p\n",trk,GetTrkIndex(trk),xx))
+ LOG( log_switchmotor, 1,("*** ReadSwitchMotor(): name = %p, normal = %p, reverse = %p, pointsense = %p\n",
+ name,normal,reverse,pointsense))
+ switchmotorDebug(trk);
+}
+
+EXPORT void ResolveSwitchmotorTurnout ( track_p trk )
+{
+ LOG( log_switchmotor, 1,("*** ResolveSwitchmotorTurnout(%p)\n",trk))
+ switchmotorData_p xx;
+ track_p t_trk;
+ if (GetTrkType(trk) != T_SWITCHMOTOR) return;
+ xx = GetswitchmotorData(trk);
+ LOG( log_switchmotor, 1, ("*** ResolveSwitchmotorTurnout(%d)\n",GetTrkIndex(trk)))
+ t_trk = FindTrack(xx->turnindx);
+ if (t_trk == NULL) {
+ NoticeMessage( _("ResolveSwitchmotor: Turnout T%d: T%d doesn't exist"), _("Continue"), NULL, GetTrkIndex(trk), xx->turnindx );
+ }
+ xx->turnout = t_trk;
+ ComputeSwitchMotorBoundingBox(trk);
+ LOG( log_switchmotor, 1,("*** ResolveSwitchmotorTurnout(): t_trk = (%d) %p\n",xx->turnindx,t_trk))
}
static void MoveSwitchMotor (track_p trk, coOrd orig ) {}
@@ -329,7 +430,6 @@ static trackCmd_t switchmotorCmds = {
NULL /* drawDesc */
};
-#ifdef SWITCHMOTORCMD
static track_p FindSwitchMotor (track_p trk)
{
track_p a_trk;
@@ -352,7 +452,7 @@ static void SwitchMotorOk ( void * junk )
LOG( log_switchmotor, 1, ("*** SwitchMotorOk()\n"))
ParamUpdate (&switchmotorPG );
if ( switchmotorName[0]==0 ) {
- NoticeMessage( 0, "Switch motor must have a name!", _("Ok"));
+ NoticeMessage( _("Switch motor must have a name!"), _("Ok"), NULL);
return;
}
wDrawDelayUpdate( mainD.d, TRUE );
@@ -365,9 +465,12 @@ static void SwitchMotorOk ( void * junk )
xx->reverse = MyStrdup(switchmotorReverse);
xx->pointsense = MyStrdup(switchmotorPointSense);
xx->turnout = switchmotorTurnout;
+ LOG( log_switchmotor, 1,("*** SwitchMotorOk(): trk = %p (%d), xx = %p\n",trk,GetTrkIndex(trk),xx))
switchmotorDebug(trk);
UndoEnd();
- wHide( switchmotorW );
+ wHide( switchmotorW );
+ ComputeSwitchMotorBoundingBox(trk);
+ DrawNewTrack(trk);
}
static void NewSwitchMotorDialog(track_p trk)
@@ -413,6 +516,7 @@ static STATUS_T CmdSwitchMotorCreate( wAction_t action, coOrd pos )
}
}
+#if 0
extern BOOL_T inDescribeCmd;
static STATUS_T CmdSwitchMotorEdit( wAction_t action, coOrd pos )
@@ -501,27 +605,177 @@ static STATUS_T CmdSwitchMotor (wAction_t action, coOrd pos )
default: return C_TERMINATE;
}
}
+#endif
+
+static void SwitchMotorEditOk ( void * junk )
+{
+ switchmotorData_p xx;
+ track_p trk;
+
+ LOG( log_switchmotor, 1, ("*** SwitchMotorEditOk()\n"))
+ ParamUpdate (&switchmotorEditPG );
+ if ( switchmotorEditName[0]==0 ) {
+ NoticeMessage( _("Switch motor must have a name!") , _("Ok"), NULL);
+ return;
+ }
+ wDrawDelayUpdate( mainD.d, TRUE );
+ UndoStart( _("Modify Switch Motor"), "Modify Switch Motor" );
+ trk = switchmotorEditTrack;
+ xx = GetswitchmotorData( trk );
+ xx->name = MyStrdup(switchmotorEditName);
+ xx->normal = MyStrdup(switchmotorEditNormal);
+ xx->reverse = MyStrdup(switchmotorEditReverse);
+ xx->pointsense = MyStrdup(switchmotorEditPointSense);
+ switchmotorDebug(trk);
+ UndoEnd();
+ wHide( switchmotorEditW );
+}
+
+
+static void EditSwitchMotor (track_p trk)
+{
+ switchmotorData_p xx = GetswitchmotorData(trk);
+ strncpy(switchmotorEditName,xx->name,STR_SHORT_SIZE);
+ strncpy(switchmotorEditNormal,xx->normal,STR_LONG_SIZE);
+ strncpy(switchmotorEditReverse,xx->reverse,STR_LONG_SIZE);
+ strncpy(switchmotorEditPointSense,xx->pointsense,STR_LONG_SIZE);
+ if (xx->turnout == NULL) switchmotorEditTonum = 0;
+ else switchmotorEditTonum = GetTrkIndex(xx->turnout);
+ switchmotorEditTrack = trk;
+ if ( !switchmotorEditW ) {
+ ParamRegister( &switchmotorEditPG );
+ switchmotorEditW = ParamCreateDialog (&switchmotorEditPG,
+ MakeWindowTitle(_("Edit switch motor")),
+ _("Ok"), SwitchMotorEditOk,
+ wHide, TRUE, NULL, F_BLOCK,
+ NULL );
+ }
+ ParamLoadControls( &switchmotorEditPG );
+ sprintf( message, _("Edit switch motor %d"), GetTrkIndex(trk) );
+ wWinSetTitle( switchmotorEditW, message );
+ wShow (switchmotorEditW);
+}
+
+static coOrd swmhiliteOrig, swmhiliteSize;
+static POS_T swmhiliteBorder;
+static wDrawColor swmhiliteColor = 0;
+static void DrawSWMotorTrackHilite( void )
+{
+ wPos_t x, y, w, h;
+ if (swmhiliteColor==0)
+ swmhiliteColor = wDrawColorGray(87);
+ w = (wPos_t)((swmhiliteSize.x/mainD.scale)*mainD.dpi+0.5);
+ h = (wPos_t)((swmhiliteSize.y/mainD.scale)*mainD.dpi+0.5);
+ mainD.CoOrd2Pix(&mainD,swmhiliteOrig,&x,&y);
+ wDrawFilledRectangle( mainD.d, x, y, w, h, swmhiliteColor, wDrawOptTemp );
+}
+
+static int SwitchmotorMgmProc ( int cmd, void * data )
+{
+ track_p trk = (track_p) data;
+ switchmotorData_p xx = GetswitchmotorData(trk);
+ /*char msg[STR_SIZE];*/
+
+ switch ( cmd ) {
+ case CONTMGM_CAN_EDIT:
+ return TRUE;
+ break;
+ case CONTMGM_DO_EDIT:
+ EditSwitchMotor (trk);
+ /*inDescribeCmd = TRUE;*/
+ /*DescribeTrack (trk, msg, sizeof msg );*/
+ /*InfoMessage( msg );*/
+ 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->turnout != NULL && !xx->IsHilite) {
+ swmhiliteBorder = mainD.scale*0.1;
+ if ( swmhiliteBorder < trackGauge ) swmhiliteBorder = trackGauge;
+ GetBoundingBox( xx->turnout, &swmhiliteSize, &swmhiliteOrig );
+ swmhiliteOrig.x -= swmhiliteBorder;
+ swmhiliteOrig.y -= swmhiliteBorder;
+ swmhiliteSize.x -= swmhiliteOrig.x-swmhiliteBorder;
+ swmhiliteSize.y -= swmhiliteOrig.y-swmhiliteBorder;
+ DrawSWMotorTrackHilite();
+ xx->IsHilite = TRUE;
+ }
+ break;
+ case CONTMGM_UN_HILIGHT:
+ if (xx->turnout != NULL && xx->IsHilite) {
+ swmhiliteBorder = mainD.scale*0.1;
+ if ( swmhiliteBorder < trackGauge ) swmhiliteBorder = trackGauge;
+ GetBoundingBox( xx->turnout, &swmhiliteSize, &swmhiliteOrig );
+ swmhiliteOrig.x -= swmhiliteBorder;
+ swmhiliteOrig.y -= swmhiliteBorder;
+ swmhiliteSize.x -= swmhiliteOrig.x-swmhiliteBorder;
+ swmhiliteSize.y -= swmhiliteOrig.y-swmhiliteBorder;
+ DrawSWMotorTrackHilite();
+ xx->IsHilite = FALSE;
+ }
+ break;
+ case CONTMGM_GET_TITLE:
+ if (xx->turnout == NULL) {
+ sprintf( message, "\t%s\t%d", xx->name, 0);
+ } else {
+ sprintf( message, "\t%s\t%d", xx->name, GetTrkIndex(xx->turnout));
+ }
+ break;
+ }
+ return FALSE;
+}
//#include "bitmaps/switchmotor.xpm"
-#include "bitmaps/switchmnew.xpm"
-#include "bitmaps/switchmedit.xpm"
-#include "bitmaps/switchmdel.xpm"
+//#include "bitmaps/switchmnew.xpm"
+//#include "bitmaps/switchmedit.xpm"
+//#include "bitmaps/switchmdel.xpm"
+#include "bitmaps/switchm.xpm"
+
+EXPORT void SwitchmotorMgmLoad( void )
+{
+ track_p trk;
+ static wIcon_p switchmI = NULL;
+
+ if ( switchmI == NULL)
+ switchmI = wIconCreatePixMap( switchm_xpm );
+
+ TRK_ITERATE(trk) {
+ if (GetTrkType(trk) != T_SWITCHMOTOR) continue;
+ ContMgmLoad( switchmI, SwitchmotorMgmProc, (void *)trk );
+ }
+}
EXPORT void InitCmdSwitchMotor( wMenu_p menu )
{
switchmotorName[0] = '\0';
switchmotorNormal[0] = '\0';
switchmotorReverse[0] = '\0';
- switchmotorPointSense[0] = '\0';
- ButtonGroupBegin( _("SwitchMotor"), "cmdSwitchMotorSetCmd", _("Switch Motors") );
- AddMenuButton( menu, CmdSwitchMotor, "cmdSwitchMotorCreate", _("Create Switch Motor"), wIconCreatePixMap(switchmnew_xpm), LEVEL0_50, IC_CANCEL|IC_POPUP, ACCL_SWITCHMOTOR1, (void*)SWITCHMOTOR_CREATE );
- AddMenuButton( menu, CmdSwitchMotor, "cmdSwitchMotorEdit", _("Edit Switch Motor"), wIconCreatePixMap(switchmedit_xpm), LEVEL0_50, IC_CANCEL|IC_POPUP, ACCL_SWITCHMOTOR2, (void*)SWITCHMOTOR_EDIT );
- AddMenuButton( menu, CmdSwitchMotor, "cmdSwitchMotorDelete", _("Delete Switch Motor"), wIconCreatePixMap(switchmdel_xpm), LEVEL0_50, IC_CANCEL|IC_POPUP, ACCL_SWITCHMOTOR3, (void*)SWITCHMOTOR_DELETE );
- ButtonGroupEnd();
+ switchmotorPointSense[0] = '\0';
+ AddMenuButton( menu, CmdSwitchMotorCreate, "cmdSwitchMotorCreate",
+ _("Switch Motor"), wIconCreatePixMap( switchm_xpm ),
+ LEVEL0_50, IC_STICKY|IC_POPUP2, ACCL_SWITCHMOTOR1,
+ NULL );
ParamRegister( &switchmotorPG );
}
-#endif
+EXPORT void CheckDeleteSwitchmotor(track_p t)
+{
+ track_p sm;
+ switchmotorData_p xx;
+
+ sm = FindSwitchMotor( t );
+ if (sm == NULL) return;
+ xx = GetswitchmotorData (sm);
+ NoticeMessage(_("Deleting Switch Motor %s"),_("Ok"),NULL,xx->name);
+ DeleteTrack (sm, FALSE);
+}
+
EXPORT void InitTrkSwitchMotor( void )
diff --git a/app/bin/ctext.c b/app/bin/ctext.c
index 0779ef5..525b55a 100644
--- a/app/bin/ctext.c
+++ b/app/bin/ctext.c
@@ -1,7 +1,5 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/ctext.c,v 1.4 2008-03-06 19:35:06 m_fischer Exp $
- *
- * TEXT
+/** \file ctext.c
+ * Text command
*
*/
@@ -26,11 +24,12 @@
#include "track.h"
#include "i18n.h"
-
track_p NewText( wIndex_t index, coOrd p, ANGLE_T angle, char * text, CSIZE_T textSize, wDrawColor color );
void LoadFontSizeList( wList_p, long );
void UpdateFontSizeList( long *, wList_p, wIndex_t );
+long GetFontSize(long);
+long GetFontSizeIndex(long size);
static wMenu_p textPopupM;
@@ -60,6 +59,11 @@ static paramData_t textPLs[] = {
};
static paramGroup_t textPG = { "text", 0, textPLs, sizeof textPLs/sizeof textPLs[0] };
+enum TEXT_POSITION
+{
+ POSITION_TEXT = 0,
+ SHOW_TEXT
+};
static void TextDlgUpdate(
paramGroup_p pg,
@@ -70,20 +74,20 @@ static void TextDlgUpdate(
switch (inx) {
case 0:
- if ( Dt.state == 1 ) {
+ if ( Dt.state == SHOW_TEXT) {
DrawString( &tempD, Dt.pos, 0.0, Dt.text, NULL, (FONTSIZE_T)Dt.size, Dt.color );
DrawLine( &tempD, Dt.cursPos0, Dt.cursPos1, 0, Dt.color );
}
UpdateFontSizeList( &Dt.size, (wList_p)textPLs[0].control, Dt.fontSizeInx );
/*wWinSetBusy( mainW, TRUE );*/
- if ( Dt.state == 1 ) {
+ if ( Dt.state == SHOW_TEXT) {
DrawTextSize( &mainD, Dt.text, NULL, Dt.size, TRUE, &size );
Dt.textLen = size.x;
}
DrawTextSize( &mainD, "X", NULL, Dt.size, TRUE, &size );
Dt.cursHeight = size.y;
/*wWinSetBusy( mainW, FALSE );*/
- if ( Dt.state == 1 ) {
+ if ( Dt.state == SHOW_TEXT) {
Dt.cursPos0.x = Dt.cursPos1.x = Dt.pos.x+Dt.textLen;
Dt.cursPos1.y = Dt.pos.y+Dt.cursHeight;
DrawLine( &tempD, Dt.cursPos0, Dt.cursPos1, 0, Dt.color );
@@ -105,24 +109,31 @@ static STATUS_T CmdText( wAction_t action, coOrd pos )
switch (action & 0xFF) {
case C_START:
- /* check if font size was updated by the preferences dialog */
- Dt.size = (CSIZE_T)wSelectedFontSize();
- Dt.state = 0;
+ Dt.state = POSITION_TEXT;
Dt.cursPos0 = Dt.cursPos1 = zero;
Dt.len = 0;
Dt.textLen = 0;
Dt.text[0] = '\0';
- if ( !inPlayback )
- wWinSetBusy( mainW, TRUE );
- DrawTextSize( &mainD, "X", NULL, Dt.size, TRUE, &size );
- Dt.cursHeight = size.y;
- if ( !inPlayback )
- wWinSetBusy( mainW, FALSE );
- if ( textPD.control==NULL ) {
- ParamCreateControls( &textPG, TextDlgUpdate );
+
+ if (textPD.control == NULL)
+ {
+ ParamCreateControls(&textPG, TextDlgUpdate);
+ LoadFontSizeList((wList_p)textPD.control, Dt.size);
+ ParamRegister(&textPG);
+ Dt.size = GetFontSize(Dt.fontSizeInx);
}
- LoadFontSizeList( (wList_p)textPD.control, Dt.size );
+ Dt.size = wSelectedFontSize();
+ Dt.fontSizeInx = GetFontSizeIndex(Dt.size);
+ ParamLoadControls(&textPG);
ParamGroupRecord( &textPG );
+
+ if (!inPlayback)
+ wWinSetBusy(mainW, TRUE);
+ DrawTextSize(&mainD, "X", NULL, Dt.size, TRUE, &size);
+ Dt.cursHeight = size.y;
+ if (!inPlayback)
+ wWinSetBusy(mainW, FALSE);
+
controls[0] = textPD.control;
controls[1] = colorPD.control;
controls[2] = 0;
@@ -142,7 +153,7 @@ static STATUS_T CmdText( wAction_t action, coOrd pos )
Dt.cursPos1.y += Dt.cursHeight;
DrawLine( &tempD, Dt.cursPos0, Dt.cursPos1, 0, Dt.color );
DrawString( &tempD, Dt.pos, 0.0, Dt.text, NULL, (FONTSIZE_T)Dt.size, Dt.color );
- Dt.state = 1;
+ Dt.state = SHOW_TEXT;
MainRedraw();
return C_CONTINUE;
case C_MOVE:
@@ -159,14 +170,13 @@ static STATUS_T CmdText( wAction_t action, coOrd pos )
case C_UP:
return C_CONTINUE;
case C_TEXT:
- if (Dt.state == 0) {
+ if (Dt.state == POSITION_TEXT) {
NoticeMessage( MSG_SEL_POS_FIRST, _("Ok"), NULL );
return C_CONTINUE;
}
DrawLine( &tempD, Dt.cursPos0, Dt.cursPos1, 0, Dt.color );
DrawString( &tempD, Dt.pos, 0.0, Dt.text, NULL, (FONTSIZE_T)Dt.size, Dt.color );
c = (unsigned char)(action >> 8);
-/*lprintf("C=%x\n", c);*/
switch (c) {
case '\b':
case 0xFF:
@@ -182,7 +192,7 @@ static STATUS_T CmdText( wAction_t action, coOrd pos )
t = NewText( 0, Dt.pos, Dt.angle, Dt.text, (CSIZE_T)Dt.size, Dt.color );
UndoEnd();
DrawNewTrack(t);
- Dt.state = 0;
+ Dt.state = POSITION_TEXT;
InfoSubstituteControls( NULL, NULL );
return C_TERMINATE;
default:
@@ -204,18 +214,18 @@ static STATUS_T CmdText( wAction_t action, coOrd pos )
}
return C_CONTINUE;
case C_CANCEL:
- if (Dt.state != 0) {
+ if (Dt.state != POSITION_TEXT) {
//DrawString( &tempD, Dt.pos, 0.0, Dt.text, NULL, (FONTSIZE_T)Dt.size, Dt.color );
//DrawLine( &tempD, Dt.cursPos0, Dt.cursPos1, 0, Dt.color );
- Dt.state = 0;
+ Dt.state = POSITION_TEXT;
}
InfoSubstituteControls( NULL, NULL );
MainRedraw();
return C_TERMINATE;
case C_OK:
- if (Dt.state != 0) {
+ if (Dt.state != POSITION_TEXT) {
DrawLine( &tempD, Dt.cursPos0, Dt.cursPos1, 0, Dt.color );
- Dt.state = 0;
+ Dt.state = POSITION_TEXT;
if (Dt.len) {
UndoStart( _("Create Text"), "newText - OK" );
t = NewText( 0, Dt.pos, Dt.angle, Dt.text, (CSIZE_T)Dt.size, Dt.color );
@@ -228,7 +238,7 @@ static STATUS_T CmdText( wAction_t action, coOrd pos )
return C_TERMINATE;
case C_FINISH:
- if (Dt.state != 0 && Dt.len > 0)
+ if (Dt.state != POSITION_TEXT && Dt.len > 0)
CmdText( C_OK, pos );
else
CmdText( C_CANCEL, pos );
@@ -251,7 +261,6 @@ void InitCmdText( wMenu_p menu )
wMenuPushCreate( textPopupM, "", _("Fonts..."), 0, (wMenuCallBack_p)SelectFont, NULL );
Dt.size = (CSIZE_T)wSelectedFontSize();
Dt.color = wDrawColorBlack;
- ParamRegister( &textPG );
}
void InitTrkText( void )
diff --git a/app/bin/cundo.c b/app/bin/cundo.c
index 1d17503..13d7af0 100644
--- a/app/bin/cundo.c
+++ b/app/bin/cundo.c
@@ -507,7 +507,7 @@ static track_p * FindParent( track_p trk, int lineNum )
{
track_p *ptrk;
ptrk = &to_first;
- while ( 1 ) {
+ while ( 1 ) {
if ( *ptrk == trk )
return ptrk;
if (*ptrk == NULL)
diff --git a/app/bin/custom.c b/app/bin/custom.c
index cbde60b..766dbd8 100644
--- a/app/bin/custom.c
+++ b/app/bin/custom.c
@@ -135,7 +135,10 @@ BOOL_T Initialize( void )
InitTrkDraw();
InitTrkNote();
InitTrkBlock();
- InitTrkSwitchMotor();
+ InitTrkSwitchMotor();
+ InitTrkSignal();
+ InitTrkControl();
+ InitTrkSensor();
InitCarDlg();
memset( message, 0, sizeof message );
diff --git a/app/bin/custom.h b/app/bin/custom.h
index 3987c16..b8ab213 100644
--- a/app/bin/custom.h
+++ b/app/bin/custom.h
@@ -94,6 +94,9 @@ void InitTrkTurnout( void );
void InitTrkTurntable( void );
void InitTrkBlock( void );
void InitTrkSwitchMotor( void );
+void InitTrkSignal ( void );
+void InitTrkControl ( void );
+void InitTrkSensor ( void );
void InitCmdCurve( wMenu_p menu );
void InitCmdHelix( wMenu_p menu );
diff --git a/app/bin/dcontmgm.c b/app/bin/dcontmgm.c
new file mode 100644
index 0000000..45fec89
--- /dev/null
+++ b/app/bin/dcontmgm.c
@@ -0,0 +1,312 @@
+/** \file dcontmgm.c
+ * Manage layout control elements
+ */
+
+/* -*- C -*- ****************************************************************
+ *
+ * System :
+ * Module :
+ * Created By : Robert Heller
+ * Created : Thu Jan 5 10:52:12 2017
+ * Last Modified : <170411.1447>
+ *
+ * Description
+ *
+ * Control Element Mangment. Control Elements are elements related to
+ * layout control: Blocks (occupency detection), Switchmotors (actuators
+ * to "throw" turnouts), and (eventually) signals. These elements don't
+ * relate to "physical" items on the layout, but instead refer to the
+ * elements used by the layout control software. These elements contain
+ * "scripts", which are really just textual items that provide information
+ * for the layout control software and provide a bridge between physical
+ * layout elements (like tracks or turnouts) and the layout control
+ * software. These textual items could be actual software code or could
+ * be LCC Events (for I/O device elements on a LCC network) or DCC
+ * addresses for stationary decoders, etc. XTrkCAD does not impose any
+ * sort of syntax or format -- that is left up to other software that might
+ * load and parse the XTrkCAD layout file. All the XTrkCAD does is provide
+ * a unified place for this information to be stored and to provide a
+ * mapping (association) between this control information and the layout
+ * itself.
+ *
+ *
+ * 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 "track.h"
+#include <errno.h>
+#include "i18n.h"
+
+#ifdef WINDOWS
+#include <io.h>
+#define F_OK (0)
+#define W_OK (2)
+#define access _access
+#endif
+
+/*****************************************************************************
+ *
+ * Control List Management
+ *
+ */
+
+static void ControlEdit( void * action );
+static void ControlDelete( void * action );
+static void ControlDone( void * action );
+static wPos_t controlListWidths[] = { 18, 100, 150 };
+static const char * controlListTitles[] = { "", N_("Name"),
+ N_("Tracks") };
+static paramListData_t controlListData = { 10, 400, 3, controlListWidths, controlListTitles };
+static paramData_t controlPLs[] = {
+#define I_CONTROLLIST (0)
+#define controlSelL ((wList_p)controlPLs[I_CONTROLLIST].control)
+ { PD_LIST, NULL, "inx", PDO_DLGRESETMARGIN|PDO_DLGRESIZE, &controlListData, NULL, BL_MANY },
+#define I_CONTROLEDIT (1)
+ { PD_BUTTON, (void*)ControlEdit, "edit", PDO_DLGCMDBUTTON, NULL, N_("Edit") },
+#define I_CONTROLDEL (2)
+ { PD_BUTTON, (void*)ControlDelete, "delete", 0, NULL, N_("Delete") },
+ } ;
+static paramGroup_t controlPG = { "contmgm", 0, controlPLs, sizeof controlPLs/sizeof controlPLs[0] };
+
+
+typedef struct {
+ contMgmCallBack_p proc;
+ void * data;
+ wIcon_p icon;
+ } contMgmContext_t, *contMgmContext_p;
+
+static BOOL_T AnyHILIGHT = FALSE;
+
+static void ControlDlgUpdate(
+ paramGroup_p pg,
+ int inx,
+ void *valueP )
+{
+ contMgmContext_p context = NULL;
+ wIndex_t selcnt = wListGetSelectedCount( (wList_p)controlPLs[0].control );
+ wIndex_t linx, lcnt;
+
+ if ( inx != I_CONTROLLIST ) return;
+ lcnt = wListGetCount( (wList_p)controlPLs[0].control );
+ AnyHILIGHT = FALSE;
+ for (linx=0;
+ linx < lcnt;
+ linx++ ) {
+ if (wListGetItemSelected( (wList_p)controlPLs[0].control, linx ) == TRUE) {
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, linx );
+ context->proc( CONTMGM_DO_HILIGHT, context->data );
+ AnyHILIGHT = TRUE;
+ } else {
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, linx );
+ context->proc( CONTMGM_UN_HILIGHT, context->data );
+ }
+ }
+ ParamControlActive( &controlPG, I_CONTROLEDIT, selcnt>0 );
+ ParamControlActive( &controlPG, I_CONTROLDEL, selcnt>0 );
+}
+
+static void ControlEdit( void * action )
+{
+ contMgmContext_p context = NULL;
+ wIndex_t selcnt = wListGetSelectedCount( (wList_p)controlPLs[0].control );
+ wIndex_t inx, cnt;
+
+ if ( selcnt != 1 )
+ return;
+ cnt = wListGetCount( (wList_p)controlPLs[0].control );
+ for ( inx=0;
+ inx<cnt && wListGetItemSelected( (wList_p)controlPLs[0].control, inx ) != TRUE;
+ inx++ );
+ if ( inx >= cnt )
+ return;
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, inx );
+ if ( context == NULL )
+ return;
+ context->proc( CONTMGM_DO_EDIT, context->data );
+ context->proc( CONTMGM_GET_TITLE, context->data );
+ wListSetValues( controlSelL, inx, message, context->icon, context );
+}
+
+
+static void ControlDelete( void * action )
+{
+ wIndex_t selcnt = wListGetSelectedCount( (wList_p)controlPLs[0].control );
+ wIndex_t inx, cnt;
+ contMgmContext_p context = NULL;
+
+ if ( selcnt <= 0 )
+ return;
+ if ( (!NoticeMessage2( 1, _("Are you sure you want to delete the %d control element(s)"), _("Yes"), _("No"), selcnt ) ) )
+ return;
+ cnt = wListGetCount( (wList_p)controlPLs[0].control );
+ UndoStart( _("Control Elements"), "delete" );
+ for ( inx=0; inx<cnt; inx++ ) {
+ if ( !wListGetItemSelected( (wList_p)controlPLs[0].control, inx ) )
+ continue;
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, inx );
+ context->proc( CONTMGM_DO_DELETE, context->data );
+ MyFree( context );
+ wListDelete( controlSelL, inx );
+ inx--;
+ cnt--;
+ }
+ UndoEnd();
+ DoChangeNotification( CHANGE_PARAMS );
+}
+
+static void ControlDone( void * action )
+{
+ contMgmContext_p context = NULL;
+ wIndex_t linx, lcnt;
+
+ if (AnyHILIGHT) {
+ lcnt = wListGetCount( (wList_p)controlPLs[0].control );
+ for (linx=0;
+ linx < lcnt;
+ linx++ ) {
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, linx );
+ context->proc( CONTMGM_UN_HILIGHT, context->data );
+ }
+ }
+ wHide( controlPG.win );
+}
+
+
+EXPORT void ContMgmLoad(
+ wIcon_p icon,
+ contMgmCallBack_p proc,
+ void * data )
+{
+ contMgmContext_p context;
+ context = MyMalloc( sizeof *context );
+ context->proc = proc;
+ context->data = data;
+ context->icon = icon;
+ context->proc( CONTMGM_GET_TITLE, context->data );
+ wListAddValue( controlSelL, message, icon, context );
+}
+
+
+static void LoadControlMgmList( void )
+{
+ wIndex_t curInx, cnt=0;
+ long tempL;
+ contMgmContext_p context;
+ contMgmContext_t curContext;
+
+ curInx = wListGetIndex( controlSelL );
+ curContext.proc = NULL;
+ curContext.data = NULL;
+ curContext.icon = NULL;
+ if ( curInx >= 0 ) {
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, curInx );
+ if ( context != NULL )
+ curContext = *context;
+ }
+ cnt = wListGetCount( controlSelL );
+ for ( curInx=0; curInx<cnt; curInx++ ) {
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, curInx );
+ if ( context )
+ MyFree( context );
+ }
+ curInx = wListGetIndex( controlSelL );
+ wControlShow( (wControl_p)controlSelL, FALSE );
+ wListClear( controlSelL );
+
+ BlockMgmLoad();
+ SwitchmotorMgmLoad();
+ SignalMgmLoad();
+ ControlMgmLoad();
+ SensorMgmLoad();
+
+#ifdef LATER
+ curInx = 0;
+ cnt = wListGetCount( controlSelL );
+ if ( curContext.proc != NULL ) {
+ for ( curInx=0; curInx<cnt; curInx++ ) {
+ context = (contMgmContext_p)wListGetItemContext( controlSelL, curInx );
+ if ( context &&
+ context->proc == curContext.proc &&
+ context->data == curContext.data )
+ break;
+ }
+ }
+ if ( curInx >= cnt )
+ curInx = (cnt>0?0:-1);
+
+ wListSetIndex( controlSelL, curInx );
+ tempL = curInx;
+#endif
+ tempL = -1;
+ ControlDlgUpdate( &controlPG, I_CONTROLLIST, &tempL );
+ wControlShow( (wControl_p)controlSelL, TRUE );
+}
+
+
+static void ContMgmChange( long changes )
+{
+ if (changes) {
+ if (changed) {
+ changed = 1;
+ checkPtMark = 1;
+ }
+ }
+ if ((changes&CHANGE_PARAMS) == 0 ||
+ controlPG.win == NULL || !wWinIsVisible(controlPG.win) )
+ return;
+
+ LoadControlMgmList();
+}
+
+
+
+static void DoControlMgr( void * junk )
+{
+ if (controlPG.win == NULL) {
+ ParamCreateDialog( &controlPG, MakeWindowTitle(_("Manage Layout Control Elements")), _("Done"), ControlDone, NULL, TRUE, NULL, F_RESIZE|F_RECALLSIZE|F_BLOCK, ControlDlgUpdate );
+ } else {
+ wListClear( controlSelL );
+ }
+ /*ParamLoadControls( &controlPG );*/
+ /*ParamGroupRecord( &controlPG );*/
+ LoadControlMgmList();
+ wShow( controlPG.win );
+}
+
+
+EXPORT addButtonCallBack_t ControlMgrInit( void )
+{
+ ParamRegister( &controlPG );
+ /*ParamRegister( &contMgmContentsPG );*/
+ RegisterChangeNotification( ContMgmChange );
+ return &DoControlMgr;
+}
diff --git a/app/bin/dprmfile.c b/app/bin/dprmfile.c
index 18b0cbe..e9cfc80 100644
--- a/app/bin/dprmfile.c
+++ b/app/bin/dprmfile.c
@@ -26,7 +26,7 @@
#include <stdint.h>
-#define PARAM_SUBDIR ("\\params")
+#define PARAM_SUBDIR FILE_SEP_CHAR "params"
/****************************************************************************
*
diff --git a/app/bin/draw.c b/app/bin/draw.c
index c04373c..92814e0 100644
--- a/app/bin/draw.c
+++ b/app/bin/draw.c
@@ -1154,7 +1154,7 @@ EXPORT void GetRoomSize( coOrd * froomSize )
}
-static void MapRedraw( void )
+EXPORT void MapRedraw( void )
{
if (inPlaybackQuit)
return;
diff --git a/app/bin/draw.h b/app/bin/draw.h
index aedc2b6..db8d91a 100644
--- a/app/bin/draw.h
+++ b/app/bin/draw.h
@@ -174,6 +174,7 @@ void GetRoomSize( coOrd * );
void DoRedraw( void );
void SetMainSize( void );
void MainRedraw( void );
+void MapRedraw( void );
void DrawMarkers( void );
void DrawMapBoundingBox( BOOL_T );
void DrawTicks( drawCmd_p, coOrd );
diff --git a/app/bin/dxfformat.c b/app/bin/dxfformat.c
new file mode 100644
index 0000000..4e1c775
--- /dev/null
+++ b/app/bin/dxfformat.c
@@ -0,0 +1,368 @@
+/** \file dxfformat.c
+* Formating of DXF commands and parameters
+*/
+
+/* XTrkCad - Model Railroad CAD
+* Copyright (C)2017 Martin Fischer
+*
+* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include <dynstring.h>
+#include "dxfformat.h"
+
+extern char *sProdNameUpper;
+extern long units; /**< meaning is 0 = English, 1 = metric */
+
+static char *dxfDimensionDefaults[][3] = { /**< default values for dimensions, English, metric and DXF variable name */
+ { "1.0", "25.0", "$DIMTXT" },
+ { "0.8", "20.0", "$DIMASZ"}
+};
+
+/**
+* Build and format layer name. The name is created by appending the layer number
+* to the basic layer name.
+*
+* \param result OUT buffer for result
+* \param name IN base part of name
+* \param layer IN layer number
+*/
+
+void DxfLayerName(DynString *result, char *name, int layer)
+{
+ DynStringPrintf(result, DXF_INDENT "8\n%s%d\n", name, layer);
+}
+
+/**
+* Build and format a position. If it specifies a point the value
+* is assumed to be in inches and will be converted to millimeters
+* if the metric system is active.
+* If it is an angle (group codes 50 to 59) it is not converted.
+*
+* \param result OUT buffer for result
+* \param type IN type of position following DXF specs
+* \param value IN position
+*/
+
+void DxfFormatPosition(DynString *result, int type, double value)
+{
+ if (units == 1)
+ {
+ if( type < 50 || type > 58 )
+ value *= 25.4;
+ }
+
+ DynStringPrintf(result, DXF_INDENT "%d\n%0.6f\n", type, value);
+}
+
+/**
+* Build and format the line style definition
+*
+* \param result OUT buffer for result
+* \param type IN line style TRUE for dashed, FALSE for solid lines
+*/
+
+void DxfLineStyle(DynString *result, int isDashed)
+{
+ DynStringPrintf(result, DXF_INDENT "6\n%s\n",
+ (isDashed ? "DASHED" : "CONTINUOUS"));
+}
+
+/**
+* Build and format layer name. The name is created by appending the layer number
+* to the basic layer name. The result is appended to the existing result buffer.
+*
+* \param output OUT buffer for result
+* \param basename IN base part of name
+* \param layer IN layer number
+*/
+
+static void
+DxfAppendLayerName(DynString *output, int layer)
+{
+ DynString formatted = NaS;
+ DynStringMalloc(&formatted, 0);
+ DxfLayerName(&formatted, sProdNameUpper, layer);
+ DynStringCatStr(output, &formatted);
+ DynStringFree(&formatted);
+}
+
+/**
+* Build and format a position. The result is appended to the existing result buffer.
+*
+* \param output OUT buffer for result
+* \param type IN type of position following DXF specs
+* \param value IN position
+*/
+
+static void
+DxfAppendPosition(DynString *output, int type, double value)
+{
+ DynString formatted = NaS;
+ DynStringMalloc(&formatted, 0);
+ DxfFormatPosition(&formatted, type, value);
+ DynStringCatStr(output, &formatted);
+ DynStringFree(&formatted);
+}
+
+/**
+* Build and format the line style definition. The result is appended to the existing result buffer.
+*
+* \param result OUT buffer for result
+* \param type IN line style TRUE for dashed, FALSE for solid lines
+*/
+
+static void
+DxfAppendLineStyle(DynString *output, int style)
+{
+ DynString formatted = NaS;
+ DynStringMalloc(&formatted, 0);
+ DxfLineStyle(&formatted, style);
+ DynStringCatStr(output, &formatted);
+ DynStringFree(&formatted);
+}
+
+/**
+* Format a complete LINE command after DXF spec
+*
+* \param result OUT buffer for the completed command
+* \param layer IN number part of the layer
+* \param x0, y0 IN first endpoint
+* \param x1, y1 IN second endpoint
+* \param style IN line style, TRUE for dashed, FALSE for continuous
+*/
+
+void
+DxfLineCommand(DynString *result, int layer, double x0,
+ double y0, double x1, double y1, int style)
+{
+ DynStringCatCStr(result, DXF_INDENT "0\nLINE\n");
+ DxfAppendLayerName(result, layer);
+ DxfAppendPosition(result, 10, x0);
+ DxfAppendPosition(result, 20, y0);
+ DxfAppendPosition(result, 11, x1);
+ DxfAppendPosition(result, 21, y1);
+ DxfAppendLineStyle(result, style);
+}
+
+/**
+* Format a complete CIRCLE command after DXF spec
+*
+* \param result OUT buffer for the completed command
+* \param layer IN number part of the layer
+* \param x, y IN center point
+* \param r IN radius
+* \param style IN line style, TRUE for dashed, FALSE for continuous
+*/
+
+void
+DxfCircleCommand(DynString *result, int layer, double x,
+ double y, double r, int style)
+{
+ DynStringCatCStr(result, DXF_INDENT "0\nCIRCLE\n");
+ DxfAppendPosition(result, 10, x);
+ DxfAppendPosition(result, 20, y);
+ DxfAppendPosition(result, 40, r);
+ DxfAppendLayerName(result, layer);
+ DxfAppendLineStyle(result, style);
+}
+
+/**
+* Format a complete ARC command after DXF spec
+*
+* \param result OUT buffer for the completed command
+* \param layer IN number part of the layer
+* \param x, y IN center point
+* \param r IN radius
+* \param a0 IN starting angle
+* \param a1 IN ending angle
+* \param style IN line style, TRUE for dashed, FALSE for continuous
+*/
+
+void
+DxfArcCommand(DynString *result, int layer, double x, double y,
+ double r, double a0, double a1, int style)
+{
+ DynStringCatCStr(result, DXF_INDENT "0\nARC\n");
+ DxfAppendPosition(result, 10, x);
+ DxfAppendPosition(result, 20, y);
+ DxfAppendPosition(result, 40, r);
+ DxfAppendPosition(result, 50, a0);
+ DxfAppendPosition(result, 51, a0+a1);
+ DxfAppendLayerName(result, layer);
+ DxfAppendLineStyle(result, style);
+}
+
+/**
+* Format a complete TEXT command after DXF spec
+*
+* \param result OUT buffer for the completed command
+* \param layer IN number part of the layer
+* \param x, y IN text position
+* \param size IN font size
+* \param text IN text
+*/
+
+void
+DxfTextCommand(DynString *result, int layer, double x,
+ double y, double size, char *text)
+{
+ DynStringCatCStr(result, DXF_INDENT "0\nTEXT\n");
+ DynStringCatCStrs(result, DXF_INDENT "1\n", text, "\n", NULL);
+ DxfAppendPosition(result, 10, x);
+ DxfAppendPosition(result, 20, y);
+ DxfAppendPosition(result, 40, size/72.0);
+ DxfAppendLayerName(result, layer);
+}
+
+/**
+ * Append the header lines needed to define the measurement system. This includes the
+ * definition of the measurement system (metric or English) vie the $MEASUREMENT variable
+ * and the units i.e. inches for English and mm for metric.
+ *
+ * \PARAM result OUT buffer for the completed command
+ */
+
+void
+DxfUnits(DynString *result)
+{
+ char *value;
+ DynStringCatCStr(result, DXF_INDENT "9\n$MEASUREMENT\n 70\n");
+
+ if (units == 1) {
+ value = "1\n";
+ } else {
+ value = "0\n";
+ }
+
+ DynStringCatCStr(result, value);
+ DynStringCatCStr(result, DXF_INDENT "9\n$INSUNITS\n 70\n");
+
+ if (units == 1) {
+ value = "4\n";
+ } else {
+ value = "1\n";
+ }
+
+ DynStringCatCStr(result, value);
+}
+
+/**
+* Define a size of dimensions. The default values are taken from
+* static array dxfDimensionDefaults
+*
+* \PARAM result OUT the completed command is appended to this buffer
+* \PARAM dimension IN dimension variable to set
+*/
+
+void
+DxfDimensionSize(DynString *result, enum DXF_DIMENSIONS dimension )
+{
+ DynString formatted;
+ DynStringMalloc(&formatted, 0);
+
+ DynStringPrintf(&formatted,
+ DXF_INDENT "9\n%s\n 40\n%s\n",
+ dxfDimensionDefaults[dimension][2],
+ dxfDimensionDefaults[dimension][units]);
+
+ DynStringCatStr(result, &formatted);
+ DynStringFree(&formatted);
+}
+
+/**
+* Create the complete prologue for a DXF file. Includes the header section,
+* a table for line styles and a table for layers.
+*
+* \param result OUT buffer for the completed command
+* \param layerCount IN count of defined layers
+* \param x0, y0 IN minimum (left bottom) position
+* \param x1, y1 IN maximum (top right) position
+*/
+
+void
+DxfPrologue(DynString *result, int layerCount, double x0, double y0, double x1,
+ double y1)
+{
+ int i;
+ DynString layer = NaS;
+ DynStringMalloc(&layer, 0);
+ DynStringCatCStr(result, "\
+ 0\nSECTION\n\
+ 2\nHEADER\n\
+ 9\n$ACADVER\n 1\nAC1015\n");
+ DxfUnits(result);
+ DxfDimensionSize(result, DXF_DIMTEXTSIZE);
+ DxfDimensionSize(result, DXF_DIMARROWSIZE);
+
+ DynStringCatCStr(result, " 9\n$EXTMIN\n");
+ DxfAppendPosition(result, 10, x0);
+ DxfAppendPosition(result, 20, y0);
+ DynStringCatCStr(result, " 9\n$EXTMAX\n");
+ DxfAppendPosition(result, 10, x1);
+ DxfAppendPosition(result, 20, y1);
+ DynStringCatCStr(result, "\
+ 9\n$TEXTSTYLE\n 7\nSTANDARD\n\
+ 0\nENDSEC\n\
+ 0\nSECTION\n\
+ 2\nTABLES\n\
+ 0\nTABLE\n\
+ 2\nLTYPE\n\
+ 0\nLTYPE\n 2\nCONTINUOUS\n 70\n0\n\
+ 3\nSolid line\n\
+ 72\n65\n 73\n0\n 40\n0\n\
+ 0\nLTYPE\n 2\nDASHED\n 70\n0\n\
+ 3\n__ __ __ __ __ __ __ __ __ __ __ __ __ __ __\n\
+ 72\n65\n 73\n2\n 40\n0.15\n 49\n0.1\n 49\n-0.05\n\
+ 0\nLTYPE\n 2\nDOT\n 70\n0\n\
+ 3\n...............................................\n\
+ 72\n65\n 73\n2\n 40\n0.1\n 49\n0\n 49\n-0.05\n\
+ 0\nENDTAB\n\
+ 0\nTABLE\n\
+ 2\nLAYER\n\
+ 70\n0\n");
+
+ for (i = 0; i < layerCount; i++) {
+ DynStringPrintf(&layer,
+ DXF_INDENT"0\nLAYER\n 2\n%s%d\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n",
+ sProdNameUpper, i + 1);
+ DynStringCatStr(result, &layer);
+ }
+
+ DynStringCatCStr(result, "\
+ 0\nENDTAB\n\
+ 0\nENDSEC\n\
+ 0\nSECTION\n\
+ 2\nENTITIES\n");
+}
+
+/**
+* Create the file footer for a DXF file. Closes the open section and places
+* an end-of-file marker
+*
+* \param result OUT buffer for the completed command
+*/
+
+void
+DxfEpilogue(DynString *result)
+{
+ DynStringCatCStr(result, DXF_INDENT "0\nENDSEC\n" DXF_INDENT "0\nEOF\n");
+}
diff --git a/app/bin/dxfformat.h b/app/bin/dxfformat.h
new file mode 100644
index 0000000..88db568
--- /dev/null
+++ b/app/bin/dxfformat.h
@@ -0,0 +1,26 @@
+#ifndef HAVE_DXFFORMAT_H
+#define HAVE_DXFFORMAT_H
+
+enum DXF_DIMENSIONS
+{
+ DXF_DIMTEXTSIZE,
+ DXF_DIMARROWSIZE
+};
+
+void DxfLayerName(DynString *result, char *name, int layer);
+void DxfFormatPosition(DynString *result, int type, double value);
+void DxfLineStyle(DynString *result, int isDashed);
+
+void DxfLineCommand(DynString *result, int layer, double x0, double yo, double x1, double y1, int style);
+void DxfCircleCommand(DynString *result, int layer, double x, double y, double r, int style);
+void DxfArcCommand(DynString *result, int layer, double x, double y, double r, double a0, double a1, int style);
+void DxfTextCommand(DynString *result, int layer, double x, double y, double size, char *text);
+void DxfUnits(DynString *result);
+void DxfDimensionSize(DynString *result, enum DXF_DIMENSIONS dimension);
+
+void DxfPrologue(DynString *result, int layerCount, double x0, double y0, double x1, double y1);
+void DxfEpilogue(DynString *result);
+#define DXF_INDENT " "
+
+#endif // !HAVE_DXFFORMAT_H
+
diff --git a/app/bin/dxfoutput.c b/app/bin/dxfoutput.c
new file mode 100644
index 0000000..91a822f
--- /dev/null
+++ b/app/bin/dxfoutput.c
@@ -0,0 +1,230 @@
+/** \file dxfoutput.c
+ * Exporting DXF files
+*/
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#ifdef WINDOWS
+ #include <io.h>
+ #include <windows.h>
+ #if _MSC_VER >=1400
+ #define strdup _strdup
+ #endif
+#else
+ #include <errno.h>
+#endif
+
+#include <xtrkcad-config.h>
+#include <locale.h>
+#include <assert.h>
+#include "track.h"
+#include "i18n.h"
+#include <dynstring.h>
+
+#include "dxfformat.h"
+
+static struct wFilSel_t * exportDXFFile_fs;
+
+static void DxfLine(
+ drawCmd_p d,
+ coOrd p0,
+ coOrd p1,
+ wDrawWidth width,
+ wDrawColor color)
+{
+ DynString command = NaS;
+ DynStringMalloc(&command, 100);
+ DxfLineCommand(&command,
+ curTrackLayer + 1,
+ p0.x, p0.y,
+ p1.x, p1.y,
+ ((d->options&DC_DASH) != 0));
+ fputs(DynStringToCStr(&command), (FILE *)d->d);
+ DynStringFree(&command);
+}
+
+static void DxfArc(
+ drawCmd_p d,
+ coOrd p,
+ DIST_T r,
+ ANGLE_T angle0,
+ ANGLE_T angle1,
+ BOOL_T drawCenter,
+ wDrawWidth width,
+ wDrawColor color)
+{
+ DynString command = NaS;
+ DynStringMalloc(&command, 100);
+ angle0 = NormalizeAngle(90.0-(angle0+angle1));
+
+ if (angle1 >= 360.0) {
+ DxfCircleCommand(&command,
+ curTrackLayer + 1,
+ p.x,
+ p.y,
+ r,
+ ((d->options&DC_DASH) != 0));
+ } else {
+ DxfArcCommand(&command,
+ curTrackLayer + 1,
+ p.x,
+ p.y,
+ r,
+ angle0,
+ angle1,
+ ((d->options&DC_DASH) != 0));
+ }
+
+ fputs(DynStringToCStr(&command), (FILE *)d->d);
+ DynStringFree(&command);
+}
+
+static void DxfString(
+ drawCmd_p d,
+ coOrd p,
+ ANGLE_T a,
+ char * s,
+ wFont_p fp,
+ FONTSIZE_T fontSize,
+ wDrawColor color)
+{
+ DynString command = NaS;
+ DynStringMalloc(&command, 100);
+ DxfTextCommand(&command,
+ curTrackLayer + 1,
+ p.x,
+ p.y,
+ fontSize,
+ s);
+ fputs(DynStringToCStr(&command), (FILE *)d->d);
+ DynStringFree(&command);
+}
+
+static void DxfBitMap(
+ drawCmd_p d,
+ coOrd p,
+ wDrawBitMap_p bm,
+ wDrawColor color)
+{
+}
+
+static void DxfFillPoly(
+ drawCmd_p d,
+ int cnt,
+ coOrd * pts,
+ wDrawColor color)
+{
+ int inx;
+
+ for (inx=1; inx<cnt; inx++) {
+ DxfLine(d, pts[inx-1], pts[inx], 0, color);
+ }
+
+ DxfLine(d, pts[cnt-1], pts[0], 0, color);
+}
+
+static void DxfFillCircle(drawCmd_p d, coOrd center, DIST_T radius,
+ wDrawColor color)
+{
+ DxfArc(d, center, radius, 0.0, 360, FALSE, 0, color);
+}
+
+
+static drawFuncs_t dxfDrawFuncs = {
+ 0,
+ DxfLine,
+ DxfArc,
+ DxfString,
+ DxfBitMap,
+ DxfFillPoly,
+ DxfFillCircle
+};
+
+static drawCmd_t dxfD = {
+ NULL, &dxfDrawFuncs, 0, 1.0, 0.0, {0.0,0.0}, {0.0,0.0}, Pix2CoOrd, CoOrd2Pix, 100.0
+};
+
+static int DoExportDXFTracks(
+ int cnt,
+ char ** fileName,
+ void * data)
+{
+ time_t clock;
+ char *oldLocale;
+ DynString command = NaS;
+ FILE * dxfF;
+
+ assert(fileName != NULL);
+ assert(cnt == 1);
+
+ DynStringMalloc(&command, 100);
+
+ SetCurrentPath(DXFPATHKEY, fileName[ 0 ]);
+ dxfF = fopen(fileName[0], "w");
+
+ if (dxfF==NULL) {
+ NoticeMessage(MSG_OPEN_FAIL, _("Continue"), NULL, "DXF", fileName[0],
+ strerror(errno));
+ return FALSE;
+ }
+
+ oldLocale = SaveLocale("C");
+ wSetCursor(wCursorWait);
+ time(&clock);
+
+ DxfPrologue(&command, 10, 0.0, 0.0, mapD.size.x, mapD.size.y);
+ fputs(DynStringToCStr(&command), dxfF);
+ dxfD.d = (wDraw_p)dxfF;
+
+ DrawSelectedTracks(&dxfD);
+
+ DynStringClear(&command);
+ DxfEpilogue(&command);
+ fputs(DynStringToCStr(&command), dxfF);
+
+ fclose(dxfF);
+ RestoreLocale(oldLocale);
+ Reset();
+ wSetCursor(wCursorNormal);
+ return TRUE;
+}
+
+/**
+* Create and show the dialog for selected the DXF export filename
+*/
+
+void DoExportDXF(void)
+{
+ //if (selectedTrackCount <= 0) {
+ // ErrorMessage(MSG_NO_SELECTED_TRK);
+ // return;
+ //}
+ assert(selectedTrackCount > 0);
+
+ if (exportDXFFile_fs == NULL)
+ exportDXFFile_fs = wFilSelCreate(mainW, FS_SAVE, 0, _("Export to DXF"),
+ sDXFFilePattern, DoExportDXFTracks, NULL);
+
+ wFilSelect(exportDXFFile_fs, curDirName);
+}
+
+
diff --git a/app/bin/fileio.c b/app/bin/fileio.c
index 23216b8..da0de68 100644
--- a/app/bin/fileio.c
+++ b/app/bin/fileio.c
@@ -1,6 +1,6 @@
/** \file fileio.c
- * Loading and saving files. Handles trackplans as well as DXF export.
- */
+ * Loading and saving files. Handles trackplans, XTrackCAD exports and cut/paste
+*/
/* XTrkCad - Model Railroad CAD
* Copyright (C) 2005 Dave Bullis
@@ -1039,7 +1039,7 @@ static int SaveTracks(
wMenuListAdd( fileList_ml, 0, nameOfFile, MyStrdup(fileName[ 0 ]) );
checkPtMark = changed = 0;
- if (curPathName != fileName[ 0 ])
+ if (strcmp(curPathName, fileName[ 0 ]))
strcpy( curPathName, fileName[ 0 ] );
curFileName = FindName( curPathName );
@@ -1053,13 +1053,14 @@ static int SaveTracks(
EXPORT void DoSave( doSaveCallBack_p after )
{
doAfterSave = after;
- if (curPathName[0] == 0) {
+ if (curPathName[0] == '\0') {
if (saveFile_fs == NULL)
saveFile_fs = wFilSelCreate( mainW, FS_SAVE, 0, _("Save Tracks"),
sSourceFilePattern, SaveTracks, NULL );
wFilSelect( saveFile_fs, curDirName );
} else {
- SaveTracks( 1, &curFileName, NULL );
+ char *temp = curPathName;
+ SaveTracks( 1, &temp, NULL );
}
SetWindowTitle();
}
@@ -1224,7 +1225,6 @@ EXPORT int LoadCheckpoint( void )
static struct wFilSel_t * exportFile_fs;
static struct wFilSel_t * importFile_fs;
-static struct wFilSel_t * exportDXFFile_fs;
static int ImportTracks(
@@ -1330,187 +1330,6 @@ EXPORT void DoExport( void )
}
-static FILE * dxfF;
-static void DxfLine(
- drawCmd_p d,
- coOrd p0,
- coOrd p1,
- wDrawWidth width,
- wDrawColor color )
-{
- fprintf(dxfF, " 0\nLINE\n" );
- fprintf(dxfF, " 8\n%s%d\n", sProdNameUpper, curTrackLayer+1 );
- fprintf(dxfF, " 10\n%0.6f\n 20\n%0.6f\n 11\n%0.6f\n 21\n%0.6f\n",
- p0.x, p0.y, p1.x, p1.y );
- fprintf(dxfF, " 6\n%s\n", (d->options&DC_DASH)?"DASHED":"CONTINUOUS" );
-}
-
-static void DxfArc(
- drawCmd_p d,
- coOrd p,
- DIST_T r,
- ANGLE_T angle0,
- ANGLE_T angle1,
- BOOL_T drawCenter,
- wDrawWidth width,
- wDrawColor color )
-{
- angle0 = NormalizeAngle(90.0-(angle0+angle1));
- if (angle1 >= 360.0) {
- fprintf(dxfF, " 0\nCIRCLE\n" );
- fprintf(dxfF, " 10\n%0.6f\n 20\n%0.6f\n 40\n%0.6f\n",
- p.x, p.y, r );
- } else {
- fprintf(dxfF, " 0\nARC\n" );
- fprintf(dxfF, " 10\n%0.6f\n 20\n%0.6f\n 40\n%0.6f\n 50\n%0.6f\n 51\n%0.6f\n",
- p.x, p.y, r, angle0, angle0+angle1 );
- }
- fprintf(dxfF, " 8\n%s%d\n", sProdNameUpper, curTrackLayer+1 );
- fprintf(dxfF, " 6\n%s\n", (d->options&DC_DASH)?"DASHED":"CONTINUOUS" );
-}
-
-static void DxfString(
- drawCmd_p d,
- coOrd p,
- ANGLE_T a,
- char * s,
- wFont_p fp,
- FONTSIZE_T fontSize,
- wDrawColor color )
-{
- fprintf(dxfF, " 0\nTEXT\n" );
- fprintf(dxfF, " 1\n%s\n", s );
- fprintf(dxfF, " 8\n%s%d\n", sProdNameUpper, curTrackLayer+1 );
- fprintf(dxfF, " 10\n%0.6f\n 20\n%0.6f\n", p.x, p.y );
- fprintf(dxfF, " 40\n%0.6f\n", fontSize/72.0 );
-}
-
-static void DxfBitMap(
- drawCmd_p d,
- coOrd p,
- wDrawBitMap_p bm,
- wDrawColor color )
-{
-}
-
-static void DxfFillPoly(
- drawCmd_p d,
- int cnt,
- coOrd * pts,
- wDrawColor color )
-{
- int inx;
- for (inx=1; inx<cnt; inx++) {
- DxfLine( d, pts[inx-1], pts[inx], 0, color );
- }
- DxfLine( d, pts[cnt-1], pts[0], 0, color );
-}
-
-static void DxfFillCircle( drawCmd_p d, coOrd center, DIST_T radius, wDrawColor color )
-{
- DxfArc( d, center, radius, 0.0, 360, FALSE, 0, color );
-}
-
-
-static drawFuncs_t dxfDrawFuncs = {
- 0,
- DxfLine,
- DxfArc,
- DxfString,
- DxfBitMap,
- DxfFillPoly,
- DxfFillCircle };
-
-static drawCmd_t dxfD = {
- NULL, &dxfDrawFuncs, 0, 1.0, 0.0, {0.0,0.0}, {0.0,0.0}, Pix2CoOrd, CoOrd2Pix, 100.0 };
-
-static int DoExportDXFTracks(
- int cnt,
- char ** fileName,
- void * data )
-{
- time_t clock;
- char *oldLocale;
-
- assert( fileName != NULL );
- assert( cnt == 1 );
-
- SetCurrentPath( DXFPATHKEY, fileName[ 0 ] );
- dxfF = fopen( fileName[0], "w" );
- if (dxfF==NULL) {
- NoticeMessage( MSG_OPEN_FAIL, _("Continue"), NULL, "DXF", fileName[0], strerror(errno) );
- return FALSE;
- }
-
- oldLocale = SaveLocale( "C" );
- wSetCursor( wCursorWait );
- time(&clock);
- fprintf(dxfF,"\
- 0\nSECTION\n\
- 2\nHEADER\n\
- 9\n$ACADVER\n 1\nAC1009\n\
- 9\n$EXTMIN\n 10\n%0.6f\n 20\n%0.6f\n\
- 9\n$EXTMAX\n 10\n%0.6f\n 20\n%0.6f\n\
- 9\n$TEXTSTYLE\n 7\nSTANDARD\n\
- 0\nENDSEC\n\
- 0\nSECTION\n\
- 2\nTABLES\n\
- 0\nTABLE\n\
- 2\nLTYPE\n\
- 0\nLTYPE\n 2\nCONTINUOUS\n 70\n0\n\
- 3\nSolid line\n\
- 72\n65\n 73\n0\n 40\n0\n\
- 0\nLTYPE\n 2\nDASHED\n 70\n0\n\
- 3\n__ __ __ __ __ __ __ __ __ __ __ __ __ __ __\n\
- 72\n65\n 73\n2\n 40\n0.15\n 49\n0.1\n 49\n-0.05\n\
- 0\nLTYPE\n 2\nDOT\n 70\n0\n\
- 3\n...............................................\n\
- 72\n65\n 73\n2\n 40\n0.1\n 49\n0\n 49\n-0.05\n\
- 0\nENDTAB\n\
- 0\nTABLE\n\
- 2\nLAYER\n\
- 70\n0\n\
- 0\nLAYER\n 2\n%s1\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s2\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s3\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s4\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s5\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s6\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s7\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s8\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s9\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nLAYER\n 2\n%s10\n 6\nCONTINUOUS\n 62\n7\n 70\n0\n\
- 0\nENDTAB\n\
- 0\nENDSEC\n\
- 0\nSECTION\n\
- 2\nENTITIES\n\
-",
- 0.0, 0.0, mapD.size.x, mapD.size.y,
- sProdNameUpper, sProdNameUpper, sProdNameUpper, sProdNameUpper, sProdNameUpper,
- sProdNameUpper, sProdNameUpper, sProdNameUpper, sProdNameUpper, sProdNameUpper );
- DrawSelectedTracks( &dxfD );
- fprintf(dxfF," 0\nENDSEC\n");
- fprintf(dxfF," 0\nEOF\n");
- fclose(dxfF);
- RestoreLocale( oldLocale );
- Reset();
- wSetCursor( wCursorNormal );
- return TRUE;
-}
-
-
-void DoExportDXF( void )
-{
- if (selectedTrackCount <= 0) {
- ErrorMessage( MSG_NO_SELECTED_TRK );
- return;
- }
- if (exportDXFFile_fs == NULL)
- exportDXFFile_fs = wFilSelCreate( mainW, FS_SAVE, 0, _("Export to DXF"),
- sDXFFilePattern, DoExportDXFTracks, NULL );
-
- wFilSelect( exportDXFFile_fs, curDirName );
-}
EXPORT BOOL_T EditCopy( void )
{
diff --git a/app/bin/helphelper.c b/app/bin/helphelper.c
new file mode 100644
index 0000000..013ff0a
--- /dev/null
+++ b/app/bin/helphelper.c
@@ -0,0 +1,146 @@
+/** \file helphelper.c
+ * use OSX Help system
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2015 Martin Fischer
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#import <CoreFoundation/CoreFoundation.h>
+#import <Carbon/Carbon.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdint.h>
+
+#define HELPCOMMANDPIPE "/tmp/helppipe"
+#define EXITCOMMAND "##exit##"
+
+
+OSStatus MyGoToHelpPage (CFStringRef pagePath, CFStringRef anchorName)
+{
+ CFBundleRef myApplicationBundle = NULL;
+ CFStringRef myBookName = NULL;
+ OSStatus err = noErr;
+ printf("HelpHelper: Started to look for help\n");
+
+ myApplicationBundle = CFBundleGetMainBundle();
+ if (myApplicationBundle == NULL) {
+ printf("HelpHelper: Error - No Application Bundle\n");
+ err = fnfErr;
+ return err;
+ }
+ printf("HelpHelper: Application Bundle Found\n");
+
+ myBookName = CFBundleGetValueForInfoDictionaryKey(
+ myApplicationBundle,
+ CFSTR("CFBundleHelpBookName"));
+ if (myBookName == NULL) {
+ myBookName = CFStringCreateWithCString(NULL, "XTrackCAD Help", kCFStringEncodingMacRoman);
+ printf("HelpHelper: Defaulting to 'XTrackCAD Help'\n" );
+ err = fnfErr;
+ return err;
+ }
+ printf("HelpHelper: BookName dictionary name %s found\n",CFStringGetCStringPtr(myBookName, kCFStringEncodingMacRoman));
+
+ if (CFGetTypeID(myBookName) != CFStringGetTypeID()) {
+ printf("HelpHelper: Error - BookName is not a string\n" );
+ err = paramErr;
+ }
+
+ if (err == noErr) {
+ err = AHGotoPage (myBookName, pagePath, anchorName);
+ if (err != noErr) {
+ printf("HelpHelper: Error in AHGoToPage('%s','%s')\n",CFStringGetCStringPtr(myBookName, kCFStringEncodingMacRoman), CFStringGetCStringPtr(pagePath, kCFStringEncodingMacRoman));
+ }
+ }
+
+ return err;
+
+};
+
+int displayHelp(char* name) {
+ CFStringRef str = CFStringCreateWithCString(NULL,name,kCFStringEncodingMacRoman);
+ OSStatus err = MyGoToHelpPage(str, NULL);
+ if (err != noErr) printf("HelpHelper: MyGoToHelpPage had error %d\n", err);
+ return err;
+
+};
+
+int
+main( int argc, char **argv )
+{
+ int handleOfPipe = 0;
+ char buffer[ 100 ];
+ char issue[ 100 ];
+
+ int len;
+ int finished = 0;
+ int numBytes = 0;
+ int numBytes2 = 0;
+
+ printf( "HelpHelper: starting!\n" );
+
+ handleOfPipe = open( HELPCOMMANDPIPE, O_RDONLY );
+ if( handleOfPipe ) {
+ printf( "HelpHelper: opened pipe for reading\n" );
+ while( !finished ) {
+ printf( "HelpHelper: reading from pipe...\n" );
+ numBytes = read( handleOfPipe, &len, sizeof( int ));
+
+ if( numBytes > 0 )
+ printf( "HelpHelper: read %d bytes\n", numBytes );
+ if( numBytes == sizeof(int)) {
+ printf( "HelpHelper: Expecting %d bytes\n", len );
+ numBytes2 = read( handleOfPipe, buffer, len + 1 );
+ if (numBytes2 > 0)
+ printf( "HelpHelper: Display help on: %s\n", buffer );
+
+ if( !strcmp(buffer, EXITCOMMAND )) {
+ finished = 1;
+ } else {
+ if (displayHelp(buffer) != 0)
+ printf( "HelpHelper: Error\n");
+ }
+ }
+ if( numBytes <= 0 ) {
+ printf( "HelpHelper: exiting on pipe error\n" );
+ exit( 1 );
+ }
+ }
+ } else {
+ printf( "HelpHelper: Could not open pipe for reading\n" );
+ }
+
+ printf( "HelpHelper: exiting!" );
+
+ exit( 0 );
+};
+
+
+
+
diff --git a/app/bin/misc.c b/app/bin/misc.c
index 77b46a2..b506f98 100644
--- a/app/bin/misc.c
+++ b/app/bin/misc.c
@@ -713,8 +713,8 @@ EXPORT void SelectFont( void )
*
*/
-#define COMMAND_MAX (160)
-#define BUTTON_MAX (160)
+#define COMMAND_MAX (170)
+#define BUTTON_MAX (170)
#define NUM_CMDMENUS (4)
#ifdef LATER
@@ -2210,8 +2210,11 @@ static void CreateMenus( void )
cmdGroup = BG_CONTROL;
InitCmdBlock( addM );
- InitCmdSwitchMotor( addM );
-
+ InitCmdSwitchMotor( addM );
+ InitCmdSignal( addM );
+ InitCmdControl( addM );
+ InitCmdSensor( addM );
+
/*
* CHANGE MENU
*/
@@ -2321,7 +2324,8 @@ static void CreateMenus( void )
InitNewTurn( wMenuMenuCreate( manageM, "cmdTurnoutNew", _("Tur&nout Designer...") ) );
- MiscMenuItemCreate( manageM, NULL, "cmdGroup", _("&Group"), ACCL_GROUP, (void*)(wMenuCallBack_p)DoGroup, IC_SELECTED, (void *)0 );
+ MiscMenuItemCreate( manageM, NULL, "smdContmgm", _("Layout &Control Elements"), ACCL_CONTMGM,(void*)ControlMgrInit(),0,(void*) 0);
+ MiscMenuItemCreate( manageM, NULL, "cmdGroup", _("&Group"), ACCL_GROUP, (void*)(wMenuCallBack_p)DoGroup, IC_SELECTED, (void *)0 );
MiscMenuItemCreate( manageM, NULL, "cmdUngroup", _("&Ungroup"), ACCL_UNGROUP, (void*)(wMenuCallBack_p)DoUngroup, IC_SELECTED, (void *)0 );
MiscMenuItemCreate( manageM, NULL, "cmdCustmgm", _("Custom defined parts..."), ACCL_CUSTMGM, (void*)CustomMgrInit(), 0, (void *)0 );
diff --git a/app/bin/misc.h b/app/bin/misc.h
index 7d3231e..1747189 100644
--- a/app/bin/misc.h
+++ b/app/bin/misc.h
@@ -318,6 +318,7 @@ addButtonCallBack_t OutputBitMapInit( void );
addButtonCallBack_t CustomMgrInit( void );
addButtonCallBack_t PriceListInit( void );
addButtonCallBack_t ParamFilesInit( void );
+addButtonCallBack_t ControlMgrInit ( void );
wIndex_t InitGrid( wMenu_p menu );
@@ -373,6 +374,18 @@ void CarCustMgmLoad();
BOOL_T CompoundCustomSave(FILE*);
BOOL_T CarCustomSave(FILE*);
+/* dcontmgm.c */
+#define CONTMGM_CAN_EDIT (1)
+#define CONTMGM_DO_EDIT (2)
+#define CONTMGM_CAN_DELETE (3)
+#define CONTMGM_DO_DELETE (4)
+#define CONTMGM_GET_TITLE (5)
+#define CONTMGM_DO_HILIGHT (6)
+#define CONTMGM_UN_HILIGHT (7)
+
+typedef int (*contMgmCallBack_p) (int, void *);
+void ContMgmLoad (wIcon_p,contMgmCallBack_p,void *);
+
/* doption.c */
long GetDistanceFormat( void );
@@ -382,10 +395,21 @@ void ClearCars( void );
void CarDlgAddProto( void );
void CarDlgAddDesc( void );
void AttachTrains( void );
-#endif
+
/* cblock.c */
void InitCmdBlock( wMenu_p menu );
-
+void BlockMgmLoad( void );
/* cswitchmotor.c */
void InitCmdSwitchMotor( wMenu_p menu );
+void SwitchmotorMgmLoad( void );
+/* csignal.c */
+void InitCmdSignal ( wMenu_p menu );
+void SignalMgmLoad ( void );
+/* ccontrol.c */
+void ControlMgmLoad ( void );
+void InitCmdControl ( wMenu_p menu );
+/* csensor.c */
+void SensorMgmLoad ( void );
+void InitCmdSensor ( wMenu_p menu );
+#endif
diff --git a/app/bin/misc2.c b/app/bin/misc2.c
index 1013179..2c7644b 100644
--- a/app/bin/misc2.c
+++ b/app/bin/misc2.c
@@ -45,7 +45,7 @@
#include "compound.h"
#include "i18n.h"
-EXPORT long units = 0;
+EXPORT long units = 0; /**< measurement units: 0 = English, 1 = metric */
EXPORT long checkPtInterval = 10;
EXPORT DIST_T curScaleRatio;
diff --git a/app/bin/param.c b/app/bin/param.c
index f5ae69f..27c558f 100644
--- a/app/bin/param.c
+++ b/app/bin/param.c
@@ -72,96 +72,6 @@ static int hotspotOffsetY = 19;
static int log_paramLayout;
-#ifdef LATER
-/*****************************************************************************
- *
- * Colors
- *
- */
-
-typedef struct {
- long rgb;
- char * name;
- wDrawColor color;
- } colorTab_t[];
-
-static colorTab_t colorTab = {
- { wRGB( 0, 0, 0), N_("Black") },
-
- { wRGB( 0, 0,128), N_("Dark Blue") },
- { wRGB( 70,130,180), N_("Steel Blue") },
- { wRGB( 65,105,225), N_("Royal Blue") },
- { wRGB( 0, 0,255), N_("Blue") },
- { wRGB( 0,191,255), N_("Deep Sky Blue") },
- { wRGB(125,206,250), N_("Light Sky Blue") },
- { wRGB(176,224,230), N_("Powder Blue") },
-
- { wRGB( 0,128,128), N_("Dark Aqua") },
- { wRGB(127,255,212), N_("Aquamarine") },
- { wRGB( 0,255,255), N_("Aqua") },
-
- { wRGB( 0,128, 0), N_("Dark Green") },
- { wRGB( 34,139, 34), N_("Forest Green") },
- { wRGB( 50,205, 50), N_("Lime Green") },
- { wRGB( 0,255, 0), N_("Green") },
- { wRGB(124,252, 0), N_("Lawn Green") },
- { wRGB(152,251,152), N_("Pale Green") },
-
- { wRGB(128,128, 0), N_("Dark Yellow") },
- { wRGB(255,127, 80), N_("Coral") },
- { wRGB(255,165, 0), N_("Orange") },
- { wRGB(255,215, 0), N_("Gold") },
- { wRGB(255,255, 0), N_("Yellow") },
-
- { wRGB(139, 69, 19), N_("Saddle Brown") },
- { wRGB(165, 42, 42), N_("Brown") },
- { wRGB(210,105, 30), N_("Chocolate") },
- { wRGB(188,143,143), N_("Rosy Brown") },
- { wRGB(210,180,140), N_("Tan") },
- { wRGB(245,245,220), N_("Beige") },
-
-
- { wRGB(128, 0, 0), N_("Dark Red") },
- { wRGB(255, 99, 71), N_("Tomato") },
- { wRGB(255, 0, 0), N_("Red") },
- { wRGB(255,105,180), N_("Hot Pink") },
- { wRGB(255,192,203), N_("Pink") },
-
- { wRGB(128, 0,128), N_("Dark Purple") },
- { wRGB(176, 48, 96), N_("Maroon") },
- { wRGB(160, 32,240), N_("Purple2") },
- { wRGB(255, 0,255), N_("Purple") },
- { wRGB(238,130,238), N_("Violet") },
-
- { wRGB( 64, 64, 64), N_("Dark Gray") },
- { wRGB(128,128,128), N_("Gray") },
- { wRGB(192,192,192), N_("Light Gray") } };
-static wIcon_p colorTabBitMaps[ sizeof colorTab/sizeof colorTab[0] ];
-#include "bitmaps/square10.xbm"
-
-static BOOL_T colorTabInitted = FALSE;
-
-static void InitColorTab( void )
-{
- wIndex_t inx;
- for ( inx=0; inx<COUNT(colorTab); inx++ )
- colorTab[inx].color = wDrawFindColor( colorTab[inx].rgb );
- colorTabInitted = TRUE;
-}
-
-
-static wIndex_t ColorTabLookup( wDrawColor color )
-{
- wIndex_t inx;
- if (!colorTabInitted)
- InitColorTab();
- for (inx = 0; inx < sizeof colorTab/sizeof colorTab[0]; inx++ )
- if (colorTab[inx].color == color)
- return inx;
- return 0;
-}
-#endif
-
/*****************************************************************************
*
*
@@ -613,10 +523,6 @@ EXPORT void ParamLoadControl(
p->oldD.l = *(wIndex_t*)p->valueP;
break;
case PD_COLORLIST:
-#ifdef LATER
- inx = ColorTabLookup( *(wDrawColor*)p->valueP );
- wListSetIndex( (wList_p)p->control, inx );
-#endif
wColorSelectButtonSetColor( (wButton_p)p->control, *(wDrawColor*)p->valueP );
p->oldD.dc = *(wDrawColor*)p->valueP;
break;
@@ -736,10 +642,6 @@ EXPORT long ParamUpdate(
break;
case PD_COLORLIST:
dc = wColorSelectButtonGetColor( (wButton_p)p->control );
-#ifdef LATER
- inx = wListGetIndex( (wList_p)p->control );
- dc = colorTab[inx].color;
-#endif
if (dc != p->oldD.dc) {
p->oldD.dc = dc;
if ( /*(p->option&PDO_NOUPDUPD)==0 &&*/ p->valueP)
@@ -830,10 +732,6 @@ EXPORT void ParamLoadData(
break;
case PD_COLORLIST:
*(wDrawColor*)p->valueP = wColorSelectButtonGetColor( (wButton_p)p->control );
-#ifdef LATER
- inx = wListGetIndex( (wList_p)p->control );
- *(wDrawColor*)p->valueP = colorTab[inx].color;
-#endif
break;
case PD_FLOAT:
if (p->option & PDO_DIM) {
@@ -1380,7 +1278,7 @@ static void ParamIntegerPush( const char * val, void * dp )
while ( isspace((unsigned char)*val)) val++;
valL = strtol( val, &cp, 10 );
- wControlSetBalloon( p->control, 0, -5, NULL );
+ //wControlSetBalloon( p->control, 0, -5, NULL );
if ( val == cp ) {
wControlSetBalloon( p->control, 0, -5, _("Invalid Number") );
return;
@@ -1432,7 +1330,7 @@ static void ParamFloatPush( const char * val, void * dp )
if (p->option & PDO_ANGLE)
valF = NormalizeAngle( (angleSystem==ANGLE_POLAR)?valF:-valF );
}
- wControlSetBalloon( p->control, 0, -5, NULL );
+ // wControlSetBalloon( p->control, 0, -5, NULL );
if ( !valid ) {
wControlSetBalloon( p->control, 0, -5, decodeErrorStr );
return;
@@ -1500,22 +1398,7 @@ static void ParamListPush( wIndex_t inx, const char * val, wIndex_t op, void * d
p->group->changeProc( p->group, p-p->group->paramPtr, &valL );
}
break;
-#ifdef LATER
- case PD_COLORLIST:
- dc = colorTab[inx].color;
- rgb = wDrawGetRGB( dc );
- if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr) {
- fprintf( recordF, "PARAMETER %s %s %ld\n",
- p->group->nameStr, p->nameStr, rgb );
- fflush( recordF );
- }
- if ( (p->option&PDO_NOPSHUPD)==0 && p->valueP)
- *(wDrawColor*)(p->valueP) = dc;
- if ( (p->option&PDO_NOPSHACT)==0 && p->group->changeProc ) {
- ; /* COLOR NOP */
- }
- break;
-#endif
+
default:
;
}
@@ -1644,10 +1527,6 @@ EXPORT void ParamChange( paramData_p p )
case PD_COLORLIST:
if (recordF && (p->option&PDO_NORECORD)==0 && p->group->nameStr && p->nameStr)
fprintf( recordF, "PARAMETER %s %s %ld\n", p->group->nameStr, p->nameStr, rgb );
-#ifdef LATER
- if ( p->control && (p->option&PDO_NOCONTUPD) == 0 )
- wColorSelectButtonSetColor( (wButton_p)p->control, wDrawFindRGB(rgb) );
-#endif
break;
case PD_FLOAT:
tmpR = *(FLOAT_T*)p->valueP;
@@ -1842,13 +1721,6 @@ static void ParamPlayback( char * line )
dc = wDrawFindColor( rgb );
if ( p->control)
wColorSelectButtonSetColor( (wButton_p)p->control, dc );
-#ifdef LATER
- valL = ColorTabLookup( dc );
- if (p->control) {
- wListSetIndex( (wList_p)p->control, (wIndex_t)valL );
- wFlush();
- }
-#endif
if (p->valueP)
*(wDrawColor*)p->valueP = dc;
if (pg->changeProc) {
diff --git a/app/bin/track.c b/app/bin/track.c
index 30ea186..bbbf48a 100644
--- a/app/bin/track.c
+++ b/app/bin/track.c
@@ -923,7 +923,7 @@ EXPORT void ResolveIndex( void )
{
track_p trk;
EPINX_T ep;
- TRK_ITERATE(trk)
+ TRK_ITERATE(trk) {
for (ep=0; ep<trk->endCnt; ep++)
if (trk->endPt[ep].index >= 0) {
trk->endPt[ep].track = FindTrack( trk->endPt[ep].index );
@@ -931,6 +931,9 @@ EXPORT void ResolveIndex( void )
NoticeMessage( MSG_RESOLV_INDEX_BAD_TRK, _("Continue"), NULL, trk->index, ep, trk->endPt[ep].index );
}
}
+ ResolveBlockTrack (trk);
+ ResolveSwitchmotorTurnout (trk);
+ }
AuditTracks( "readTracks" );
}
@@ -966,6 +969,8 @@ LOG( log_track, 4, ( "DeleteTrack(T%d)\n", GetTrkIndex(trk) ) )
ClrTrkElev( trk2 );
}
}
+ CheckDeleteSwitchmotor( trk );
+ CheckDeleteBlock( trk );
UndoDelete( trk );
MainRedraw();
trackCount--;
diff --git a/app/bin/track.h b/app/bin/track.h
index 81f5e4c..e26a47a 100644
--- a/app/bin/track.h
+++ b/app/bin/track.h
@@ -42,8 +42,6 @@
#include "misc.h"
-
-
extern TRKTYP_T T_NOTRACK;
struct track_t ;
@@ -650,5 +648,12 @@ void AddHotBarTurnouts( void );
void AddHotBarStructures( void );
void AddHotBarCarDesc( void );
+/* cblock.c */
+void CheckDeleteBlock( track_p t );
+void ResolveBlockTrack ( track_p trk );
+/* cswitchmotor.c */
+void CheckDeleteSwitchmotor( track_p t );
+void ResolveSwitchmotorTurnout ( track_p trk );
+
#endif
diff --git a/app/bin/unittest/CMakeLists.txt b/app/bin/unittest/CMakeLists.txt
new file mode 100644
index 0000000..b6d2bc5
--- /dev/null
+++ b/app/bin/unittest/CMakeLists.txt
@@ -0,0 +1,12 @@
+# build unit tests for the xtrkcad library
+
+add_executable(dxfformattest
+ dxfformattest.c
+ ../dxfformat.c
+ )
+
+target_link_libraries(dxfformattest
+ dynstring
+ ${LIBS})
+
+add_test(DXFOutputTest dxfformattest) \ No newline at end of file
diff --git a/app/bin/unittest/dxfformattest.c b/app/bin/unittest/dxfformattest.c
new file mode 100644
index 0000000..b797ad9
--- /dev/null
+++ b/app/bin/unittest/dxfformattest.c
@@ -0,0 +1,144 @@
+/** \file DynStringTest.c
+* Unit tests for the dxfformat module
+*/
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <dynstring.h>
+#include <dxfformat.h>
+
+char *sProdNameUpper = "XTRKCAD";
+long units;
+
+static void BasicFormatting(void **state)
+{
+ DynString string;
+ (void)state;
+
+ DynStringMalloc(&string, 0);
+
+ DxfLayerName(&string, sProdNameUpper, 0);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "8\nXTRKCAD0\n");
+
+ DxfLayerName(&string, sProdNameUpper, 99);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "8\nXTRKCAD99\n");
+
+ DxfFormatPosition(&string, 20, 1);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "20\n1.000000\n");
+
+ DxfFormatPosition(&string, 20, 1.23456789);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "20\n1.234568\n");
+
+ DxfFormatPosition(&string, 20, 1.23456712);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "20\n1.234567\n");
+}
+
+static void LineCommand(void **state)
+{
+ DynString string;
+ (void)state;
+
+ DynStringMalloc(&string, 0);
+
+ DxfLineCommand( &string, 0, 1.0, 2.0, 1.1, 2.2, 1);
+ assert_string_equal(DynStringToCStr(&string),
+ DXF_INDENT "0\nLINE\n 8\nXTRKCAD0\n 10\n1.000000\n 20\n2.000000\n 11\n1.100000\n 21\n2.200000\n 6\nDASHED\n");
+
+ DynStringFree(&string);
+}
+
+
+static void CircleCommand(void **state)
+{
+ DynString string;
+ (void)state;
+
+ DynStringMalloc(&string, 0);
+
+ DxfCircleCommand(&string, 0, 1.0, 2.0, 1.1, 1);
+ assert_string_equal(DynStringToCStr(&string),
+ DXF_INDENT "0\nCIRCLE\n 10\n1.000000\n 20\n2.000000\n 40\n1.100000\n 8\nXTRKCAD0\n 6\nDASHED\n");
+
+ DynStringFree(&string);
+}
+
+
+static void ArcCommand(void **state)
+{
+ DynString string;
+ (void)state;
+
+ DynStringMalloc(&string, 0);
+
+ DxfArcCommand(&string, 0, 1.0, 2.0, 1.1, 10.0, 180.0, 1);
+ assert_string_equal(DynStringToCStr(&string),
+ DXF_INDENT "0\nARC\n 10\n1.000000\n 20\n2.000000\n 40\n1.100000\n 50\n10.000000\n 51\n190.000000\n 8\nXTRKCAD0\n 6\nDASHED\n");
+
+ DynStringFree(&string);
+}
+
+#define TESTSTRING "This is a dxf test string"
+
+static void TextCommand(void **state)
+{
+ DynString string;
+ (void)state;
+
+ DynStringMalloc(&string, 0);
+
+ DxfTextCommand(&string, 0, 10.0, 12.0, 144.0, TESTSTRING);
+
+ assert_string_equal(DynStringToCStr(&string),
+ DXF_INDENT "0\nTEXT\n 1\n" TESTSTRING "\n 10\n10.000000\n 20\n12.000000\n 40\n2.000000\n 8\nXTRKCAD0\n");
+
+ DynStringFree(&string);
+}
+
+static void Units(void **state)
+{
+ DynString string;
+ (void)state;
+
+ DynStringMalloc(&string, 0);
+
+ /* test English units */
+ units = 0;
+ DxfUnits(&string);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "9\n$MEASUREMENT\n 70\n0\n" DXF_INDENT "9\n$INSUNITS\n 70\n1\n");
+ DxfFormatPosition(&string, 20, 1.23456789);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "20\n1.234568\n");
+
+ DynStringClear(&string);
+ DxfDimensionSize(&string, DXF_DIMTEXTSIZE);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "9\n$DIMTXT\n 40\n1.0\n");
+
+ /* test metric units */
+ units = 1;
+ DynStringClear(&string);
+ DxfUnits(&string);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "9\n$MEASUREMENT\n 70\n1\n" DXF_INDENT "9\n$INSUNITS\n 70\n4\n");
+ DxfFormatPosition(&string, 20, 1.23456789);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "20\n31.358024\n");
+
+ DynStringClear(&string);
+ DxfDimensionSize(&string, DXF_DIMTEXTSIZE);
+ assert_string_equal(DynStringToCStr(&string), DXF_INDENT "9\n$DIMTXT\n 40\n25.0\n");
+
+}
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(BasicFormatting),
+ cmocka_unit_test(LineCommand),
+ cmocka_unit_test(CircleCommand),
+ cmocka_unit_test(ArcCommand),
+ cmocka_unit_test(TextCommand),
+ cmocka_unit_test(Units)
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+} \ No newline at end of file