summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/FindCMocka.cmake51
-rw-r--r--CMakeLists.txt17
-rw-r--r--app/CMakeLists.txt2
-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
-rw-r--r--app/doc/CMakeLists.txt34
-rw-r--r--app/doc/addm.but131
-rw-r--r--app/doc/appendix.but41
-rw-r--r--app/doc/changem.but2
-rw-r--r--app/doc/drawm.but2
-rw-r--r--app/doc/editm.but1
-rw-r--r--app/doc/filem.but2
-rw-r--r--app/doc/helpm.but1
-rw-r--r--app/doc/hotbar.but1
-rw-r--r--app/doc/intro.but.in10
-rw-r--r--app/doc/linconf.but4
-rw-r--r--app/doc/macrom.but1
-rw-r--r--app/doc/managem.but35
-rw-r--r--app/doc/navigation.but1
-rw-r--r--app/doc/optionm.but1
-rw-r--r--app/doc/osxconf.but16
-rw-r--r--app/doc/png.d/bblock.pngbin0 -> 713 bytes
-rw-r--r--app/doc/png.d/bcontrol.pngbin0 -> 619 bytes
-rw-r--r--app/doc/png.d/block.pngbin0 -> 18245 bytes
-rw-r--r--app/doc/png.d/bsensor.pngbin0 -> 563 bytes
-rw-r--r--app/doc/png.d/bsignal.pngbin0 -> 581 bytes
-rw-r--r--app/doc/png.d/bswitchmotor.pngbin0 -> 679 bytes
-rw-r--r--app/doc/png.d/control.pngbin0 -> 12729 bytes
-rw-r--r--app/doc/png.d/lcemanager.pngbin0 -> 35289 bytes
-rw-r--r--app/doc/png.d/madd.pngbin3690 -> 7895 bytes
-rw-r--r--app/doc/png.d/mmanage.pngbin4860 -> 8632 bytes
-rw-r--r--app/doc/png.d/sensor.pngbin0 -> 11777 bytes
-rw-r--r--app/doc/png.d/signal.pngbin0 -> 30230 bytes
-rw-r--r--app/doc/png.d/switchmotor.pngbin0 -> 22300 bytes
-rw-r--r--app/doc/statusbar.but1
-rw-r--r--app/doc/upgrade.but3
-rw-r--r--app/doc/view_winm.but1
-rw-r--r--app/doc/warranty.but3
-rw-r--r--app/doc/xtrkcad_osx.css144
-rw-r--r--app/dynstring/CMakeLists.txt11
-rw-r--r--app/dynstring/dynstring.c457
-rw-r--r--app/dynstring/dynstring.h40
-rw-r--r--app/dynstring/unittest/CMakeLists.txt8
-rw-r--r--app/dynstring/unittest/DynStringTest.c108
-rw-r--r--app/help/genhelp.in15
-rw-r--r--app/help/xtrkcad.info16
-rw-r--r--app/i18n/de_DE.po165
-rw-r--r--app/i18n/fi.po2
-rw-r--r--app/i18n/pt_BR.po2
-rw-r--r--app/lib/CMakeLists.txt11
-rw-r--r--app/lib/Readme.md68
-rw-r--r--app/lib/Readme.txt1051
-rw-r--r--app/lib/astylerc8
-rw-r--r--app/lib/params/HO-Frateschi.xtp196
-rw-r--r--app/lib/params/HOn3-BlackStoneProTraxx.xtp21
-rw-r--r--app/lib/params/Lego-Track.xtp152
-rw-r--r--app/lib/params/S-MTH S-Trax.xtp156
-rw-r--r--app/lib/params/S-SHelper S-Trax.xtp200
-rw-r--r--app/lib/params/TT-Kuehn.xtp6
-rw-r--r--app/lib/params/TTi-AuhagenNG.xtp40
-rw-r--r--app/lib/params/TilligAdvTT.xtp627
-rw-r--r--app/lib/params/atl83ho.xtp8
-rw-r--r--app/lib/params/pecoho83.xtp271
-rw-r--r--app/lib/xtrkcad.desktop4
-rw-r--r--app/lib/xtrkcad.png (renamed from app/lib/icon.png)bin3803 -> 3803 bytes
-rw-r--r--app/lib/xtrkcad.xtq4
-rw-r--r--app/tools/halibut/bk_html.c185
-rw-r--r--app/tools/halibut/halibut.h1
-rw-r--r--app/tools/halibut/input.c3
-rw-r--r--app/wlib/gtklib/CMakeLists.txt56
-rw-r--r--app/wlib/gtklib/bitmap.c136
-rw-r--r--app/wlib/gtklib/boxes.c203
-rw-r--r--app/wlib/gtklib/button.c630
-rw-r--r--app/wlib/gtklib/color.c466
-rw-r--r--app/wlib/gtklib/control.c283
-rw-r--r--app/wlib/gtklib/droplist.c456
-rw-r--r--app/wlib/gtklib/dynarr.h5
-rw-r--r--app/wlib/gtklib/filesel.c43
-rw-r--r--app/wlib/gtklib/font.c403
-rw-r--r--app/wlib/gtklib/gtkbitmap.c85
-rw-r--r--app/wlib/gtklib/gtkbutton.c461
-rw-r--r--app/wlib/gtklib/gtkcolor.c476
-rw-r--r--app/wlib/gtklib/gtkdraw-cairo.c138
-rw-r--r--app/wlib/gtklib/gtkfont.c342
-rw-r--r--app/wlib/gtklib/gtkhelp.c733
-rw-r--r--app/wlib/gtklib/gtkint.h263
-rw-r--r--app/wlib/gtklib/gtklist.c1131
-rw-r--r--app/wlib/gtklib/gtkmenu.c873
-rw-r--r--app/wlib/gtklib/gtkmisc.c1210
-rw-r--r--app/wlib/gtklib/gtksimple.c366
-rw-r--r--app/wlib/gtklib/gtksingle.c645
-rw-r--r--app/wlib/gtklib/gtksplash.c142
-rw-r--r--app/wlib/gtklib/gtktext.c670
-rw-r--r--app/wlib/gtklib/gtkwindow.c856
-rw-r--r--app/wlib/gtklib/gtkxpm.c173
-rw-r--r--app/wlib/gtklib/help.c69
-rw-r--r--app/wlib/gtklib/ixhelp.c441
-rw-r--r--app/wlib/gtklib/lines.c150
-rw-r--r--app/wlib/gtklib/list.c547
-rw-r--r--app/wlib/gtklib/liststore.c267
-rw-r--r--app/wlib/gtklib/main.c107
-rw-r--r--app/wlib/gtklib/menu.c1084
-rw-r--r--app/wlib/gtklib/message.c168
-rw-r--r--app/wlib/gtklib/notice.c297
-rw-r--r--app/wlib/gtklib/osxhelp.c133
-rw-r--r--app/wlib/gtklib/pixbuf.c99
-rw-r--r--app/wlib/gtklib/png.c64
-rw-r--r--app/wlib/gtklib/print.c1000
-rw-r--r--app/wlib/gtklib/single.c335
-rw-r--r--app/wlib/gtklib/splash.c144
-rw-r--r--app/wlib/gtklib/square10.bmp8
-rw-r--r--app/wlib/gtklib/text.c590
-rw-r--r--app/wlib/gtklib/timer.c144
-rw-r--r--app/wlib/gtklib/tooltip.c255
-rw-r--r--app/wlib/gtklib/treeview.c530
-rw-r--r--app/wlib/gtklib/util.c672
-rw-r--r--app/wlib/gtklib/window.c936
-rw-r--r--app/wlib/gtklib/wpref.c128
-rw-r--r--app/wlib/include/wlib.h174
-rw-r--r--app/wlib/mswlib/mswedit.c2
-rw-r--r--app/wlib/mswlib/mswmisc.c2
-rw-r--r--distribution/osx/CMakeLists.txt51
-rw-r--r--distribution/osx/bundle/Info.plist.in4
-rw-r--r--distribution/osx/gtk-bundle/CMakeLists.txt20
-rw-r--r--distribution/osx/gtk-bundle/Drag-to-Copy-Arrow.pngbin0 -> 2171 bytes
-rw-r--r--distribution/osx/gtk-bundle/XTrackCAD-help/CMakeLists.txt14
-rw-r--r--distribution/osx/gtk-bundle/XTrackCAD-help/Contents/CMakeLists.txt5
-rw-r--r--distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/CMakeLists.txt12
-rw-r--r--distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/CMakeLists.txt10
-rw-r--r--distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/InfoPlist.strings2
-rw-r--r--distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/icon_16x16.pngbin0 -> 673 bytes
-rw-r--r--distribution/osx/gtk-bundle/XTrackCAD-help/info-xtrkcad-help.plist.in36
-rw-r--r--distribution/osx/gtk-bundle/gtk-bundle.README44
-rw-r--r--distribution/osx/gtk-bundle/info-xtrkcad.plist34
-rw-r--r--distribution/osx/gtk-bundle/info-xtrkcad.plist.in34
-rw-r--r--distribution/osx/gtk-bundle/toc.js67
-rwxr-xr-xdistribution/osx/gtk-bundle/xtrkcad-bundler.sh84
-rwxr-xr-xdistribution/osx/gtk-bundle/xtrkcad-launcher.sh214
-rw-r--r--distribution/osx/gtk-bundle/xtrkcad-logo.icnsbin0 -> 1337741 bytes
-rw-r--r--distribution/osx/gtk-bundle/xtrkcad-template.dmg.zipbin0 -> 3990654 bytes
-rw-r--r--distribution/osx/gtk-bundle/xtrkcad.bundle132
-rw-r--r--distribution/posix/CMakeLists.txt2
-rw-r--r--distribution/posix/xtrkcad.spec4
-rw-r--r--docs/doxygen/Doxyfile.in3
-rw-r--r--notes12
-rw-r--r--xtrkcad-config.h.in1
189 files changed, 18818 insertions, 11135 deletions
diff --git a/CMake/FindCMocka.cmake b/CMake/FindCMocka.cmake
new file mode 100644
index 0000000..e8a4e92
--- /dev/null
+++ b/CMake/FindCMocka.cmake
@@ -0,0 +1,51 @@
+# - Try to find CMocka
+# Once done this will define
+#
+# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
+#
+# Read-Only variables:
+# CMOCKA_FOUND - system has CMocka
+# CMOCKA_INCLUDE_DIR - the CMocka include directory
+# CMOCKA_LIBRARIES - Link these to use CMocka
+# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
+#
+#=============================================================================
+# Copyright (c) 2011-2012 Andreas Schneider <asn@cryptomilk.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+#
+
+find_path(CMOCKA_INCLUDE_DIR
+ NAMES
+ cmocka.h
+ PATHS
+ ${CMOCKA_ROOT_DIR}/include
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Andreas Schneider\\cmocka]/include"
+)
+
+find_library(CMOCKA_LIBRARY
+ NAMES
+ cmocka
+ PATHS
+ ${CMOCKA_ROOT_DIR}/lib
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Andreas Schneider\\cmocka]/lib"
+)
+
+if (CMOCKA_LIBRARY)
+ set(CMOCKA_LIBRARIES
+ ${CMOCKA_LIBRARIES}
+ ${CMOCKA_LIBRARY}
+ )
+endif (CMOCKA_LIBRARY)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARY CMOCKA_INCLUDE_DIR)
+
+# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
+mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARY CMOCKA_LIBRARIES) \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3db52bb..2f0a9a9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,10 @@
PROJECT(XTrkCAD)
+enable_testing()
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/app)
+# additional CMake modules can be found here
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake/")
# Setup high-level build options ...
IF(UNIX AND NOT APPLE)
@@ -71,6 +74,14 @@ IF(XTRKCAD_USE_PACKAGEMAKER)
ENDIF(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr")
ENDIF(XTRKCAD_USE_PACKAGEMAKER)
+# Find unit testing framework
+find_package(CMocka)
+if( CMOCKA_FOUND)
+ include_directories(${CMOCKA_INCLUDE_DIR})
+ set(LIBS ${LIBS} ${CMOCKA_LIBRARIES})
+ option( XTRKCAD_TESTING "Build unittests" ON)
+endif()
+
# Test for headers and libraries for portability ...
INCLUDE (CheckIncludeFiles)
@@ -78,9 +89,9 @@ CHECK_INCLUDE_FILES (malloc.h HAVE_MALLOC_H)
# Setup some global options for installation ...
SET(XTRKCAD_MAJOR_VERSION "4")
-SET(XTRKCAD_MINOR_VERSION "2")
-SET(XTRKCAD_RELEASE_VERSION "4")
-SET(XTRKCAD_VERSION_MODIFIER "a")
+SET(XTRKCAD_MINOR_VERSION "3")
+SET(XTRKCAD_RELEASE_VERSION "0")
+SET(XTRKCAD_VERSION_MODIFIER "")
SET(XTRKCAD_VERSION "${XTRKCAD_MAJOR_VERSION}.${XTRKCAD_MINOR_VERSION}.${XTRKCAD_RELEASE_VERSION}${XTRKCAD_VERSION_MODIFIER}")
IF(WIN32)
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index b237015..9a47f95 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -1,7 +1,9 @@
# "bin/i18n.h" is widely used
INCLUDE_DIRECTORIES(bin)
+include_directories(dynstring)
# Setup the rest of the build ...
+add_subdirectory(dynstring)
ADD_SUBDIRECTORY(wlib)
ADD_SUBDIRECTORY(tools)
ADD_SUBDIRECTORY(help)
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
diff --git a/app/doc/CMakeLists.txt b/app/doc/CMakeLists.txt
index dcee056..03ac14b 100644
--- a/app/doc/CMakeLists.txt
+++ b/app/doc/CMakeLists.txt
@@ -38,7 +38,11 @@ ADD_CUSTOM_TARGET(clean-html
# If we're using the GTK back-end, just generate "vanilla" HTML help files for use with gtkhtml
IF(XTRKCAD_USE_GTK)
- SET(HALIBUT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/linconf.but ${HALIBUT_SOURCES})
+ IF (APPLE)
+ SET(HALIBUT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/osxconf.but ${HALIBUT_SOURCES})
+ ELSE(APPLE)
+ SET(HALIBUT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/linconf.but ${HALIBUT_SOURCES})
+ ENDIF(APPLE)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/html/index.html
@@ -63,7 +67,31 @@ IF(XTRKCAD_USE_GTK)
INSTALL(
FILES xtrkcad_lin.css
DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/html
- )
+ )
+# Copy the help files to the Help bundle if Apple
+ IF (APPLE)
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/html/XTrackCAD.helpindex
+ DEPENDS help-html ${HALIBUT_SOURCES}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
+ COMMAND hiutil -Cf XTrackCAD.helpindex -gva -e "IndexPage.html" -e "toc.html" ${CMAKE_CURRENT_BINARY_DIR}/html
+ )
+
+ ADD_CUSTOM_TARGET(help-index ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/html/XTrackCAD.helpindex)
+
+ INSTALL(
+ DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/Contents/Resources/en.lproj
+ )
+ INSTALL(
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/png.d
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/Contents/Resources/en.lproj
+ )
+ INSTALL(
+ FILES xtrkcad_osx.css
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/Contents/Resources/en.lproj
+ )
+ ENDIF(APPLE)
# Otherwise, we're using the Win32 back-end, so generate a compiled HTML help file
ELSE(XTRKCAD_USE_GTK)
@@ -86,7 +114,7 @@ ELSE(XTRKCAD_USE_GTK)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/html/xtrkcad.chm
- DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}
)
ENDIF(XTRKCAD_USE_GTK)
diff --git a/app/doc/addm.but b/app/doc/addm.but
index 111b188..cee8896 100644
--- a/app/doc/addm.but
+++ b/app/doc/addm.but
@@ -6,8 +6,9 @@
\C{commandMenus} Command Menus
-\rule
+\cfg{html-local-head}{<meta name="AppleTitle" content="Command Menus" />}
+\rule
\H{addM}\i{Add Menu}
@@ -49,8 +50,25 @@ The \f{Add Menu} has all the actions related to adding track pieces to the layou
\dd \f{Turntable} - Place a turntable.
-\rule
+\u000
+
+\dd \f{Block} - Create, edit or delete a block.
+
+\u000
+
+\dd \f{Switchmotor} - Create, edit or delete a switchmotor.
+
+\u000
+
+\dd \f{Signal} - Create, edit or delete a signal.
+
+\u000
+\dd \f{Control} - Create a signal.
+
+\u000
+
+\dd \f{Sensor} - Create a sensor.
\S{cmdCircle} Circle Track
@@ -258,4 +276,111 @@ The \f{Modify command} (\K{cmdModify}) can be used to create turntable stall tra
The \f{Turntable Angle} control on the Preferences (\K{cmdPref}) dialog controls how closely you can place tracks connected to a turntable. If you want to create stall tracks every 7.5\u00B0, set the \f{Turntable Angle} control to 7.5 and place the track as close to each other as allowed. \e{XTrackCAD} makes sure they will be separated by the correct angle.
-\rule \ No newline at end of file
+\rule
+
+\S{cmdBlock} Block
+
+\G{png.d/bblock.png}
+
+A block is created by first selecting the track segments in the block and then
+selecting \f{Create Block} from either the Add menu \K{cmdAdd} or from the block menu on the
+hotbar. A block gets a name and a script. The name is only used for
+identification and the script is used by the layout control software. The
+script should provide whatever information is needed by the layout control
+software to determine block occupancy. This could be a code snippet to
+retrieve the state of the block occupancy or it could be the address of the
+sensor, etc.
+
+\G{png.d/block.png}
+
+The create block dialog has spaces for two text strings. One is the name and
+the other is a block occupancy script. The name identifies the block and the
+script is information used by the layout control software to detect block
+occupancy. The script could be a code snippet or I/O device address
+information, etc.
+
+\rule
+
+\S{cmdSwitchmotor} Switchmotor
+
+\G{png.d/bswitchmotor.png}
+
+A switchmotor is created by selecting \f{Create SwitchMotor} from either the Add
+menu \K{cmdAdd} or from the switchmotor menu on the hotbar and then clicking on a turnout.
+A switchmotor gets a name and three scripts. The name is only used for
+identification and the three scripts are used by the layout control software.
+The three scripts are for throwing the turnout to its "normal" position,
+throwing the turnout to its "reverse" position, and a script to read a point
+position sensor. These scripts could be code snippets or they could be
+addresses of I/O devices, etc.
+
+\G{png.d/switchmotor.png}
+
+The create switchmotor dialog has spaces for four text strings. One is the
+name and the other three are scripts for Normal, Reverse, and Point Sense. The
+name identifies the switchmotor and the scripts are information used by the
+layout control software to throw the turnout to the normal position, throw the
+turnout to the reverse position, and sense the point position. The scripts
+could be code snippets or I/O device address information, etc.
+
+\rule
+
+\S{cmdSignal} Signal
+
+\G{png.d/bsignal.png}
+
+A signal is created by selecting \f{Create Signal} from either the Add menu \K{cmdAdd} or
+from the hotbar. Use the mouse to select a location (left button) and then
+draging (left button down) the signal to set its orientation. Once the left
+button is released, a Create/Edit Signal dialog box is displayed, and you can
+fill in the signal's properties: name, fine tune the location and orientation,
+number of heads, and the aspects.
+
+\G{png.d/signal.png}
+
+The create/edit signal dialog has spaces for the name of the signal, its
+location and orientation, the number of heads (1, 2, or 3), and a list of
+aspects. Each aspect has a name and a script. The name could be a rule book
+name (Clear, Aproach, Stop, etc.) or the actual color(s) displayed (green,
+yellow, red, etc.). The script is just some information for the layout
+control software to actually effect the display of the aspect -- this could be
+the LCC event id to trigger the aspect or it could be a code snippet that
+causes the aspect to be displayed.
+
+\rule
+
+\S{cmdControl} Control
+
+\G{png.d/bControl.png}
+
+A control is created by selecting \f{Create Control} from either the Add menu \K{cmdAdd} or
+from the hotbar. Use the mouse to select a location (left button) and then
+dragging (left button down) the control to where you want it. Once the left
+button is released, a Create/Edit Control dialog box is displayed, and you can
+fill in the control's properties: name, fine tune the location, and the on and
+off scripts.
+
+\G{png.d/control.png}
+
+The create/edit control dialog has entry fields for the name of the control, its
+location, and a pair of scripts, one to turn the control on and one to turn
+the control off. The scripts are just some information for the layout control
+software to actually effect the state on the control (on or off).
+
+\rule
+
+\S{cmdSensor} Sensor
+
+\G{png.d/bSensor.png}
+
+A sensor is created by selecting \f{Create Sensor} from either the Add menu \K{cmdAdd} or
+from the hotbar. Use the mouse to select a location (left button) and then
+dragging (left button down) the sensor to where you want it. Once the left
+button is released, a Create/Edit Sensor dialog box is displayed, and you can
+fill in the sensor's properties: name, fine tune the location, and the script.
+
+\G{png.d/sensor.png}
+
+The create/edit sensor dialog has spaces for the name of the sensor, its
+location, and a script. The script is just some information for the layout
+control software to actually return the state of the sensor (on or off). \ No newline at end of file
diff --git a/app/doc/appendix.but b/app/doc/appendix.but
index 3155e38..2c16319 100644
--- a/app/doc/appendix.but
+++ b/app/doc/appendix.but
@@ -2,7 +2,7 @@
\#
\# The "\u000" command is used to format the output. These commands causes a blank line to appear between "bulleted" or "described" items.
\#
-
+\cfg{html-local-head}{<meta name="AppleTitle" content="Frequently Asked Questions" />}
\A{faqs} Frequently Asked Questions
@@ -209,6 +209,44 @@ Menu and sub-menu items are indicated by \e{File>Open}, which means select the \
\rule
+\H{controlElementScripts} Control Element Scripts and the Model RR System's Dispatcher
+
+Notes about control element scripts and the Model RR System's Dispatcher
+program in OpenLCB mode:
+
+When using the Model RR System's Dispatcher program in OpenLCB mode to create
+CTC panels, the panel elements can have their LCC event IDs automatically
+populated from the information in the XTrackCAD file, if the proper syntax is
+observed.
+
+A LCC event id is a 64-bit number, represented as eight pairs of hexadevimal
+digits (0-9, a-f/A-F) separated by periods (.). Each pair represents one 8-bit
+byte of the event id. This event id is either produced by a sensor or logic
+element or is consumed by a control/device or a logic element.
+
+For blocks the occupency script contains a pair of LCC event ids, separated by
+a colon (:). The first LCC event id is produced by the occupency detector
+when the train enters the block and the second LCC event id is produced by the
+occupency detector when the train leaves the block.
+
+For switchmotors the point sense script contains a pair of LCC event ids,
+separated by a colon (:). The first LCC event id is produced by the point
+sensor when the points are aligned in the "normal" position (typically aligned
+to the main) and the second LCC event id is produced by the point sensor when
+the points are aligned in the "reverse" position (typically aligned to the
+spur). The normal and reverse script each contain a signal LCC event id.
+These events are produced by the CTC Panel when the control point Code button
+is pressed (clicked) and are consumed by the switch motor.
+
+For signals, the aspect name is a space separated list of the color(s) of the
+signal heads from top to bottom and the aspect script is a LCC event id that
+is consumed to produce that aspect. Presumably, the LCC event id is produced
+by a logic element (presumably a mast group in a Tower-LCC or similar device)
+or virtual track circuit in a Tower-LCC or similar device.
+
+\rule
+
+
\A{} Messages and Explanations
\H{messageType} \i{Message Types}
@@ -236,3 +274,4 @@ Menu and sub-menu items are indicated by \e{File>Open}, which means select the \
\K{messageList} provides detail explanation of each information or error message.
\rule
+
diff --git a/app/doc/changem.but b/app/doc/changem.but
index 8327edf..2bcd90b 100644
--- a/app/doc/changem.but
+++ b/app/doc/changem.but
@@ -4,6 +4,8 @@
\#
\# The "\u00B0" command gives proper format to the degree sign.
+\cfg{html-local-head}{<meta name="AppleTitle" content="Change Menu" />}
+
\H{changeM}\i{Change Menu}
\G{png.d/mchange.png}
diff --git a/app/doc/drawm.but b/app/doc/drawm.but
index dd53418..21785ce 100644
--- a/app/doc/drawm.but
+++ b/app/doc/drawm.but
@@ -2,7 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
-
+\cfg{html-local-head}{<meta name="AppleTitle" content="Draw Menu" />}
\H{cmdDraw} \i{Draw Menu}
diff --git a/app/doc/editm.but b/app/doc/editm.but
index 9572172..f31b6d6 100644
--- a/app/doc/editm.but
+++ b/app/doc/editm.but
@@ -2,6 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="Edit Menu" />}
\H{editM}\i{Edit Menu}
diff --git a/app/doc/filem.but b/app/doc/filem.but
index a47452e..8b74434 100644
--- a/app/doc/filem.but
+++ b/app/doc/filem.but
@@ -2,9 +2,11 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="File Menu" />}
\H{fileM} \i{File Menu}
+
\G{png.d/mfile.png}
The \f{File Menu} shows file oriented commands for loading and saving layout files.
diff --git a/app/doc/helpm.but b/app/doc/helpm.but
index 290adf5..08ccd49 100644
--- a/app/doc/helpm.but
+++ b/app/doc/helpm.but
@@ -2,6 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="Help Menu" />}
\H{helpM} Help Menu
diff --git a/app/doc/hotbar.but b/app/doc/hotbar.but
index 3ce82f4..9683c5e 100644
--- a/app/doc/hotbar.but
+++ b/app/doc/hotbar.but
@@ -2,6 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="Hot Bar" />}
\H{cmdHotBar} Hot Bar
diff --git a/app/doc/intro.but.in b/app/doc/intro.but.in
index 3fe5b7e..cb0d0d2 100644
--- a/app/doc/intro.but.in
+++ b/app/doc/intro.but.in
@@ -44,7 +44,6 @@ Copyright 2007, Bob Blackwell and Martin Fischer
\IM{Created by Turnout Command}{Easements and Sectional Track} Sectional Track
-
\# >>>>>>>>>> Manual Begin's Here <<<<<<<<<<
\title \e{XTrackCAD} User's Manual
@@ -57,9 +56,10 @@ Copyright 2007, Bob Blackwell and Martin Fischer
\rule
-
\C{index} Introduction To \e{XTrackCAD}
+\cfg{html-local-head}{<meta name="AppleTitle" content="org.xtrkcad.help" />}
+
\e{XTrackCAD} is a CAD (computer-aided design) program for designing Model Railroad layouts. \e{XTrackCAD} supports any scale, has libraries of popular brands of turnouts and sectional track (plus you add your own easily), can automatically use spiral transition curves when joining track and has extensive on-line help and demonstrations. \e{XTrackCAD} lets you manipulate track much like you would with actual flex-track to modify, extend and join tracks and turnouts. Additional features include tunnels, 'post-it' notes, on-screen ruler, parts list, 99 drawing layers, undo/redo commands, bench-work, 'Print to Bitmap', elevations, train simulation and car inventory.
Using it, you can
@@ -780,7 +780,7 @@ This section of the manual describes how and where to report a bug or seek an en
\S{bugs} Reporting \i{Bugs}
-If you encounter an unreported bug please submit detail regarding such to the \f{Bug Tracker} located at the \W{http://sourceforge.net/tracker/?group_id=151737&atid=781978}{\e{XTrackCAD} Fork Project Site}.
+If you encounter an unreported bug please submit detail regarding such to the \f{Bug Tracker} located at the \W{http://sourceforge.net/tracker/?group_id=151737&amp;atid=781978}{\e{XTrackCAD} Fork Project Site}.
\f{Be sure to provide the three basic elements of a bug report:} What you were doing at the time the bug occurred, what you expected to happen and what actually happened. This detail will help developers replicate the error, find and correct the offending code.
@@ -808,7 +808,7 @@ If you encounter an unreported bug please submit detail regarding such to the \f
\f{Always search the bug database first.} Advice so good, we'll repeat it twice. Always search the bug database first. The odds are good that if you've found a problem, someone else found it too. If you spend a few minutes of your time making sure that you're not filing a duplicate bug, that's a few more minutes someone can spend helping to fix that bug rather than sorting out duplicate bug reports.
-\f{If you don't understand an error message, ask for help.} Don't report an error message you don't understand as a bug. There are a lot of places you can ask for help in understanding what is going on before you can claim that an error message you do not understand is a bug. (Once you've understood the error message and have a good suggestion for a way to make the error message clearer, you might consider reporting it as a \W{http://sourceforge.net/tracker/?group_id=151737&atid=781981}{\e{XTrackCAD} Feature Request}).
+\f{If you don't understand an error message, ask for help.} Don't report an error message you don't understand as a bug. There are a lot of places you can ask for help in understanding what is going on before you can claim that an error message you do not understand is a bug. (Once you've understood the error message and have a good suggestion for a way to make the error message clearer, you might consider reporting it as a \W{http://sourceforge.net/tracker/?group_id=151737&amp;atid=781981}{\e{XTrackCAD} Feature Request}).
\f{Be brief, but don't leave any important details out.} This is a fine line to walk. But there are some general guidelines:
@@ -825,6 +825,6 @@ If you can recreate the problem the \f{Macro>Record} command can be used to reco
\S{enhancements} \i{Enhancement Requests}
-Suggestions for improvements are encouraged and welcome. Submit your suggestion to the \e{XTrackCAD} \f{Feature Tracker} located at the \W{http://sourceforge.net/tracker/?group_id=151737&atid=781981}{\e{XTrackCAD} Fork Project Site} or the \e{XTrackCAD} \f{Wikka Wish List} located at the \W{http://www.xtrkcad.org/Wikka/WishList}{\e{XTrackCAD} Wiki: WishList}.
+Suggestions for improvements are encouraged and welcome. Submit your suggestion to the \e{XTrackCAD} \f{Feature Tracker} located at the \W{http://sourceforge.net/tracker/?group_id=151737&amp;.atid=781981}{\e{XTrackCAD} Fork Project Site} or the \e{XTrackCAD} \f{Wikka Wish List} located at the \W{http://www.xtrkcad.org/Wikka/WishList}{\e{XTrackCAD} Wiki: WishList}.
\rule
diff --git a/app/doc/linconf.but b/app/doc/linconf.but
index c8de305..ffb2685 100644
--- a/app/doc/linconf.but
+++ b/app/doc/linconf.but
@@ -1,7 +1,7 @@
\cfg{html-leaf-level}{infinite}
\cfg{html-leaf-contains-contents}{false}
-\cfg{html-suppress-navlinks}{true}
-\cfg{html-suppress-address}{true}
+\cfg{html-suppress-navlinks}{false}
+\cfg{html-suppress-address}{false}
\cfg{html-contents-filename}{contents.html}
\cfg{html-template-filename}{%k.html}
diff --git a/app/doc/macrom.but b/app/doc/macrom.but
index 85fed13..7bf816c 100644
--- a/app/doc/macrom.but
+++ b/app/doc/macrom.but
@@ -2,6 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="Macro Menu" />}
\H{macroM} Macro Menu
diff --git a/app/doc/managem.but b/app/doc/managem.but
index 65a20c0..4a769db 100644
--- a/app/doc/managem.but
+++ b/app/doc/managem.but
@@ -3,6 +3,7 @@
\# The "\u000" command is used to format the output. These commands causes a blank line to appear between "bulleted" or "described" items.
\#
\# The "\u00B0" command gives proper format to the degree sign.
+\cfg{html-local-head}{<meta name="AppleTitle" content="Manage Menu" />}
\H{manageM}\i{Manage Menu}
@@ -18,6 +19,10 @@ The \f{Manage Menu} shows commands affecting the \f{Main Canvas} (\K{mainW}).
\u000
+\dd \f{Layout Control Elements} - display the \f{Layout Control Elements} (\K{cmdContmgm}) dialog to manipulate blocks, turnout motors and signals.
+
+\u000
+
\dd \f{Group} - creates a \f{Structure} or \f{Turnout} definition from the selected (\K{cmdSelect}) objects. See the \f{Group} command (\K{cmdGroup}) for details.
\u000
@@ -290,6 +295,36 @@ The \f{New} buttons invokes the Car (\K{cmdCarpart}) dialog to create a new \f{C
\rule
+\S{cmdContmgm} Layout Control Elements Dialog
+
+This dialog is used to manage layout control elements (blocks, switchmotors, and signals).
+
+Control Elements are elements related to layout control: blocks (occupancy
+detection), switchmotors (actuators to "throw" turnouts), signals, controls
+(other actuator or output devices), and sensors (other sensor or input
+devices). These elements don't relate to directly "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. XTrackCAD 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 that XTrackCAD 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.
+
+\G{png.d/lcemanager.png}
+
+The main part of this dialog contains a list of the currently defined layout
+control elements (blocks, switchmotors, signals, controls, and sensors),
+along with the tracks they relate to. These elements are added to the layout
+either from their Hotbar menus or from the Add menu.
+
+The \f{Edit} button allows for editing a control element. And the \f{Delete} button
+deletes the selected element(s).
+
\S{cmdGroup} Group Dialog
The \f{Group} command combines the selected (\K{cmdSelect}) Lines and Shapes (\K{cmdDraw}) to create structures (\K{cmdHotBar}). You can give the structure (\K{cmdHotBar}) a title consisting of Manufacturer, Description and Part Number on the \f{Group} dialog.
diff --git a/app/doc/navigation.but b/app/doc/navigation.but
index a11e4fa..66b0cc9 100644
--- a/app/doc/navigation.but
+++ b/app/doc/navigation.but
@@ -3,6 +3,7 @@
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
\# The "\u00B0" command gives proper format to the degree sign.
+\cfg{html-local-head}{<meta name="AppleTitle" content="Navigation" />}
\C{navigation} Navigation
diff --git a/app/doc/optionm.but b/app/doc/optionm.but
index e6d49e0..c7f00d9 100644
--- a/app/doc/optionm.but
+++ b/app/doc/optionm.but
@@ -3,6 +3,7 @@
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
\# The "\u00B0" command gives proper format to the degree sign.
+\cfg{html-local-head}{<meta name="AppleTitle" content="Options Menu" />}
\H{optionM}\i{Options Menu}
diff --git a/app/doc/osxconf.but b/app/doc/osxconf.but
new file mode 100644
index 0000000..8656f0e
--- /dev/null
+++ b/app/doc/osxconf.but
@@ -0,0 +1,16 @@
+\cfg{html-version}{xhtml1.0strict}
+\cfg{html-leaf-level}{infinite}
+\cfg{html-leaf-contains-contents}{false}
+\cfg{html-suppress-navlinks}{true}
+\cfg{html-suppress-address}{true}
+
+\cfg{html-contents-filename}{contents.html}
+\cfg{html-template-filename}{%k.html}
+\cfg{html-template-fragment}{%k}
+\cfg{html-applehelp-toc}{toc.html}
+
+\cfg{html-contents-depth}{0}{2}
+
+\cfg{html-head-end}{<link rel="stylesheet" type="text/css" href="xtrkcad_osx.css" /><script type="text/javascript" src="toc.js" ></script>}
+\cfg{html-body-start}{<div id="container"><div id="toc" data-include="toc.html"></div><div id="contents">}
+\cfg{html-body-end}{</div></div>} \ No newline at end of file
diff --git a/app/doc/png.d/bblock.png b/app/doc/png.d/bblock.png
new file mode 100644
index 0000000..ccd90d9
--- /dev/null
+++ b/app/doc/png.d/bblock.png
Binary files differ
diff --git a/app/doc/png.d/bcontrol.png b/app/doc/png.d/bcontrol.png
new file mode 100644
index 0000000..131bb94
--- /dev/null
+++ b/app/doc/png.d/bcontrol.png
Binary files differ
diff --git a/app/doc/png.d/block.png b/app/doc/png.d/block.png
new file mode 100644
index 0000000..598fdad
--- /dev/null
+++ b/app/doc/png.d/block.png
Binary files differ
diff --git a/app/doc/png.d/bsensor.png b/app/doc/png.d/bsensor.png
new file mode 100644
index 0000000..7d9834b
--- /dev/null
+++ b/app/doc/png.d/bsensor.png
Binary files differ
diff --git a/app/doc/png.d/bsignal.png b/app/doc/png.d/bsignal.png
new file mode 100644
index 0000000..f6b52f8
--- /dev/null
+++ b/app/doc/png.d/bsignal.png
Binary files differ
diff --git a/app/doc/png.d/bswitchmotor.png b/app/doc/png.d/bswitchmotor.png
new file mode 100644
index 0000000..68d9a4a
--- /dev/null
+++ b/app/doc/png.d/bswitchmotor.png
Binary files differ
diff --git a/app/doc/png.d/control.png b/app/doc/png.d/control.png
new file mode 100644
index 0000000..2097021
--- /dev/null
+++ b/app/doc/png.d/control.png
Binary files differ
diff --git a/app/doc/png.d/lcemanager.png b/app/doc/png.d/lcemanager.png
new file mode 100644
index 0000000..281c0c2
--- /dev/null
+++ b/app/doc/png.d/lcemanager.png
Binary files differ
diff --git a/app/doc/png.d/madd.png b/app/doc/png.d/madd.png
index 15a1426..f689ebe 100644
--- a/app/doc/png.d/madd.png
+++ b/app/doc/png.d/madd.png
Binary files differ
diff --git a/app/doc/png.d/mmanage.png b/app/doc/png.d/mmanage.png
index 931d065..8ea36f7 100644
--- a/app/doc/png.d/mmanage.png
+++ b/app/doc/png.d/mmanage.png
Binary files differ
diff --git a/app/doc/png.d/sensor.png b/app/doc/png.d/sensor.png
new file mode 100644
index 0000000..1217b3a
--- /dev/null
+++ b/app/doc/png.d/sensor.png
Binary files differ
diff --git a/app/doc/png.d/signal.png b/app/doc/png.d/signal.png
new file mode 100644
index 0000000..e4332a5
--- /dev/null
+++ b/app/doc/png.d/signal.png
Binary files differ
diff --git a/app/doc/png.d/switchmotor.png b/app/doc/png.d/switchmotor.png
new file mode 100644
index 0000000..7b4e73d
--- /dev/null
+++ b/app/doc/png.d/switchmotor.png
Binary files differ
diff --git a/app/doc/statusbar.but b/app/doc/statusbar.but
index 61af8fc..6390722 100644
--- a/app/doc/statusbar.but
+++ b/app/doc/statusbar.but
@@ -2,6 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="Status Bar" />}
\H{cmdStatusbar} Status Bar
diff --git a/app/doc/upgrade.but b/app/doc/upgrade.but
index a88f8ce..efd0908 100644
--- a/app/doc/upgrade.but
+++ b/app/doc/upgrade.but
@@ -2,6 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="Upgrades" />}
\A{upgrades} Upgrade From Earlier \e{XTrackCAD} Version
@@ -70,7 +71,7 @@ The wheel on a wheel mouse can now be used to zoom in and out on a layout design
\f{Internationalization}
-Internationalization or the ability to localize \e{XTrackCAD} for use with various languages was adopted during this version upgrade. \e{XTrackCAD} is now available with balloon help and daily tips written in US English, Finnish and German. The \e{XTrackCAD} development team welcomes anyone who wishes to volunteer with translation of various support files. Let them know by submitting an offer to assist to the \e{XTrackCAD} \f{Feature Tracker} located at the \W{http://sourceforge.net/tracker/?group_id=151737&atid=781981}{\e{XTrackCAD} Fork Project Site} or the \e{XTrackCAD} \f{Wikka Wish List} located at the \W{http://www.xtrkcad.org/Wikka/WishList}{\e{XTrackCAD} Wiki: WishList}.
+Internationalization or the ability to localize \e{XTrackCAD} for use with various languages was adopted during this version upgrade. \e{XTrackCAD} is now available with balloon help and daily tips written in US English, Finnish and German. The \e{XTrackCAD} development team welcomes anyone who wishes to volunteer with translation of various support files. Let them know by submitting an offer to assist to the \e{XTrackCAD} \f{Feature Tracker} located at the \W{http://sourceforge.net/tracker/?group_id=151737&amp;atid=781981}{\e{XTrackCAD} Fork Project Site} or the \e{XTrackCAD} \f{Wikka Wish List} located at the \W{http://www.xtrkcad.org/Wikka/WishList}{\e{XTrackCAD} Wiki: WishList}.
\f{Minor Fixes and Enhancements}
diff --git a/app/doc/view_winm.but b/app/doc/view_winm.but
index eecb843..47ec17b 100644
--- a/app/doc/view_winm.but
+++ b/app/doc/view_winm.but
@@ -2,6 +2,7 @@
\#
\# The "\u000" command is used to format the output. The command causes a blank line to appear between "bulleted" or "described" items.
\#
+\cfg{html-local-head}{<meta name="AppleTitle" content="View Menu" />}
\H{viewM} \i{View Menu}
diff --git a/app/doc/warranty.but b/app/doc/warranty.but
index 9c4e909..357a0cb 100644
--- a/app/doc/warranty.but
+++ b/app/doc/warranty.but
@@ -1,3 +1,5 @@
+\cfg{html-local-head}{<meta name="AppleTitle" content="Warranty" />}
+
\A{warrantyLicenseCopy} Warranty, License and Copying
\e{XTrackCAD} is \XTCCopyRight.
@@ -10,6 +12,7 @@ covered by the Creative Commons Attribution-ShareAlike 2.5 License Agreement.
\H{warranty} Warranty
+
\e{XTrackCAD} is provided "as is" without warranty of any kind, either express or implied, including, but not limited to warranties of merchantability or fitness for a particular purpose. In no event will Sillub Technology be liable for any damages, including incidental or consequential damages, arising out of the use of the program, even if advised of the possibility of such damages.
\rule
diff --git a/app/doc/xtrkcad_osx.css b/app/doc/xtrkcad_osx.css
new file mode 100644
index 0000000..9069eb8
--- /dev/null
+++ b/app/doc/xtrkcad_osx.css
@@ -0,0 +1,144 @@
+/************************************************************************************
+LINUX Help File colour and fonts are done here. Halibut controls margins, line spacing and indents.
+*************************************************************************************/
+
+BODY {
+ background: white;
+ font-family: "Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif;
+}
+
+A:link {
+ text-decoration: none;
+ color: #7DA1BF;
+ font-weight: bold;
+} /* unvisited link */
+
+A:visited {
+ text-decoration: none;
+ color: #1d4e89;
+ font-weight: bold;
+} /* visited links */
+
+A:active {
+ text-decoration: none;
+ font-weight: bold;
+ color: red;
+ } /* active links */
+
+a:hover {
+ text-decoration: underline;
+ color: #F69256;
+ }
+
+H1 {
+ text-align: left;
+ font-size: large;
+ font-style: italic;
+ font-weight: bold;
+ padding: 3px 6px;
+}
+
+H2 {
+ text-align: left;
+ font-size: medium;
+ font-style: italic;
+ font-weight: bold;
+ padding: 3px 6px;
+}
+
+H3 {
+ text-align: left;
+ font-size: small;
+ font-style: italic;
+ font-weight: bold;
+ padding: 3px 6px;
+}
+
+#container {
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+}
+
+#toc {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ bottom: 0px;
+ font-size: 25% small;
+ overflow-y: scroll;
+ width: 20%;
+}
+
+#contents {
+ top: 0px;
+ right: 0px;
+ bottom: 0px;
+ margin-left: 20%;
+ float: left;
+ font-size: 90%;
+ color: #333;
+ font-weight: normal;
+ overflow: auto;
+}
+
+UL.top_link {
+ list-style: none;
+ padding-left:0;
+}
+
+#toc UL {
+ list-style: none;
+ padding-left:1em;
+}
+
+#toc A:link {
+ font-size: 62%;
+ text-decoration: none;
+ color: #7DA1BF;
+}
+#toc A:active {
+ font_size: 62%;
+ text-decoration: none;
+ color: red;
+ } /* active links */
+/* Style the buttons that are used to open and close the accordion panel */
+button.accordion {
+ background-color: #eee;
+ color: #444;
+ cursor: pointer;
+ padding: 0px;
+ width: 20px%;
+ text-align: left;
+ border: none;
+ outline: none;
+ transition: 0.4s;
+}
+
+button.accordion:before {
+ content: '\02795'; /* Unicode character for "plus" sign (+) */
+ font-size: 62%;
+ color: #777;
+ float: left;
+ margin-left: 5px;
+}
+
+button.accordion.active:before {
+ content: "\2796"; /* Unicode character for "minus" sign (-) */
+}
+
+
+/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
+button.accordion.active, button.accordion:hover {
+ background-color: #ddd;
+}
+
+div.panel {
+ padding: 0 18px;
+ background-color: white;
+ max-height: 0;
+ overflow: hidden;
+ transition: max-height 0.2s ease-out;
+}
+
+
diff --git a/app/dynstring/CMakeLists.txt b/app/dynstring/CMakeLists.txt
new file mode 100644
index 0000000..b407805
--- /dev/null
+++ b/app/dynstring/CMakeLists.txt
@@ -0,0 +1,11 @@
+# compile the dynstring library
+
+set( SOURCES
+ dynstring.c )
+
+add_library(dynstring
+ ${SOURCES})
+
+if(XTRKCAD_TESTING)
+ add_subdirectory( unittest )
+endif(XTRKCAD_TESTING) \ No newline at end of file
diff --git a/app/dynstring/dynstring.c b/app/dynstring/dynstring.c
new file mode 100644
index 0000000..6f3159c
--- /dev/null
+++ b/app/dynstring/dynstring.c
@@ -0,0 +1,457 @@
+/** \file dynstring.c
+* Library for dynamic string functions
+*/
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdarg.h>
+#include <memory.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "dynstring.h"
+
+/**
+* Get the current length of the string
+*
+* \param s IN the dynamic string
+* \return the length of the string in bytes
+*/
+
+size_t DynStringSize(DynString *s)
+{
+ if (isnas(s)) {
+ return 0;
+ }
+
+ return s->size;
+}
+
+/* An initialized empty struct string */
+#define STRINIT() (DynStringMalloc(16))
+
+/**
+* Allocate memory for a string of the desired length. To optimize memory usage
+* a minimum length of 16 bytes is allocated. The allocated string has to be freed
+* using the DynStringFree() function.
+*
+* \param s IN pointer to DynString structure
+* \param size IN number of bytes to allocate
+* \return pointer to the DynString
+*/
+
+DynString *DynStringMalloc(DynString *s, size_t size)
+{
+ if (size < 16) {
+ size = 16;
+ }
+
+ s->s = malloc(size);
+ s->size = 0;
+ s->b_size = (size_t)(size | STR_FREEABLE );
+ return (s);
+}
+
+/**
+* Try to compact string memory by reallocating a buffer large enough for the current
+* string content.
+*
+* \param s IN the dynamic string
+*/
+
+void DynStringRealloc(DynString *s)
+{
+ char *buf;
+
+ /* Not a string? */
+ if (isnas(s)) {
+ return;
+ }
+
+ /* Can't realloc? */
+ if (!(s->b_size & STR_FREEABLE)) {
+ return;
+ }
+
+ /* Don't invoke undefined behaviour with realloc(x, 0) */
+ if (!s->size) {
+ free(s->s);
+ s->s = malloc(16);
+ s->b_size = (size_t)(16 | STR_FREEABLE);
+ } else {
+ /* Try to compact */
+ buf = realloc(s->s, s->size);
+
+ if (buf) {
+ s->s = buf;
+ }
+ s->b_size = (size_t)(s->size | STR_FREEABLE);
+ }
+}
+
+/**
+* Clear the dynamic string. Current content is deleted. The buffer is shrinked to the
+* minimum size.
+*
+* \param s IN the dynamic string
+*/
+
+void DynStringClear(DynString *s)
+{
+ /* Not a string? */
+ if (isnas(s))
+ {
+ return;
+ }
+
+ /* Can't realloc? */
+ if (!(s->b_size & STR_FREEABLE))
+ {
+ return;
+ }
+ s->size = 0;
+
+ DynStringRealloc(s);
+}
+/**
+* Resize the string for a minimum number of bytes. In order to optimize memory usage the
+* actually allocated block of memory can be larger than the requested size.
+* In case of an error, the string is set to NaS
+*
+* \param s IN OUT the string
+* \param size IN the requested new size
+*/
+
+void DynStringResize(DynString *s, size_t size)
+{
+ char *buf;
+ size_t bsize;
+
+ /* Are we not a string? */
+ if (isnas(s)) {
+ return;
+ }
+
+ /* Not resizable */
+ if (!(s->b_size & STR_FREEABLE)) {
+ DynString s2;
+
+ /* Don't do anything if we want to shrink */
+ if (size <= s->size) {
+ return;
+ }
+
+ /* Need to alloc a new string */
+ DynStringMalloc(&s2, size);
+ /* Copy into new string */
+ memcpy(s2.s, s->s, s->size);
+ /* Point to new string */
+ s->s = s2.s;
+ s->b_size = s2.b_size;
+ return;
+ }
+
+ /* Too big */
+ if (size & STR_FREEABLE) {
+ DynString nas = NaS;
+ free(s->s);
+ *s = nas;
+ return;
+ }
+
+ bsize = (size_t)(s->b_size - STR_FREEABLE);
+
+ /* Keep at least 16 bytes */
+ if (size < 16) {
+ size = 16;
+ }
+
+ /* Nothing to do? */
+ if ((4 * size > 3 * bsize) && (size <= bsize)) {
+ return;
+ }
+
+ /* Try to double size instead of using a small increment */
+ if ((size > bsize) && (size < bsize * 2)) {
+ size = bsize * 2;
+ }
+
+ /* Keep at least 16 bytes */
+ if (size < 16) {
+ size = 16;
+ }
+
+ buf = realloc(s->s, size);
+
+ if (!buf) {
+ DynString nas = NaS;
+ /* Failed, go to NaS state */
+ free(s->s);
+ *s = nas;
+ } else {
+ s->s = buf;
+ s->b_size = (size_t)(size | STR_FREEABLE);
+ }
+}
+
+/**
+* Free the previously allocated string.
+*
+* \param s IN OUT the dynamic string
+*/
+
+void DynStringFree(DynString *s)
+{
+ DynString nas = NaS;
+
+ if (s->b_size & STR_FREEABLE) {
+ free(s->s);
+ }
+
+ *s = nas;
+}
+
+/**
+* Create a newly allocated copy of the passed dynamic string.
+*
+* \param s IN the dynamic string
+* \return the newly allocated dynamic string
+*/
+
+/* Create a new string as a copy of an old one */
+DynString *DynStringDupStr(DynString *s2, DynString *s)
+{
+ DynString nas = NaS;
+
+ /* Not a string? */
+ if (isnas(s)) {
+ return NULL;
+ }
+
+ DynStringMalloc(s2, s->size);
+ s2->size = s->size;
+ memcpy(s2->s, s->s, s->size);
+ return s2;
+}
+
+/**
+* Copy the memory from the source string into the dest string.
+*
+* \param dest IN the destination dynamic string
+* \param src IN the source dynamic string
+*/
+
+void DynStringCpyStr(DynString *dest, DynString *src)
+{
+ /* Are we no a string */
+ if (isnas(src)) {
+ return;
+ }
+
+ DynStringResize(dest, src->size);
+
+ if (isnas(dest)) {
+ return;
+ }
+
+ dest->size = src->size;
+ memcpy(dest->s, src->s, src->size);
+}
+
+/**
+* Return the content of the dynamic string as a \0 terminated C string. This memory may not be freed by the
+* caller.
+*
+* \param s IN the dynamic string
+* \return the C string
+*/
+
+char *DynStringToCStr(DynString *s)
+{
+ size_t bsize;
+
+ /* Are we not a string? */
+ if (isnas(s)) {
+ return NULL;
+ }
+
+ /* Get real buffer size */
+ bsize = s->b_size & ~STR_FREEABLE;
+
+ if (s->size == bsize) {
+ /* Increase buffer size */
+ DynStringResize(s, bsize + 1);
+
+ /* Are we no longer a string? */
+ if (isnas(s)) {
+ return NULL;
+ }
+ }
+
+ /* Tack a zero on the end */
+ s->s[s->size] = 0;
+ /* Don't update the size */
+ /* Can use this buffer as long as you don't append anything else */
+ return s->s;
+}
+
+/**
+* Concatenate a number of bytes from the source string to the dynamic string.
+*
+* \param s IN the dynamic string
+* \param len IN the number of bytes to append to the dynamic string
+* \param str IN the source string
+*/
+
+void DynStringNCatCStr(DynString *s, size_t len, const char *str)
+{
+ size_t bsize;
+
+ /* Are we not a string? */
+ if (isnas(s)) {
+ return;
+ }
+
+ /* Nothing to do? */
+ if (!str || !len) {
+ return;
+ }
+
+ /* Get real buffer size */
+ bsize = s->b_size & ~STR_FREEABLE;
+
+ if (s->size + len >= bsize) {
+ DynStringResize(s, s->size + len);
+
+ /* Are we no longer a string? */
+ if (isnas(s)) {
+ return;
+ }
+ }
+
+ memcpy(&s->s[s->size], str, len);
+ s->size += len;
+}
+
+/**
+* Concatenate a zero-terminated source string to the dynamic string.
+*
+* \param s IN the dynamic string
+* \param str IN the source string
+*/
+
+void DynStringCatCStr(DynString *s, const char *str)
+{
+ if (str) {
+ DynStringNCatCStr(s, strlen(str), str);
+ }
+}
+
+/**
+* Concatenate a dynamic string to another dynamic string.
+*
+* \param s IN the destination dynamic string
+* \param s2 IN the source dynamic string
+*/
+
+void DynStringCatStr(DynString *s, const DynString *s2)
+{
+ DynStringNCatCStr(s, s2->size, s2->s);
+}
+
+/**
+* Concatenate a variable number zero terminated strings to the dynamic string. The
+* list of source strings has to be terminated by a NULL pointer.
+*
+* \param s IN the dynamic string
+* \param ... IN variable number of C strings
+*/
+
+void DynStringCatCStrs(DynString *s, ...)
+{
+ const char *str;
+ va_list v;
+
+ /* Are we not a string? */
+ if (isnas(s)) {
+ return;
+ }
+
+ va_start(v, s);
+
+ for (str = va_arg(v, const char *); str; str = va_arg(v, const char *)) {
+ DynStringNCatCStr(s, strlen(str), str);
+ }
+
+ va_end(v);
+}
+
+/**
+* Concatenate a variable number of dynamic string to another dynamic string.
+* The list of source strings has to be terminated by a NULL pointer.
+*
+* \param s IN the destination dynamic string
+* \param s2 IN the source dynamic strings
+*/
+
+void DynStringCatStrs(DynString *s1, ...)
+{
+ const DynString *s2;
+ va_list v;
+
+ /* Are we not a string? */
+ if (isnas(s1)) {
+ return;
+ }
+
+ va_start(v, s1);
+
+ for (s2 = va_arg(v, const DynString *); s2; s2 = va_arg(v, const DynString *)) {
+ DynStringNCatCStr(s1, s2->size, s2->s);
+ }
+
+ va_end(v);
+}
+
+/**
+* Return a formatted dynamic string. Formatting is performed similar to the printf style
+* of functions.
+*
+* \param s IN the dynamic string
+* \param fmt IN format specification
+* \param ... IN values
+*/
+
+void DynStringPrintf(DynString *s, const char *fmt, ...)
+{
+ va_list v;
+ size_t len;
+ DynString nas = NaS;
+
+ ///* Are we not a string? */
+ //if (isnas(s)) {
+ // *s = STRINIT();
+ //}
+
+ /* Nothing to do? */
+ if (!fmt) {
+ return;
+ }
+
+ va_start(v, fmt);
+ len = vsnprintf(NULL, 0, fmt, v) + 1;
+ va_end(v);
+ DynStringResize(s, len);
+
+ /* Are we no longer a string? */
+ if (isnas(s)) {
+ return;
+ }
+
+ va_start(v, fmt);
+ vsnprintf(s->s, len, fmt, v);
+ va_end(v);
+ s->size = len - 1;
+}
diff --git a/app/dynstring/dynstring.h b/app/dynstring/dynstring.h
new file mode 100644
index 0000000..d6fac51
--- /dev/null
+++ b/app/dynstring/dynstring.h
@@ -0,0 +1,40 @@
+#ifndef HAVE_DYNSTRING_H
+#define HAVE_DYNSTRING_H
+
+typedef struct DynString DynString;
+struct DynString
+{
+ char *s;
+ size_t size; // length of the string
+ size_t b_size; // length of the buffer containing the string
+};
+
+#define NaS {NULL, 0, 0}
+#define isnas(S) (!(S)->s)
+
+// define highest bit depending on 32 or 64 bit compile
+
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+ #define STR_FREEABLE (1ULL << 63)
+#else
+ #define STR_FREEABLE (1ULL << 31)
+#endif
+
+size_t DynStringSize(DynString * s);
+
+DynString * DynStringMalloc(DynString *s, size_t size);
+void DynStringClear(DynString *s);
+void DynStringRealloc(DynString * s);
+void DynStringResize(DynString * s, size_t size);
+void DynStringFree(DynString * s);
+DynString * DynStringDupStr(DynString *s2, DynString * s);
+void DynStringCpyStr(DynString * dest, DynString * src);
+char * DynStringToCStr(DynString * s);
+void DynStringNCatCStr(DynString * s, size_t len, const char * str);
+void DynStringCatCStr(DynString * s, const char * str);
+void DynStringCatStr(DynString * s, const DynString * s2);
+void DynStringCatCStrs(DynString * s, ...);
+void DynStringCatStrs(DynString * s1, ...);
+void DynStringPrintf(DynString * s, const char * fmt, ...);
+
+#endif // !HAVE_DYNSTRING_H
diff --git a/app/dynstring/unittest/CMakeLists.txt b/app/dynstring/unittest/CMakeLists.txt
new file mode 100644
index 0000000..7aad7c1
--- /dev/null
+++ b/app/dynstring/unittest/CMakeLists.txt
@@ -0,0 +1,8 @@
+# build unit tests for the dynstring library
+
+add_executable(dynstringtest DynStringTest.c)
+target_link_libraries(dynstringtest
+ dynstring
+ ${LIBS})
+
+add_test(DynStringTest dynstringtest) \ No newline at end of file
diff --git a/app/dynstring/unittest/DynStringTest.c b/app/dynstring/unittest/DynStringTest.c
new file mode 100644
index 0000000..33d4c9a
--- /dev/null
+++ b/app/dynstring/unittest/DynStringTest.c
@@ -0,0 +1,108 @@
+/** \file DynStringTest.c
+* Unit tests for the dynstring library
+*/
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "../dynstring.h"
+
+#define TEXT1 "Pastry gummi bears candy canes jelly beans macaroon choc"
+#define TEXT2 "olate jelly beans. Marshmallow cupcake tart jelly apple pie sesame snaps ju"
+#define TEXT3 "jubes. Tootsie roll dessert gummi bears jelly."
+
+static void PrintfString(void **state)
+{
+ DynString string;
+
+ (void)state;
+ DynStringMalloc(&string, 0);
+ DynStringPrintf(&string, "%d", 1);
+ assert_string_equal(DynStringToCStr(&string), "1");
+ DynStringFree(&string);
+}
+
+static void CopyString(void **state)
+{
+ DynString string;
+ DynString string2;
+ (void)state;
+ DynStringMalloc(&string, 0);
+ DynStringCatCStr(&string, TEXT1);
+ DynStringDupStr(&string2, &string);
+ assert_int_equal(DynStringSize(&string2), strlen(TEXT1));
+ assert_string_equal(DynStringToCStr(&string2), TEXT1);
+ DynStringFree(&string2);
+ DynStringMalloc(&string2, 0);
+ DynStringCatCStr(&string2, TEXT2);
+ DynStringCatStr(&string, &string2);
+ assert_int_equal(DynStringSize(&string), strlen(TEXT1) + strlen(TEXT2));
+ assert_string_equal(DynStringToCStr(&string), TEXT1 TEXT2);
+}
+
+static void VarStringCount(void **state)
+{
+ DynString string;
+ (void)state;
+ DynStringMalloc(&string, 0);
+ DynStringCatCStrs(&string, TEXT1, TEXT2, TEXT3, NULL);
+ assert_int_equal(DynStringSize(&string),
+ strlen(TEXT1) + strlen(TEXT2) + strlen(TEXT3));
+ assert_string_equal(DynStringToCStr(&string), TEXT1 TEXT2 TEXT3);
+ DynStringFree(&string);
+}
+
+static void MultipleStrings(void **state)
+{
+ DynString string;
+ (void)state;
+ DynStringMalloc(&string, 0);
+ DynStringCatCStr(&string, TEXT1);
+ DynStringCatCStr(&string, TEXT2);
+ assert_int_equal(DynStringSize(&string), strlen(TEXT1)+strlen(TEXT2));
+ assert_string_equal(DynStringToCStr(&string), TEXT1 TEXT2);
+ DynStringFree(&string);
+}
+
+static void SingleString(void **state)
+{
+ DynString string;
+ (void)state;
+ DynStringMalloc(&string, 0);
+ DynStringCatCStr(&string, TEXT1);
+ assert_int_equal(DynStringSize(&string), strlen(TEXT1));
+ assert_string_equal(DynStringToCStr(&string), TEXT1);
+
+ DynStringClear(&string);
+ assert_int_equal(DynStringSize(&string), 0);
+
+ DynStringFree(&string);
+}
+
+static void SimpleInitialization(void **state)
+{
+ DynString string;
+ (void)state;
+ DynStringMalloc(&string, 0);
+ assert_non_null((void *)&string);
+ assert_false(isnas(&string));
+ assert_int_equal(DynStringSize(&string), 0);
+ DynStringFree(&string);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(SimpleInitialization),
+ cmocka_unit_test(SingleString),
+ cmocka_unit_test(MultipleStrings),
+ cmocka_unit_test(VarStringCount),
+ cmocka_unit_test(CopyString),
+ cmocka_unit_test(PrintfString)
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+} \ No newline at end of file
diff --git a/app/help/genhelp.in b/app/help/genhelp.in
index b15a727..d4265b7 100644
--- a/app/help/genhelp.in
+++ b/app/help/genhelp.in
@@ -6,10 +6,7 @@ cmdAbout About box dialog
cmdAbove Move Selected object to top
cmdAddElevations Raise or Lower all Selected tracks
cmdBelow Move Selected object to bottom
-cmdBlockCreate Create Block
-cmdBlockDelete Delete Block
-cmdBlockEdit Edit Block
-cmdBlockSetCmd Block
+cmdBlockCreate Create a section of track for automation.
cmdCarDesc Create a new Car/Loco description
cmdCarInventory Manage your Car and Loco Inventory
cmdCircleCenter Create track circle from center cmdCircle
@@ -21,6 +18,7 @@ cmdClearElevations Removes elevation from Selected tracks
cmdCmdopt Command Options dialog
cmdColor Controls colors
cmdConnect Connect two tracks
+cmdControl Create a control for layout automation
cmdCopy Copy selected objects to clipboard
cmdCurveCenter Create curved track from center cmdCurve
cmdCurveChord Create curved track from chord cmdCurve
@@ -126,13 +124,12 @@ cmdSelectCurrentLayer Selects all objects in the current Layer layer
cmdSelectInvert Invert current selection
cmdSplitTrack Split a track
cmdSelectOrphaned Select stranded (unconnected) track pieces
+cmdSensor Create a sensor (ie. a occupancy detector or a toggle switch)
+cmdSignal Create a signal for train control
cmdSticky Choose which commands are sticky
cmdStraight Create straight track
cmdStructure Place a structure on the layout
-cmdSwitchMotorCreate Create Switch Motor
-cmdSwitchMotorDelete Delete Switch Motor
-cmdSwitchMotorEdit Edit Switch Motor
-cmdSwitchMotorSetCmd Switch Motors
+cmdSwitchMotorCreate Create a switchmotor for turnout control
cmdText Enter text on the layout
cmdTextSize Controls the size of the entered text cmdText
#cmdTighten Remove slack from connected tracks
@@ -346,7 +343,7 @@ draw-benchorient Orientation of Benchwork cmdDraw
draw-arrowsize Size of Dimension Arrows cmdDraw
#
easement-val This controls the sharpness of the easement curve cmdEasement
-easement-r Minumum radius cmdEasement
+easement-r Minimum radius cmdEasement
easement-x Maximum offset cmdEasement
easement-l Easement length cmdEasement
easement-radio These radio buttons are a short-cut for Values of 0.0, 0.5, 1.0 and 2.0. None turns Easements off cmdEasement
diff --git a/app/help/xtrkcad.info b/app/help/xtrkcad.info
index 39c343e..955bab7 100644
--- a/app/help/xtrkcad.info
+++ b/app/help/xtrkcad.info
@@ -1,3 +1,8 @@
+INFO-DIR-SECTION CAD
+START-INFO-DIR-ENTRY
+* xtrkcad: xtrkcad-4.2.4. Model Train Track CAD Program
+END-INFO-DIR-ENTRY
+
:Help
Invokes on-line help for this dialog
:cancel
@@ -12,6 +17,8 @@ Move Selected object to top
Raise or Lower all Selected tracks
:cmdBelow
Move Selected object to bottom
+:cmdBlockCreate
+Create a section of track for automation.
:cmdCarDesc
Create a new Car/Loco description
:cmdCarInventory
@@ -34,6 +41,8 @@ Controls colors
Connect two tracks
:cmdCopy
Copy selected objects to clipboard
+:cmdControl
+Create a control for layout automation
:cmdCurveCenter
Create curved track from center
:cmdCurveChord
@@ -194,16 +203,22 @@ Selects all objects on the layout
Selects all objects in the current Layer
:cmdSelectInvert
Invert current selection
+:cmdSensor
+Create a sensor (ie. a occupancy detector or a toggle switch)
:cmdSplitTrack
Split a track
:cmdSelectOrphaned
Select stranded (unconnected) track pieces
+:cmdSignal
+Create a signal for train control
:cmdSticky
Choose which commands are sticky
:cmdStraight
Create straight track
:cmdStructure
Place a structure on the layout
+:cmdSwitchMotorCreate
+Create a switchmotor for turnout control
:cmdText
Enter text on the layout
:cmdTextSize
@@ -1099,3 +1114,4 @@ Layer
:cmdLayerShow19
Layer
:
+
diff --git a/app/i18n/de_DE.po b/app/i18n/de_DE.po
index a97c2a0..7f03e3a 100644
--- a/app/i18n/de_DE.po
+++ b/app/i18n/de_DE.po
@@ -3,14 +3,14 @@ msgstr ""
"Project-Id-Version: xtrkcad 4.1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-02-06 12:30+0100\n"
-"PO-Revision-Date: 2016-02-06 12:35+0100\n"
+"PO-Revision-Date: 2016-08-25 10:38+0200\n"
"Last-Translator: \n"
"Language-Team: German <m_fischer@users.sourceforge.net>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.8.1\n"
+"X-Generator: Poedit 1.8.4\n"
#: ../bin/cblock.c:98 ../bin/cblock.c:133 ../bin/compound.c:520
#: ../bin/cswitchmotor.c:78 ../bin/cswitchmotor.c:138 ../bin/dlayer.c:319
@@ -59,40 +59,40 @@ msgid "Block"
msgstr "Block"
#: ../bin/cblock.c:442 ../bin/cblock.c:461 ../bin/cblock.c:469
-#: ../bin/cblock.c:525 ../bin/cdraw.c:78 ../bin/cdraw.c:870
-#: ../bin/cgroup.c:962 ../bin/cgroup.c:1009 ../bin/cgroup.c:1024
-#: ../bin/cgroup.c:1063 ../bin/cgroup.c:1089 ../bin/cgroup.c:1148
-#: ../bin/cgroup.c:1592 ../bin/cnote.c:96 ../bin/cprint.c:520
-#: ../bin/cprint.c:945 ../bin/cpull.c:499 ../bin/cpull.c:514
-#: ../bin/cpull.c:516 ../bin/cpull.c:518 ../bin/cselect.c:670
-#: ../bin/cselect.c:767 ../bin/cselect.c:1243 ../bin/csnap.c:578
-#: ../bin/csnap.c:711 ../bin/cstruct.c:763 ../bin/cstruct.c:772
-#: ../bin/cstruct.c:874 ../bin/cswitchmotor.c:355 ../bin/cswitchmotor.c:381
-#: ../bin/ctext.c:163 ../bin/ctodesgn.c:150 ../bin/ctodesgn.c:1040
-#: ../bin/ctodesgn.c:1090 ../bin/ctodesgn.c:1203 ../bin/ctodesgn.c:1505
-#: ../bin/ctrain.c:2561 ../bin/cturnout.c:2381 ../bin/cturnout.c:2508
-#: ../bin/cundo.c:152 ../bin/cundo.c:156 ../bin/dbitmap.c:65
-#: ../bin/dbitmap.c:122 ../bin/dbitmap.c:200 ../bin/dbitmap.c:235
-#: ../bin/dcar.c:3528 ../bin/dcar.c:3712 ../bin/dcar.c:3716 ../bin/dcar.c:3720
-#: ../bin/dcar.c:3725 ../bin/dcar.c:4039 ../bin/dcar.c:4150 ../bin/dcar.c:4528
-#: ../bin/dcmpnd.c:387 ../bin/dcmpnd.c:398 ../bin/dcmpnd.c:530
-#: ../bin/dcustmgm.c:186 ../bin/dcustmgm.c:192 ../bin/dcustmgm.c:201
-#: ../bin/dcustmgm.c:217 ../bin/dease.c:220 ../bin/dlayer.c:200
-#: ../bin/dlayer.c:217 ../bin/dlayer.c:657 ../bin/dlayer.c:662
-#: ../bin/doption.c:155 ../bin/doption.c:274 ../bin/doption.c:354
-#: ../bin/doption.c:505 ../bin/doption.c:517 ../bin/doption.c:583
-#: ../bin/dprmfile.c:91 ../bin/dprmfile.c:105 ../bin/dprmfile.c:118
-#: ../bin/dprmfile.c:160 ../bin/dprmfile.c:438 ../bin/draw.c:2234
-#: ../bin/fileio.c:609 ../bin/fileio.c:678 ../bin/fileio.c:789
-#: ../bin/fileio.c:791 ../bin/fileio.c:796 ../bin/fileio.c:958
-#: ../bin/macro.c:934 ../bin/macro.c:938 ../bin/macro.c:1015
-#: ../bin/macro.c:1121 ../bin/macro.c:1349 ../bin/macro.c:1365
-#: ../bin/misc2.c:411 ../bin/param.c:1820 ../bin/param.c:1944
-#: ../bin/param.c:1947 ../bin/param.c:2069 ../bin/param.c:2075
-#: ../bin/smalldlg.c:91 ../bin/smalldlg.c:221 ../bin/tease.c:1039
-#: ../bin/track.c:1311 ../bin/misc.c:304 ../bin/misc.c:354 ../bin/misc.c:1712
-#: ../bin/misc.c:1846 ../bin/misc.c:1910 ../bin/misc.c:2476 ../bin/misc.c:2486
-#: ../bin/misc.c:2506 ../bin/misc.c:2509 ../wlib/gtklib/wpref.c:126
+#: ../bin/cblock.c:525 ../bin/cdraw.c:78 ../bin/cdraw.c:870 ../bin/cgroup.c:962
+#: ../bin/cgroup.c:1009 ../bin/cgroup.c:1024 ../bin/cgroup.c:1063
+#: ../bin/cgroup.c:1089 ../bin/cgroup.c:1148 ../bin/cgroup.c:1592
+#: ../bin/cnote.c:96 ../bin/cprint.c:520 ../bin/cprint.c:945 ../bin/cpull.c:499
+#: ../bin/cpull.c:514 ../bin/cpull.c:516 ../bin/cpull.c:518
+#: ../bin/cselect.c:670 ../bin/cselect.c:767 ../bin/cselect.c:1243
+#: ../bin/csnap.c:578 ../bin/csnap.c:711 ../bin/cstruct.c:763
+#: ../bin/cstruct.c:772 ../bin/cstruct.c:874 ../bin/cswitchmotor.c:355
+#: ../bin/cswitchmotor.c:381 ../bin/ctext.c:163 ../bin/ctodesgn.c:150
+#: ../bin/ctodesgn.c:1040 ../bin/ctodesgn.c:1090 ../bin/ctodesgn.c:1203
+#: ../bin/ctodesgn.c:1505 ../bin/ctrain.c:2561 ../bin/cturnout.c:2381
+#: ../bin/cturnout.c:2508 ../bin/cundo.c:152 ../bin/cundo.c:156
+#: ../bin/dbitmap.c:65 ../bin/dbitmap.c:122 ../bin/dbitmap.c:200
+#: ../bin/dbitmap.c:235 ../bin/dcar.c:3528 ../bin/dcar.c:3712
+#: ../bin/dcar.c:3716 ../bin/dcar.c:3720 ../bin/dcar.c:3725 ../bin/dcar.c:4039
+#: ../bin/dcar.c:4150 ../bin/dcar.c:4528 ../bin/dcmpnd.c:387
+#: ../bin/dcmpnd.c:398 ../bin/dcmpnd.c:530 ../bin/dcustmgm.c:186
+#: ../bin/dcustmgm.c:192 ../bin/dcustmgm.c:201 ../bin/dcustmgm.c:217
+#: ../bin/dease.c:220 ../bin/dlayer.c:200 ../bin/dlayer.c:217
+#: ../bin/dlayer.c:657 ../bin/dlayer.c:662 ../bin/doption.c:155
+#: ../bin/doption.c:274 ../bin/doption.c:354 ../bin/doption.c:505
+#: ../bin/doption.c:517 ../bin/doption.c:583 ../bin/dprmfile.c:91
+#: ../bin/dprmfile.c:105 ../bin/dprmfile.c:118 ../bin/dprmfile.c:160
+#: ../bin/dprmfile.c:438 ../bin/draw.c:2234 ../bin/fileio.c:609
+#: ../bin/fileio.c:678 ../bin/fileio.c:789 ../bin/fileio.c:791
+#: ../bin/fileio.c:796 ../bin/fileio.c:958 ../bin/macro.c:934
+#: ../bin/macro.c:938 ../bin/macro.c:1015 ../bin/macro.c:1121
+#: ../bin/macro.c:1349 ../bin/macro.c:1365 ../bin/misc2.c:411
+#: ../bin/param.c:1820 ../bin/param.c:1944 ../bin/param.c:1947
+#: ../bin/param.c:2069 ../bin/param.c:2075 ../bin/smalldlg.c:91
+#: ../bin/smalldlg.c:221 ../bin/tease.c:1039 ../bin/track.c:1311
+#: ../bin/misc.c:304 ../bin/misc.c:354 ../bin/misc.c:1712 ../bin/misc.c:1846
+#: ../bin/misc.c:1910 ../bin/misc.c:2476 ../bin/misc.c:2486 ../bin/misc.c:2506
+#: ../bin/misc.c:2509 ../wlib/gtklib/wpref.c:126
#: ../../../build/xtc_4-2-3dev/app/bin/bllnhlp.c:523
msgid "Ok"
msgstr "Ok"
@@ -142,8 +142,7 @@ msgstr "Ja"
#: ../bin/ctrain.c:2056 ../bin/dcar.c:3664 ../bin/dcar.c:3742
#: ../bin/dcar.c:3826 ../bin/dcar.c:3845 ../bin/dcar.c:4175 ../bin/dcar.c:4590
#: ../bin/dcustmgm.c:136 ../bin/track.c:1313 ../bin/track.c:1410
-#: ../bin/track.c:1424 ../bin/misc.c:1053 ../bin/misc.c:1058
-#: ../bin/misc.c:1123
+#: ../bin/track.c:1424 ../bin/misc.c:1053 ../bin/misc.c:1058 ../bin/misc.c:1123
msgid "No"
msgstr "Nein"
@@ -154,11 +153,11 @@ msgstr "Gleisabschnitt löschen"
#: ../bin/cblock.c:641
msgid "Blocks"
-msgstr "Blocks"
+msgstr "Gleisabschnitte"
#: ../bin/cblock.c:643 ../../../build/xtc_4-2-3dev/app/bin/bllnhlp.c:19
msgid "Edit Block"
-msgstr "Block bearbeiten"
+msgstr "Gleisabschnitt bearbeiten"
#: ../bin/ccurve.c:102
msgid "Drag from End-Point in direction of curve"
@@ -178,7 +177,7 @@ msgstr "Zum anderen Ende der Sehne ziehen"
#: ../bin/ccurve.c:128 ../bin/chndldto.c:91
msgid "Drag to set angle"
-msgstr "Ziehen um den Winkel zu ändern"
+msgstr "Durch Ziehen den Winkel festlegen"
#: ../bin/ccurve.c:156
#, c-format
@@ -264,7 +263,7 @@ msgstr "Gleiswendel"
#: ../bin/ccurve.c:524
msgid "Circle Radius"
-msgstr "Radius des Kreis"
+msgstr "Kreisradius"
#: ../bin/ccurve.c:529
msgid "Click on Circle Edge"
@@ -272,7 +271,7 @@ msgstr "Auf den Rand des Kreis klicken"
#: ../bin/ccurve.c:533
msgid "Click on Circle Center"
-msgstr "Auf Kreismittelpunkt klicken"
+msgstr "Auf den Mittelpunkt des Kreises klicken"
#: ../bin/ccurve.c:564
msgid "Drag to Center"
@@ -280,7 +279,7 @@ msgstr "Zum Mittelpunkt ziehen"
#: ../bin/ccurve.c:568
msgid "Drag to Edge"
-msgstr "Zur Kante ziehen"
+msgstr "Zum Rand ziehen"
#: ../bin/ccurve.c:589 ../bin/ccurve.c:593
#, c-format
@@ -305,7 +304,7 @@ msgstr "Radius durch Ziehen festlegen"
#: ../bin/ccurve.c:686
msgid "Place circle"
-msgstr "Setze Kreis"
+msgstr "Platziere Kreis"
#: ../bin/ccurve.c:711
msgid "Curve Track"
@@ -313,19 +312,19 @@ msgstr "Gleisbogen"
#: ../bin/ccurve.c:711
msgid "Curve Tracks"
-msgstr "Gleise biegen"
+msgstr "Gleisbögen"
#: ../bin/ccurve.c:712
msgid "Curve from End-Pt"
-msgstr "Bogen aus Endpunkte"
+msgstr "Bogen aus Endpunkten"
#: ../bin/ccurve.c:713
msgid "Curve from Tangent"
-msgstr "Bogen aus Tangente"
+msgstr "Bogen an Tangente"
#: ../bin/ccurve.c:714
msgid "Curve from Center"
-msgstr "Bogen aus Mittelpunkt"
+msgstr "Bogen um Mittelpunkt"
#: ../bin/ccurve.c:715
msgid "Curve from Chord"
@@ -345,11 +344,11 @@ msgstr "Kreis mit festem Radius"
#: ../bin/ccurve.c:720
msgid "Circle from Tangent"
-msgstr "Kreis aus Tangente"
+msgstr "Kreis an Tangente"
#: ../bin/ccurve.c:721
msgid "Circle from Center"
-msgstr "Kreis aus Mittelpunkt"
+msgstr "Kreis um Mittelpunkt"
#: ../bin/cdraw.c:78
msgid "Font Size must be > 0"
@@ -371,15 +370,15 @@ msgstr "Winkel"
#: ../bin/cdraw.c:196 ../bin/tcurve.c:352
msgid "CCW Angle"
-msgstr "Winkel (gegen Uhrzeiger)"
+msgstr "Winkel (gegen Uhrzeigersinn)"
#: ../bin/cdraw.c:197 ../bin/tcurve.c:353
msgid "CW Angle"
-msgstr "Winkel (im Uhrzeiger)"
+msgstr "Winkel (im Uhrzeigersinn)"
#: ../bin/cdraw.c:198
msgid "Point Count"
-msgstr "Anzahl Punkte"
+msgstr "Anzahl der Punkte"
#: ../bin/cdraw.c:199 ../bin/cdraw.c:811 ../bin/ctodesgn.c:148
msgid "Line Width"
@@ -418,8 +417,8 @@ msgstr "Schriftgröße"
msgid "Text"
msgstr "Text"
-#: ../bin/cdraw.c:208 ../bin/cmisc.c:114 ../bin/tcurve.c:355
-#: ../bin/tease.c:509 ../bin/tstraigh.c:84
+#: ../bin/cdraw.c:208 ../bin/cmisc.c:114 ../bin/tcurve.c:355 ../bin/tease.c:509
+#: ../bin/tstraigh.c:84
msgid "Pivot"
msgstr "Drehpunkt"
@@ -454,7 +453,7 @@ msgstr "Gerade Linie"
#: ../bin/cdraw.c:421 ../bin/cdraw.c:1036
msgid "Dimension Line"
-msgstr "Maßstablinie"
+msgstr "Maßlinie"
#: ../bin/cdraw.c:436 ../bin/cdraw.c:832 ../bin/cdraw.c:1038
msgid "Table Edge"
@@ -515,7 +514,7 @@ msgstr "Gerade"
#: ../bin/cdraw.c:830
msgid "Dimension"
-msgstr "Abmessungen"
+msgstr "Abmessung"
#: ../bin/cdraw.c:833 ../bin/cdraw.c:834 ../bin/cdraw.c:835 ../bin/cdraw.c:836
msgid "Curved"
@@ -536,7 +535,7 @@ msgstr "Gefülltes Rechteck"
#: ../bin/cdraw.c:888
#, c-format
msgid "%s Line Width"
-msgstr "%s Strichstärke"
+msgstr "%s Strichdicke"
#: ../bin/cdraw.c:901
#, c-format
@@ -549,7 +548,7 @@ msgstr " Maßliniengröße"
#: ../bin/cdraw.c:945
msgid "Drag to create Table Edge"
-msgstr "Ziehen um die Tischkante zu erstellen"
+msgstr "Durch Ziehen die Tischkante erstellen"
#: ../bin/cdraw.c:1035
msgid "Line"
@@ -577,7 +576,7 @@ msgstr "Zeichne Tischkante"
#: ../bin/cdraw.c:1040
msgid "Curve End"
-msgstr "Kurve Enden "
+msgstr "Kurvenenden "
#: ../bin/cdraw.c:1040
msgid "Draw Curve from End"
@@ -593,7 +592,7 @@ msgstr "Zeichne Kurve an Tangente"
#: ../bin/cdraw.c:1042
msgid "Curve Center"
-msgstr "Kurve Mittelpunkt"
+msgstr "Kurve um Mittelpunkt"
#: ../bin/cdraw.c:1042
msgid "Draw Curve from Center"
@@ -601,15 +600,15 @@ msgstr "Zeichne Kurve um Mittelpunkt"
#: ../bin/cdraw.c:1043
msgid "Curve Chord"
-msgstr "Kurve Sehne "
+msgstr "Kurve durch Sehne "
#: ../bin/cdraw.c:1043
msgid "Draw Curve from Chord"
-msgstr "Bogen aus Sehne"
+msgstr "Zeichne Kurve durch Sehne"
#: ../bin/cdraw.c:1046
msgid "Circle Tangent"
-msgstr "Kreis Tangente"
+msgstr "Kreis an Tangente"
#: ../bin/cdraw.c:1046
msgid "Draw Circle from Tangent"
@@ -625,7 +624,7 @@ msgstr "Zeichne Kreis um Mittelpunkt"
#: ../bin/cdraw.c:1049
msgid "Circle Filled Tangent"
-msgstr "Gefüllter Kreis Tangente"
+msgstr "Gefüllter Kreis an Tangente"
#: ../bin/cdraw.c:1049
msgid "Draw Filled Circle from Tangent"
@@ -777,9 +776,8 @@ msgstr "Durch neue Gruppe ersetzen?"
#: ../bin/cgroup.c:604 ../bin/compound.c:519 ../bin/cstruct.c:64
#: ../bin/ctodesgn.c:140 ../bin/ctodesgn.c:1764 ../bin/cturnout.c:69
-#: ../bin/dcar.c:1933 ../bin/dcar.c:4070 ../bin/dcar.c:4075
-#: ../bin/dcmpnd.c:444 ../bin/dcustmgm.c:45
-#: ../../../build/xtc_4-2-3dev/app/bin/bllnhlp.c:333
+#: ../bin/dcar.c:1933 ../bin/dcar.c:4070 ../bin/dcar.c:4075 ../bin/dcmpnd.c:444
+#: ../bin/dcustmgm.c:45 ../../../build/xtc_4-2-3dev/app/bin/bllnhlp.c:333
#: ../../../build/xtc_4-2-3dev/app/bin/bllnhlp.c:502
msgid "Manufacturer"
msgstr "Hersteller"
@@ -1796,8 +1794,7 @@ msgstr "Weichendesigner"
msgid "%s %s Designer"
msgstr "%s %s Designer"
-#: ../bin/ctrain.c:168 ../bin/dcar.c:1986 ../bin/dcar.c:4070
-#: ../bin/dcar.c:4075
+#: ../bin/ctrain.c:168 ../bin/dcar.c:1986 ../bin/dcar.c:4070 ../bin/dcar.c:4075
msgid "Index"
msgstr "Verzeichnis"
@@ -2153,17 +2150,16 @@ msgstr ""
"Falscher Trägertyp %s:\n"
"%s"
-#: ../bin/dbench.c:142 ../bin/dcar.c:4225 ../bin/dcar.c:4409
-#: ../bin/dcar.c:4419 ../bin/dcar.c:4466 ../bin/dcar.c:4473 ../bin/dcar.c:4491
-#: ../bin/dcar.c:4504 ../bin/dcar.c:4509 ../bin/dcar.c:4538 ../bin/dcar.c:4699
-#: ../bin/fileio.c:242 ../bin/fileio.c:538 ../bin/fileio.c:656
-#: ../bin/fileio.c:749 ../bin/fileio.c:938 ../bin/fileio.c:1231
-#: ../bin/fileio.c:1375 ../bin/fileio.c:1461 ../bin/fileio.c:1507
-#: ../bin/macro.c:165 ../bin/macro.c:833 ../bin/macro.c:849
-#: ../bin/macro.c:1152 ../bin/param.c:2062 ../bin/track.c:931
-#: ../bin/track.c:1297 ../bin/track.c:1588 ../bin/track.c:1592
-#: ../bin/track.c:1612 ../bin/track.c:1674 ../wlib/gtklib/wpref.c:246
-#: ../wlib/gtklib/wpref.c:253
+#: ../bin/dbench.c:142 ../bin/dcar.c:4225 ../bin/dcar.c:4409 ../bin/dcar.c:4419
+#: ../bin/dcar.c:4466 ../bin/dcar.c:4473 ../bin/dcar.c:4491 ../bin/dcar.c:4504
+#: ../bin/dcar.c:4509 ../bin/dcar.c:4538 ../bin/dcar.c:4699 ../bin/fileio.c:242
+#: ../bin/fileio.c:538 ../bin/fileio.c:656 ../bin/fileio.c:749
+#: ../bin/fileio.c:938 ../bin/fileio.c:1231 ../bin/fileio.c:1375
+#: ../bin/fileio.c:1461 ../bin/fileio.c:1507 ../bin/macro.c:165
+#: ../bin/macro.c:833 ../bin/macro.c:849 ../bin/macro.c:1152
+#: ../bin/param.c:2062 ../bin/track.c:931 ../bin/track.c:1297
+#: ../bin/track.c:1588 ../bin/track.c:1592 ../bin/track.c:1612
+#: ../bin/track.c:1674 ../wlib/gtklib/wpref.c:246 ../wlib/gtklib/wpref.c:253
msgid "Continue"
msgstr "Weiter"
@@ -2454,8 +2450,7 @@ msgstr "Hinzufügen"
msgid "Update %s Scale Car"
msgstr "Aktualisiere Wagen in Maßstab %s"
-#: ../bin/dcar.c:2822 ../bin/dcar.c:2831 ../bin/dcar.c:2840
-#: ../bin/dcmpnd.c:166
+#: ../bin/dcar.c:2822 ../bin/dcar.c:2831 ../bin/dcar.c:2840 ../bin/dcmpnd.c:166
msgid "Update"
msgstr "Aktualisieren"
@@ -6814,7 +6809,7 @@ msgid "This controls the sharpness of the easement curve"
msgstr "Steuert die Größe des Übergangsradius"
#: ../../../build/xtc_4-2-3dev/app/bin/bllnhlp.c:306
-msgid "Minumum radius"
+msgid "Minimum radius"
msgstr "Mindestgleisradius"
#: ../../../build/xtc_4-2-3dev/app/bin/bllnhlp.c:307
diff --git a/app/i18n/fi.po b/app/i18n/fi.po
index 0a6ba8f..be9826e 100644
--- a/app/i18n/fi.po
+++ b/app/i18n/fi.po
@@ -5702,7 +5702,7 @@ msgid "Mint"
msgstr "Loistava"
#: ../../../../build/xtrkcad/app/bin/bllnhlp.c:298
-msgid "Minumum radius"
+msgid "Minimum radius"
msgstr "Pienin karresäde"
#: ../../../../build/xtrkcad/app/i18n/custmsg.h:41
diff --git a/app/i18n/pt_BR.po b/app/i18n/pt_BR.po
index b9c7ac0..d7304ed 100644
--- a/app/i18n/pt_BR.po
+++ b/app/i18n/pt_BR.po
@@ -7210,7 +7210,7 @@ msgid "This controls the sharpness of the easement curve"
msgstr ""
#: ../../../../xtrkcad-build/app/bin/bllnhlp.c:297
-msgid "Minumum radius"
+msgid "Minimum radius"
msgstr ""
#: ../../../../xtrkcad-build/app/bin/bllnhlp.c:298
diff --git a/app/lib/CMakeLists.txt b/app/lib/CMakeLists.txt
index 2ec9d2d..3de124e 100644
--- a/app/lib/CMakeLists.txt
+++ b/app/lib/CMakeLists.txt
@@ -15,3 +15,14 @@ INSTALL(FILES
xtrkcad.xtq
DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}
)
+
+IF(UNIX AND NOT APPLE)
+ INSTALL(FILES
+ xtrkcad.desktop
+ DESTINATION "/usr/share/applications"
+ )
+ INSTALL(FILES
+ xtrkcad.png
+ DESTINATION "/usr/share/pixmaps"
+ )
+ENDIF(UNIX AND NOT APPLE) \ No newline at end of file
diff --git a/app/lib/Readme.md b/app/lib/Readme.md
index 297fd18..dfa904d 100644
--- a/app/lib/Readme.md
+++ b/app/lib/Readme.md
@@ -1,4 +1,4 @@
-# XTrackCAD 4.2.4a #
+# XTrackCAD 4.3.0 #
This file contains installation instructions and up-to-date information regarding XTrackCad.
@@ -39,6 +39,25 @@ you can find in the file COPYING.
## New features ##
+### Version 4.3.0 ###
+
+* Linux: Install xtrkcad.desktop and xtrkcad.png for desktop integration
+* All: Fix color button initialization
+* Add control and sensor types
+* Development of signal feature was finished
+* Add extra AppleHelp files
+* All: Add documentation for layout control elements
+* Write proper Describe, Move, and Rotate functions for Signals.
+* Add high lighting for signals.
+* Add AppleHelp bundle generation including index
+* First pass at high lighting layout control elements.
+* Linux/OSX: Set directory for rc file
+* All: Rework DXF export, add support for metric measurements
+* All: Add dynstring to build and modify DynstrMalloc interface
+* All: Add dynstring library and unit tests
+* All: enable unit testing with CMocka
+* Add Layout Control Element management dialog
+
### Version 4.2.4 ###
* All: Parameter file for Minitrains HOe-009-HOn30 Track System
* All: Improved and new parameter files Kato N and Super O
@@ -94,7 +113,46 @@ you can find in the file COPYING.
* Update help CSS to the Wiki's new default look
## Bugs fixed ##
+
+### Version 4.3.0 ###
+* All: Save and set user defined values for Text command
+* All: Fix path handling error after Save/Save As
+* All: Fix color button initialization
+* Fix Malloc error (wrong size in ReadBlock, causing Guard1 hose error)
+* Updated cblock.c and cswitchmotor.c to handle possible broken blocks and switchmotors and not crash (check for NULL pointers)
+* Bulletproof against undefined (NULL pointer) track segments in SwitchMotor code.
+* Bulletproof against undefined (NULL pointer) track segments in Block code.
+* Linux/OSX: Preparing for GTK3 migration, second set of changes
+* Clean up help files for Apple Help Indexer
+* Linux/OSX: Preparing for GTK3 migration, first set of changes
+* All: New and updated parameter files for Lego and Peco H0 Code 83
+* Linux/OSX: Add OSX specific files
+* Linux/OSX: Split help functions in generic and platform specific piece
+* Description: Correct some translation typos
+* Linux/OSX: Fix #163 GCC format-security errors
+* All: Update parameter file for Kuehn TT track
+* Add forward reference resolution for Blocks and Switchmotors
+* Cleanly delete blocks and switch motors when their tracks are deleted (avoid dangling pointers)
+* Updated Spec file
+* Expand help path name for longer bundle directories
+* Attempt to fix help files crash issue
+* Add GLIB Schemas to GTK-Bundle
+* All: Improved German translations
+* Update Readme for OSX package
+* Add support for gtk-mac-bundler
+* fix bugs in xtrkcad-bundler code
+* Fix parm dialog default for GTK builds
+* Add a post-build script for auto-creating OSX images
+* Remove failing copy command for gtk-bundle share
+* Linux/OSX: Fix uninitialized param file directory on first run
+* All: Add TTi scale / gauge
+* All: New paramter files for Frateschi HO and Auhagen TTi
+
### Version 4.2.4a ###
+* All: Update help
+* Linux: Installation from self extracting archive accepts install path
+* Linux/OSX: Remove absolute path from source packages
+* All: remove all dependencies on obsolete XTRKCAD_USE_LAYOUTCONTROL conditional
* All: New parameter file for Micro Engineering HOn3 Turnouts
* Windows: Fix bug 157 Crash on color change when drawing lines
* All: Updated parameter file for Kato N scale
@@ -242,19 +300,19 @@ self-installing program using the NSIS Installer from Nullsoft Inc.
Using Windows Explorer, locate the directory in which you downloaded or copied your new version of XTrackCAD.
Start the installation program by double clicking on the
-**[xtrkcad-setup-4.2.4.exe][]** file icon.
+**[xtrkcad-setup-4.3.0.exe][]** file icon.
Follow the steps in the installation program.
The installation lets you define the directory into which XTrackCAD is
installed. The directory is created automatically if it doesn't already exist.
-A program folder named XTrackCAD 4.2.4 will be created during the installation
+A program folder named XTrackCAD 4.3.0 will be created during the installation
process. This folder contains the program, documentation, parameter and
example files. An existing installation of earlier versions of XTrackCad is
not overwritten.
-A new program group named XTrackCad 4.2.4 will be created in the Start menu.
+A new program group named XTrackCad 4.3.0 will be created in the Start menu.
## Linux ##
@@ -269,7 +327,7 @@ Use your operating system's package manager to install XTrackCAD.
After downloading open a command line then
- ./xtrkcad-setup-4.2.4.x86_64.sh --prefix=/usr/local --exclude-subdir
+ ./xtrkcad-setup-4.3.0.x86_64.sh --prefix=/usr/local --exclude-subdir
This will install the executable in /usr/local/bin. A directory named
xtrkcad will be created in /usr/local/share and all files will be unpacked
diff --git a/app/lib/Readme.txt b/app/lib/Readme.txt
index e98f6d6..568b2e5 100644
--- a/app/lib/Readme.txt
+++ b/app/lib/Readme.txt
@@ -1,492 +1,559 @@
-
-
-XTRACKCAD 4.2.4A
-
-
-This file contains installation instructions and up-to-date information
-regarding XTrackCad.
-
-
-Contents
-
-- About XTrackCad
-- License Information
-- New features in this release
-- Installation
-- Upgrading from earlier releases
-- Bugs fixed
-- Building
-- Where to go for support
-
-
-About XTrackCad
-
-XTrackCad is a powerful CAD program for designing Model Railroad
-layouts.
-
-Some highlights:
-
-- Easy to use.
-- Supports any scale.
-- Supplied with parameter libraries for many popular brands of
- turnouts, plus the capability to define your own.
-- Automatic easement (spiral transition) curve calculation.
-- Extensive help files and video-clip demonstration mode.
-
-Availability: XTrkCad Fork is a project for further development of the
-original XTrkCad software. See the project homepage at
-http://www.xtrackcad.org/ for news and current releases.
-
-
-License Information
-
-COPYING:
-
-XTrackCad is copyrighted by Dave Bullis and Martin Fischer and licensed
-as free software under the terms of the GNU General Public License v2
-which you can find in the file COPYING.
-
-
-New features
-
-Version 4.2.4
-
-- All: Parameter file for Minitrains HOe-009-HOn30 Track System
-- All: Improved and new parameter files Kato N and Super O
-- All: Corrected parameter file for Peco HOn30/OO9 track
-- All: New parameter file for Peco HOn3 turnouts
-- All: New and updated parameter files for Z-scale
-- All: added a few more length formats
-- All: added additional zoom and marco zoom steps
-- All: Increase meximum number of layer buttons to 99
-- All: The parameter file dialog now allows loading and unloading
- several files together
-
-Version 4.2.3
-
-- All: updated German translations
-- All: TT Kuehn added items
-- Linux/OSX: New printing system
-- All: tomix-n.xtp Added or Updated multiple items
-- All: Add length format with six decimal places for English units
- (feature wish #33)
-- All: Feature Request #35: add hotkey for switching map window on and
- off
-- All: Make the installation's param directory the default on initial
- run
-- All: several new and updated parameter files
-- All: add Nm gauge and some Nm track parameters
-
-Version 4.2.2
-
-- All: Update German translations
-- All: extended parameter files fð² ‹ato HO and Walthers N structures
-- All: Added and extended parameter files
-- All: Add support for HOf scale/gauge and Busch track parameter files
-- Linux/OSX: Replace file selector dialog with newer file chooser
- dialog
-- All: Make editing of custom track work
-- All: Fix Atlas HO Code 100 parameter file
-- All: new Kato Unitrack N-Scale parameter file
-- All: add measurement units to train speed
-
-Version 4.2.1
-
-- Increase the number of layer buttons to 99
-- All: Update Eishindo T Gauge parameter file
-- All: Paste clipboard content at position of mouse pointer
-- All: Never mark curve centers of turnouts
-- All: Make drawing of center markings (crosshair) an user option
-- add ability to set text color when creating them
-- Windows: Draw and print crosshair to mark the center of an arc
-- Add the ability to change layers of a piece of track in the
- describe box.
-
-Version 4.2.0
-
-- New and updated parameter files and layout examples
-- Apply user preferences for dimensions to elevations
-- Add ability to update color of Text in properties
-- Fix compile problem on FreeBSD
-- Fix Oracle Solaris Studio 12.3 warnings
-- partially completed Brazilian Portuguese translation (57%)
-- Improve German translations
-- Merged webkit help system from Debian
-- Update help CSS to the Wiki's new default look
-
-
-Bugs fixed
-
-Version 4.2.4a
-
-- All: New parameter file for Micro Engineering HOn3 Turnouts
-- Windows: Fix bug 157 Crash on color change when drawing lines
-- All: Updated parameter file for Kato N scale
-- All: Fix build problem with block and switchmotor feature
-
-Version 4.2.4
-
-- Linux/OSX: Correct search order for config files
-- All: Layout control functions are always included
-- Linux/OSX: add a default file extension when none is present on save
-- Linux/OSX: Update package build
-- All: Fix compiler warnings for pointer to in casts on 64 bit systems
-- All: Correct file comments
-- All: Consistent spelling
-- All: Fix definition for Atlas Code 83 3/4" straight track
-
-Version 4.2.3b
-
-- Windows: Fix numeric overflow when reading layouts created on Linux
-- Linux/OSX: Fix crash when closing Train Control window
-- Linux/OSX: Fix crash when closing Change Elevation Window
-- All: new and improved parameter files for Tillig track
-
-Version 4.2.3a
-
-- Windows: Make UI translation work with directory structure of 64 bit
- Windows
-- Linux/OSX: Use defaults for printer and page settings on first run
-
-Version 4.2.3
-
-- All: Fix bug #143: Roco N Turnout 22247
-- All: fix invalid const variable usage
-- Linux/OSX: cairo is required and no longer optional
-- All: Fix bug #137 remove accelerator keys from block and switchmotor
- functions
-- All: Fixed wrapping of messages in status line
-- All: fix parameter files for On30
-- All: fix some compiler warnings
-- All: Fix bug #137 ie. crash on in intial run
-- All: fix possible signed / unsigned char problems
-- Windows: fix some compiler warnings
-
-Version 4.2.2
-
-- All: proper initialization of gauge on initial run
-- All: Added missing Language code header in Finnish and Brazilian
- Portuguese translations
-- Linux/MacOSX Fix for string conversion issues found using
- -Wformat-security default compiler flag on modern Linux distros
-- All: Bugfix: enable changing the layer of drawing elements from
- Describe dialog
-- All: Fix formatting of parts list, use monospace font on Linux and
- OSX
-- All: fix buffer overflow bug on overly long title lines (bug 120)
-- All: Fix memory violation bug on initial run of XTrackCAD
-- All: help and message fixes, load example directories on first start
-- All: Fix cmake backwards compatibility
-- All: Fix Backspace-Handling when field is emptied completly
-- All: Suppress warning from CMake versions 3.0
-- Linux: Additional files needed for Debian packages
-
-Version 4.2.1
-
-- All: Fix problem with blank line in American prototype file
-- All: fix one occurence if undo assert bug
-- All: Fix setting and getting minimum radius in Layout Options dialog
-- Windows: add round() missing in older Visual Studio versions
-- All: Fix locale problem with Export/Import
-- Linux/OSX: fix line width when printing
-- Linux/OSX: Add text rotation to gtk/cairo
-- Windows: Fix text rotation from Describe dialog
-- Fix initial HotBar Text Issue
-- Fix shift-modify abend
-- Fix redraw on Undo and Redo
-- All: fix bug 23 - make line width independent of zoom factor a
- creation time
-- Remove Ruler Text when selecting ruler button
-- Windows: Correct size calculation for radio buttons and checkboxes
-- Fix ghosts after delete
-- Fix modify
-- Fix ghost tracks and text on mac
-- Fix color stack protection bug
-- Windows Fix Bug 108: make sure that the line width is at least 1
-- ALL Fix bug 110: Proper error message on invalid scale in parameter
- file
-- Linux: Add valid ChangeLog to the RPM package
-- fix layerlist
-- Linux: Make RPM package generator work
-- Linux/OSX Draw and print crosshair to mark center of arc
-- ALL: Complete German translation for UI, messages and demos
-- Linux/OSX Fix bug 103: Icons are unreadable
-- Linux/OSX Fix bug 101: Print command fails with path+name > 42 chars
-- fix kato-n parameter file
-- Change the default input to be the same as the default output.
-- Correction to parameter file, Marklin 5119 is a Right not a Left
- turnout
-
-Version 4.2.0
-
-- Fix I18N on Windows
-- Fix bug 48: created invalid XPMs when many colors were used
-- Windows: associate application icon to xtc files
-- Fixed installation problem on Windows 7 when profile directory did
- not exist
-- Add math library libm to link library list.
-- sscanf extra format string parameter removed
-- Changed the font size used to print XtrackCAD in the engineering
- data box.
-- Update in app/README - correct instructions for Mercurial access
-- Fixed bug 3121382 - made menu item and dialog box labeling
- consistent for custom management
-- Fix bug 3310506, 3121372 (partly) - Minimum gauge is persisted,
- gauge is automatically selected in Layout Options
-- Fixed bug 3524218: print scale is shown correctly on print out.
-- Fixed bug 3468014 - build instructions for OSX in README have been
- updated
-- Fixed bug 3535258 - Broken PostScript in German locale
-- Fixed bug 3375218 - Odometer Reads A Multiple Of Locos
-- Fixed MSVC compile problem and added missing function to mswlib
-- Updated doxygen configuration file to doxygen version 1.8.2
-- Added code to properly determine the postscript fonts occurring in
- a document.
-- Fixed the syntax of the Document Structure Comments.
-- Circle line tangent/center were interchanged
-- Fix cairo text drawing bugs by forcing painting with
- frequent redraws.
-- Locale prefix change to conform to FHS (tracker bug 3049900)
-- Internationalization support added for help button text.
-- FIX: replaced hard-coded XTRKCAD_LOCALE_DIR path with 'locale' based
- on application library directory (XTRKCAD_LOCALE_DIR is defined at
- makefiles generation time and does not reflect the place where the
- application is actually installed)
-- FIX: now it should work with CMake-2.8.1
-- Get command line parameter handling correct
-- make load last layout option work
-- Pango version check at compile time
-- Block and Switchmotor updates
-- FIX: "Gauge" translation support
-- FIX: application crash due to a double value used as a "%*" sprintf.
- scenario is "Manage" -> "Parts List..." -> "Price" (checkbox).
-- Bug fix for setting the minimum radius
-- FIX: hotbar redraw too slow under gtk-quartz
-- FIX: linux still crashed due to a cairo context access after its
- drawable destruction
-- FIX: workaround for OSX with GTK-Quartz -> pixmaps are not rendered
- when using the mask; and replaced gtk_pixmap_new deprecated function
- with gtk_image_new_from_pixmap
-- FIX: crash when displaying a non utf8 string in balloon help
-- FIX: warning removed: pointer targets in passing argument 1 of
- 'strcpy' differ in signedness
-- FIX: removed GTK run-time references to /opt/local in root directory
-- FIX: removed remained Xlib dependencies and added gtk configuration
- files when generating the OSX bundle
-- FIX: image in about dialog box was not being displayed
-- FIX: deallocate PangoFontDescription using the right function
-- FIX: EXC_BAD_ACCESS when displaying about dialog
-- ENH: replace the old font select dialog with the GTK standard one,
- and some code cleanup
-- FIX - text in layout and selection were not aligned
-- New 'About' and new icons
-- Add source for new button icons
-- LINUX Desktop File
-- New application icon
-- Improved support for bitmaps
-- New tip of the day icon
-- Enhanced bitmap display control
-- Improve internationalization support, use simple gettext on Win32
-
-
-
-INSTALLATION
-
-
-Windows
-
-XTrackCad has only been tested on Windows 7.
-
-The MS-Windows version of XTrackCad is shipped as a self-extracting/
-self-installing program using the NSIS Installer from Nullsoft Inc.
-
-Using Windows Explorer, locate the directory in which you downloaded or
-copied your new version of XTrackCAD.
-
-Start the installation program by double clicking on the
-[XTRKCAD-SETUP-4.2.4.EXE][] file icon.
-
-Follow the steps in the installation program.
-
-The installation lets you define the directory into which XTrackCAD is
-installed. The directory is created automatically if it doesn't already
-exist.
-
-A program folder named XTrackCAD 4.2.4 will be created during the
-installation process. This folder contains the program, documentation,
-parameter and example files. An existing installation of earlier
-versions of XTrackCad is not overwritten.
-
-A new program group named XTrackCad 4.2.4 will be created in the Start
-menu.
-
-
-Linux
-
-XTrackCAD for LINUX is shipped as a RPM file and a self extracting
-archive. You will need libc6, X11R6, GTK+2.0, webkitgtk.
-
-Installing from the RPM package.
-
-Use your operating system's package manager to install XTrackCAD.
-
-Installing from the self-extracting archive.
-
-After downloading open a command line then
-
- ./xtrkcad-setup-4.2.4.x86_64.sh --prefix=/usr/local --exclude-subdir
-
-This will install the executable in /usr/local/bin. A directory named
-xtrkcad will be created in /usr/local/share and all files will be
-unpacked into it.
-
-If you install XTrackCAD into another directory, set the XTRKCADLIB
-environment variable to point to that directory.
-
-
-
-RELEASE INFO
-
-
-Upgrade Information
-
-The available options for number formats have been extended. Check your
-setting in Options>Preferences
-
-
-
-BUILDING
-
-
-Overview
-
-The following instructions detail building XTrackCAD using CMake. CMake
-is a cross-platform build system, available at http://www.cmake.org,
-that can be used to generate builds for a variety of build tools ranging
-from "make" to Visual Studio and XCode. Using CMake you can build
-XTrackCAD on Windows, GNU/Linux, and Mac OSX using the build tool(s) of
-your choice.
-
-Building XTrackCAD on GNU/Linux
-
-- Obtain the current sources from Mercurial; I assume that they are
- stored locally at "~/src/xtrkcad". Note that the correct URL for
- read-only access to Mercurial is
- http://xtrkcad-fork.hg.sourceforge.net:8000/hgroot/xtrkcad-fork/xtrkcad
-- Create a separate build directory; for these instructions I assume
- that your build directory is "~/build/xtrkcad".
-- Run CMake from the build directory, passing it the path to the
- source directory:
-
- $ cd ~/build/xtrkcad $ ccmake ~/src/xtrkcad
-
-- Press the "c" key to configure the build. After a few moments you
- will see four options to configure: CMAKE_BUILD_TYPE,
- CMAKE_INSTALL_PREFIX, XTRKCAD_USE_GTK, and XTRKCAD_USE_GTK_CAIRO.
-- Use CMAKE_BUILD_TYPE to control the build type. Enter "Debug" for a
- debug build, "Release" for a release build, etc.
-- Use CMAKE_INSTALL_PREFIX to control where the software will be
- installed. For this example, I assume "~/install/xtrkcad".
-- Use XTRKCAD_USE_GETTEXT to add new locales (language translations).
- Choose "OFF" to use XTrackCAD's default language (English). Refer to
- http://www.xtrkcad.org/Wikka/Internationalization for
- additional information.
-- Use XTRKCAD_USE_GTK to control the user-interface back-end. Choose
- "OFF" for Windows, "ON" for all other platforms.
-- Use XTRKCAD_USE_GTK_CAIRO to enable optional high-quality
- antialiased Cairo rendering for the GTK back-end. This option has no
- effect unless you are using the GTK back-end.
-- Use XTRKCAD_USE_DOXYGEN to enable the production of type, function,
- etc., documentation from the the source code. Requires doxygen if
- enabled. Enable if and only if you intend to hack on the code.
-- If you made any changes, press the "c" key again to update your
- new configuration.
-- Once everything is configured to your satisfaction, press the "g"
- key to generate makefiles for your build.
-- Compile XTrkCad using your new build:
-
- $ make
-
-- Install the new binary:
-
- $ make install
-
-- Run the installed binary:
-
- $ ~/install/xtrkcad/bin/xtrkcad
-
-- If XTRKCAD_USE_DOXYGEN was enabled:
-
- $ make docs-doxygen
-
-to create the internals documentation. Read this documentation by
-pointing your web browser at
-~/build/xtrkcad/docs/doxygen/html/index.html.
-
-Building XTrackCAD on Mac OSX
-
-- You will need to install the following dependencies - I recommend
- using http://www.macports.org to obtain them:
-- GTK2
-- webkit
-- gnome-icon-theme
-- Once the prerequisites are installed the build instructions are the
- same as for the GNU/Linux build, above.
-- Remember that to run XTrackCAD on OSX, you need to have X11 running
- with your DISPLAY set.
-
-Building XTrackCAD on Windows
-
-- Obtain the current sources from Mercurial; I assume that they are
- stored locally at "c:/src/xtrkcad". Note that the correct URL for
- read-only access to Mercurial is
- http://xtrkcad-fork.hg.sourceforge.net:8000/hgroot/xtrkcad-fork/xtrkcad
-- Use the Windows Start menu to run CMake (cmake-gui).
-- Specify the source and build directories in the CMake window. You
- must provide a build directory outside the source tree - I
- use "c:/build/xtrkcad".
-- Press the "Configure" button to configure the build. You will be
- prompted for the type of build to generate. Choose your desired
- tool - I used "Visual Studio 10". After a few moments you will see
- three options to configure: CMAKE_INSTALL_PREFIX, XTRKCAD_USE_GTK,
- and XTRKCAD_USE_GTK_CAIRO.
-- Use CMAKE_INSTALL_PREFIX to control where the software will be
- installed. The default "c:/Program Files/XTrkCAD" is a good choice.
-- Use XTRKCAD_USE_GETTEXT to add new locales (language translations).
- Choose "OFF" to use XTrackCAD's default language (English). Refer to
- http://www.xtrkcad.org/Wikka/Internationalization for
- additional information.
-- Use XTRKCAD_USE_GTK to control the user-interface back-end. Choose
- "OFF" for Windows.
-- Use XTRKCAD_USE_GTK_CAIRO to enable optional high-quality
- antialiased Cairo rendering for the GTK back-end. This option has no
- effect unless on Windows.
-- Use XTRKCAD_USE_DOXYGEN to enable the production of type, function,
- etc., documentation from the the source code. Requires doxygen if
- enabled. Enable if and only if you intend to hack on the code.
-- If you made any changes, press the "Configure" button again to
- update your new configuration.
-- Once everything is configured to your satisfaction, press the "OK"
- button to generate project files for your build.
-- Compile XTrackCad using the new project files. For example, start
- MSVC and open the "XTrkCAD.sln" solution file which is located in
- your build directory.
-- Build the "BUILD_ALL" project to build the software.
-- Build the "INSTALL" project to install the software.
-- Run XTrackCAD by double-clicking its icon located in the install
- directory - for example: c:/Program Files/XTrkCAD/bin/xtrkcad.exe.
-
-
-Where to go for support
-
-The following web addresses will be helpful for any questions or bug
-reports
-
-- The Yahoo!Group mailing list
- http://groups.yahoo.com/projects/XTrkCad
-- The project website for the open source development
- http://www.xtrackcad.org/
-- The official Sourceforge site
- http://www.sourceforge.net/groups/xtrkcad-fork/
-
-Thanks for your interest in XTrackCAD.
+
+
+XTRACKCAD 4.3.0
+
+
+This file contains installation instructions and up-to-date information
+regarding XTrackCad.
+
+
+Contents
+
+- About XTrackCad
+- License Information
+- New features in this release
+- Installation
+- Upgrading from earlier releases
+- Bugs fixed
+- Building
+- Where to go for support
+
+
+About XTrackCad
+
+XTrackCad is a powerful CAD program for designing Model Railroad
+layouts.
+
+Some highlights:
+
+- Easy to use.
+- Supports any scale.
+- Supplied with parameter libraries for many popular brands of
+ turnouts, plus the capability to define your own.
+- Automatic easement (spiral transition) curve calculation.
+- Extensive help files and video-clip demonstration mode.
+
+Availability: XTrkCad Fork is a project for further development of the
+original XTrkCad software. See the project homepage at
+http://www.xtrackcad.org/ for news and current releases.
+
+
+License Information
+
+COPYING:
+
+XTrackCad is copyrighted by Dave Bullis and Martin Fischer and licensed
+as free software under the terms of the GNU General Public License v2
+which you can find in the file COPYING.
+
+
+New features
+
+Version 4.3.0
+
+- Linux: Install xtrkcad.desktop and xtrkcad.png for desktop
+ integration
+- All: Fix color button initialization
+- Add control and sensor types
+- Development of signal feature was finished
+- Add extra AppleHelp files
+- All: Add documentation for layout control elements
+- Write proper Describe, Move, and Rotate functions for Signals.
+- Add high lighting for signals.
+- Add AppleHelp bundle generation including index
+- First pass at high lighting layout control elements.
+- Linux/OSX: Set directory for rc file
+- All: Rework DXF export, add support for metric measurements
+- All: Add dynstring to build and modify DynstrMalloc interface
+- All: Add dynstring library and unit tests
+- All: enable unit testing with CMocka
+- Add Layout Control Element management dialog
+
+Version 4.2.4
+
+- All: Parameter file for Minitrains HOe-009-HOn30 Track System
+- All: Improved and new parameter files Kato N and Super O
+- All: Corrected parameter file for Peco HOn30/OO9 track
+- All: New parameter file for Peco HOn3 turnouts
+- All: New and updated parameter files for Z-scale
+- All: added a few more length formats
+- All: added additional zoom and marco zoom steps
+- All: Increase meximum number of layer buttons to 99
+- All: The parameter file dialog now allows loading and unloading
+ several files together
+
+Version 4.2.3
+
+- All: updated German translations
+- All: TT Kuehn added items
+- Linux/OSX: New printing system
+- All: tomix-n.xtp Added or Updated multiple items
+- All: Add length format with six decimal places for English units
+ (feature wish #33)
+- All: Feature Request #35: add hotkey for switching map window on and
+ off
+- All: Make the installation's param directory the default on initial
+ run
+- All: several new and updated parameter files
+- All: add Nm gauge and some Nm track parameters
+
+Version 4.2.2
+
+- All: Update German translations
+- All: extended parameter files fð² ‹ato HO and Walthers N structures
+- All: Added and extended parameter files
+- All: Add support for HOf scale/gauge and Busch track parameter files
+- Linux/OSX: Replace file selector dialog with newer file chooser
+ dialog
+- All: Make editing of custom track work
+- All: Fix Atlas HO Code 100 parameter file
+- All: new Kato Unitrack N-Scale parameter file
+- All: add measurement units to train speed
+
+Version 4.2.1
+
+- Increase the number of layer buttons to 99
+- All: Update Eishindo T Gauge parameter file
+- All: Paste clipboard content at position of mouse pointer
+- All: Never mark curve centers of turnouts
+- All: Make drawing of center markings (crosshair) an user option
+- add ability to set text color when creating them
+- Windows: Draw and print crosshair to mark the center of an arc
+- Add the ability to change layers of a piece of track in the
+ describe box.
+
+Version 4.2.0
+
+- New and updated parameter files and layout examples
+- Apply user preferences for dimensions to elevations
+- Add ability to update color of Text in properties
+- Fix compile problem on FreeBSD
+- Fix Oracle Solaris Studio 12.3 warnings
+- partially completed Brazilian Portuguese translation (57%)
+- Improve German translations
+- Merged webkit help system from Debian
+- Update help CSS to the Wiki's new default look
+
+
+Bugs fixed
+
+Version 4.3.0
+
+- All: Save and set user defined values for Text command
+- All: Fix path handling error after Save/Save As
+- All: Fix color button initialization
+- Fix Malloc error (wrong size in ReadBlock, causing Guard1
+ hose error)
+- Updated cblock.c and cswitchmotor.c to handle possible broken blocks
+ and switchmotors and not crash (check for NULL pointers)
+- Bulletproof against undefined (NULL pointer) track segments in
+ SwitchMotor code.
+- Bulletproof against undefined (NULL pointer) track segments in
+ Block code.
+- Linux/OSX: Preparing for GTK3 migration, second set of changes
+- Clean up help files for Apple Help Indexer
+- Linux/OSX: Preparing for GTK3 migration, first set of changes
+- All: New and updated parameter files for Lego and Peco H0 Code 83
+- Linux/OSX: Add OSX specific files
+- Linux/OSX: Split help functions in generic and platform specific
+ piece
+- Description: Correct some translation typos
+- Linux/OSX: Fix #163 GCC format-security errors
+- All: Update parameter file for Kuehn TT track
+- Add forward reference resolution for Blocks and Switchmotors
+- Cleanly delete blocks and switch motors when their tracks are
+ deleted (avoid dangling pointers)
+- Updated Spec file
+- Expand help path name for longer bundle directories
+- Attempt to fix help files crash issue
+- Add GLIB Schemas to GTK-Bundle
+- All: Improved German translations
+- Update Readme for OSX package
+- Add support for gtk-mac-bundler
+- fix bugs in xtrkcad-bundler code
+- Fix parm dialog default for GTK builds
+- Add a post-build script for auto-creating OSX images
+- Remove failing copy command for gtk-bundle share
+- Linux/OSX: Fix uninitialized param file directory on first run
+- All: Add TTi scale / gauge
+- All: New paramter files for Frateschi HO and Auhagen TTi
+
+Version 4.2.4a
+
+- All: Update help
+- Linux: Installation from self extracting archive accepts install
+ path
+- Linux/OSX: Remove absolute path from source packages
+- All: remove all dependencies on obsolete XTRKCAD_USE_LAYOUTCONTROL
+ conditional
+- All: New parameter file for Micro Engineering HOn3 Turnouts
+- Windows: Fix bug 157 Crash on color change when drawing lines
+- All: Updated parameter file for Kato N scale
+- All: Fix build problem with block and switchmotor feature
+
+Version 4.2.4
+
+- Linux/OSX: Correct search order for config files
+- All: Layout control functions are always included
+- Linux/OSX: add a default file extension when none is present on save
+- Linux/OSX: Update package build
+- All: Fix compiler warnings for pointer to in casts on 64 bit systems
+- All: Correct file comments
+- All: Consistent spelling
+- All: Fix definition for Atlas Code 83 3/4" straight track
+
+Version 4.2.3b
+
+- Windows: Fix numeric overflow when reading layouts created on Linux
+- Linux/OSX: Fix crash when closing Train Control window
+- Linux/OSX: Fix crash when closing Change Elevation Window
+- All: new and improved parameter files for Tillig track
+
+Version 4.2.3a
+
+- Windows: Make UI translation work with directory structure of 64 bit
+ Windows
+- Linux/OSX: Use defaults for printer and page settings on first run
+
+Version 4.2.3
+
+- All: Fix bug #143: Roco N Turnout 22247
+- All: fix invalid const variable usage
+- Linux/OSX: cairo is required and no longer optional
+- All: Fix bug #137 remove accelerator keys from block and switchmotor
+ functions
+- All: Fixed wrapping of messages in status line
+- All: fix parameter files for On30
+- All: fix some compiler warnings
+- All: Fix bug #137 ie. crash on in intial run
+- All: fix possible signed / unsigned char problems
+- Windows: fix some compiler warnings
+
+Version 4.2.2
+
+- All: proper initialization of gauge on initial run
+- All: Added missing Language code header in Finnish and Brazilian
+ Portuguese translations
+- Linux/MacOSX Fix for string conversion issues found using
+ -Wformat-security default compiler flag on modern Linux distros
+- All: Bugfix: enable changing the layer of drawing elements from
+ Describe dialog
+- All: Fix formatting of parts list, use monospace font on Linux and
+ OSX
+- All: fix buffer overflow bug on overly long title lines (bug 120)
+- All: Fix memory violation bug on initial run of XTrackCAD
+- All: help and message fixes, load example directories on first start
+- All: Fix cmake backwards compatibility
+- All: Fix Backspace-Handling when field is emptied completly
+- All: Suppress warning from CMake versions 3.0
+- Linux: Additional files needed for Debian packages
+
+Version 4.2.1
+
+- All: Fix problem with blank line in American prototype file
+- All: fix one occurence if undo assert bug
+- All: Fix setting and getting minimum radius in Layout Options dialog
+- Windows: add round() missing in older Visual Studio versions
+- All: Fix locale problem with Export/Import
+- Linux/OSX: fix line width when printing
+- Linux/OSX: Add text rotation to gtk/cairo
+- Windows: Fix text rotation from Describe dialog
+- Fix initial HotBar Text Issue
+- Fix shift-modify abend
+- Fix redraw on Undo and Redo
+- All: fix bug 23 - make line width independent of zoom factor a
+ creation time
+- Remove Ruler Text when selecting ruler button
+- Windows: Correct size calculation for radio buttons and checkboxes
+- Fix ghosts after delete
+- Fix modify
+- Fix ghost tracks and text on mac
+- Fix color stack protection bug
+- Windows Fix Bug 108: make sure that the line width is at least 1
+- ALL Fix bug 110: Proper error message on invalid scale in parameter
+ file
+- Linux: Add valid ChangeLog to the RPM package
+- fix layerlist
+- Linux: Make RPM package generator work
+- Linux/OSX Draw and print crosshair to mark center of arc
+- ALL: Complete German translation for UI, messages and demos
+- Linux/OSX Fix bug 103: Icons are unreadable
+- Linux/OSX Fix bug 101: Print command fails with path+name > 42 chars
+- fix kato-n parameter file
+- Change the default input to be the same as the default output.
+- Correction to parameter file, Marklin 5119 is a Right not a Left
+ turnout
+
+Version 4.2.0
+
+- Fix I18N on Windows
+- Fix bug 48: created invalid XPMs when many colors were used
+- Windows: associate application icon to xtc files
+- Fixed installation problem on Windows 7 when profile directory did
+ not exist
+- Add math library libm to link library list.
+- sscanf extra format string parameter removed
+- Changed the font size used to print XtrackCAD in the engineering
+ data box.
+- Update in app/README - correct instructions for Mercurial access
+- Fixed bug 3121382 - made menu item and dialog box labeling
+ consistent for custom management
+- Fix bug 3310506, 3121372 (partly) - Minimum gauge is persisted,
+ gauge is automatically selected in Layout Options
+- Fixed bug 3524218: print scale is shown correctly on print out.
+- Fixed bug 3468014 - build instructions for OSX in README have been
+ updated
+- Fixed bug 3535258 - Broken PostScript in German locale
+- Fixed bug 3375218 - Odometer Reads A Multiple Of Locos
+- Fixed MSVC compile problem and added missing function to mswlib
+- Updated doxygen configuration file to doxygen version 1.8.2
+- Added code to properly determine the postscript fonts occurring in
+ a document.
+- Fixed the syntax of the Document Structure Comments.
+- Circle line tangent/center were interchanged
+- Fix cairo text drawing bugs by forcing painting with
+ frequent redraws.
+- Locale prefix change to conform to FHS (tracker bug 3049900)
+- Internationalization support added for help button text.
+- FIX: replaced hard-coded XTRKCAD_LOCALE_DIR path with 'locale' based
+ on application library directory (XTRKCAD_LOCALE_DIR is defined at
+ makefiles generation time and does not reflect the place where the
+ application is actually installed)
+- FIX: now it should work with CMake-2.8.1
+- Get command line parameter handling correct
+- make load last layout option work
+- Pango version check at compile time
+- Block and Switchmotor updates
+- FIX: "Gauge" translation support
+- FIX: application crash due to a double value used as a "%*" sprintf.
+ scenario is "Manage" -> "Parts List..." -> "Price" (checkbox).
+- Bug fix for setting the minimum radius
+- FIX: hotbar redraw too slow under gtk-quartz
+- FIX: linux still crashed due to a cairo context access after its
+ drawable destruction
+- FIX: workaround for OSX with GTK-Quartz -> pixmaps are not rendered
+ when using the mask; and replaced gtk_pixmap_new deprecated function
+ with gtk_image_new_from_pixmap
+- FIX: crash when displaying a non utf8 string in balloon help
+- FIX: warning removed: pointer targets in passing argument 1 of
+ 'strcpy' differ in signedness
+- FIX: removed GTK run-time references to /opt/local in root directory
+- FIX: removed remained Xlib dependencies and added gtk configuration
+ files when generating the OSX bundle
+- FIX: image in about dialog box was not being displayed
+- FIX: deallocate PangoFontDescription using the right function
+- FIX: EXC_BAD_ACCESS when displaying about dialog
+- ENH: replace the old font select dialog with the GTK standard one,
+ and some code cleanup
+- FIX - text in layout and selection were not aligned
+- New 'About' and new icons
+- Add source for new button icons
+- LINUX Desktop File
+- New application icon
+- Improved support for bitmaps
+- New tip of the day icon
+- Enhanced bitmap display control
+- Improve internationalization support, use simple gettext on Win32
+
+
+
+INSTALLATION
+
+
+Windows
+
+XTrackCad has only been tested on Windows 7.
+
+The MS-Windows version of XTrackCad is shipped as a self-extracting/
+self-installing program using the NSIS Installer from Nullsoft Inc.
+
+Using Windows Explorer, locate the directory in which you downloaded or
+copied your new version of XTrackCAD.
+
+Start the installation program by double clicking on the
+[XTRKCAD-SETUP-4.3.0.EXE][] file icon.
+
+Follow the steps in the installation program.
+
+The installation lets you define the directory into which XTrackCAD is
+installed. The directory is created automatically if it doesn't already
+exist.
+
+A program folder named XTrackCAD 4.3.0 will be created during the
+installation process. This folder contains the program, documentation,
+parameter and example files. An existing installation of earlier
+versions of XTrackCad is not overwritten.
+
+A new program group named XTrackCad 4.3.0 will be created in the Start
+menu.
+
+
+Linux
+
+XTrackCAD for LINUX is shipped as a RPM file and a self extracting
+archive. You will need libc6, X11R6, GTK+2.0, webkitgtk.
+
+Installing from the RPM package.
+
+Use your operating system's package manager to install XTrackCAD.
+
+Installing from the self-extracting archive.
+
+After downloading open a command line then
+
+ ./xtrkcad-setup-4.3.0.x86_64.sh --prefix=/usr/local --exclude-subdir
+
+This will install the executable in /usr/local/bin. A directory named
+xtrkcad will be created in /usr/local/share and all files will be
+unpacked into it.
+
+If you install XTrackCAD into another directory, set the XTRKCADLIB
+environment variable to point to that directory.
+
+
+
+RELEASE INFO
+
+
+Upgrade Information
+
+The available options for number formats have been extended. Check your
+setting in Options>Preferences
+
+
+
+BUILDING
+
+
+Overview
+
+The following instructions detail building XTrackCAD using CMake. CMake
+is a cross-platform build system, available at http://www.cmake.org,
+that can be used to generate builds for a variety of build tools ranging
+from "make" to Visual Studio and XCode. Using CMake you can build
+XTrackCAD on Windows, GNU/Linux, and Mac OSX using the build tool(s) of
+your choice.
+
+Building XTrackCAD on GNU/Linux
+
+- Obtain the current sources from Mercurial; I assume that they are
+ stored locally at "~/src/xtrkcad". Note that the correct URL for
+ read-only access to Mercurial is
+ http://xtrkcad-fork.hg.sourceforge.net:8000/hgroot/xtrkcad-fork/xtrkcad
+- Create a separate build directory; for these instructions I assume
+ that your build directory is "~/build/xtrkcad".
+- Run CMake from the build directory, passing it the path to the
+ source directory:
+
+ $ cd ~/build/xtrkcad $ ccmake ~/src/xtrkcad
+
+- Press the "c" key to configure the build. After a few moments you
+ will see four options to configure: CMAKE_BUILD_TYPE,
+ CMAKE_INSTALL_PREFIX, XTRKCAD_USE_GTK, and XTRKCAD_USE_GTK_CAIRO.
+- Use CMAKE_BUILD_TYPE to control the build type. Enter "Debug" for a
+ debug build, "Release" for a release build, etc.
+- Use CMAKE_INSTALL_PREFIX to control where the software will be
+ installed. For this example, I assume "~/install/xtrkcad".
+- Use XTRKCAD_USE_GETTEXT to add new locales (language translations).
+ Choose "OFF" to use XTrackCAD's default language (English). Refer to
+ http://www.xtrkcad.org/Wikka/Internationalization for
+ additional information.
+- Use XTRKCAD_USE_GTK to control the user-interface back-end. Choose
+ "OFF" for Windows, "ON" for all other platforms.
+- Use XTRKCAD_USE_GTK_CAIRO to enable optional high-quality
+ antialiased Cairo rendering for the GTK back-end. This option has no
+ effect unless you are using the GTK back-end.
+- Use XTRKCAD_USE_DOXYGEN to enable the production of type, function,
+ etc., documentation from the the source code. Requires doxygen if
+ enabled. Enable if and only if you intend to hack on the code.
+- If you made any changes, press the "c" key again to update your
+ new configuration.
+- Once everything is configured to your satisfaction, press the "g"
+ key to generate makefiles for your build.
+- Compile XTrkCad using your new build:
+
+ $ make
+
+- Install the new binary:
+
+ $ make install
+
+- Run the installed binary:
+
+ $ ~/install/xtrkcad/bin/xtrkcad
+
+- If XTRKCAD_USE_DOXYGEN was enabled:
+
+ $ make docs-doxygen
+
+to create the internals documentation. Read this documentation by
+pointing your web browser at
+~/build/xtrkcad/docs/doxygen/html/index.html.
+
+Building XTrackCAD on Mac OSX
+
+- You will need to install the following dependencies - I recommend
+ using http://www.macports.org to obtain them:
+- GTK2
+- webkit
+- gnome-icon-theme
+- Once the prerequisites are installed the build instructions are the
+ same as for the GNU/Linux build, above.
+- Remember that to run XTrackCAD on OSX, you need to have X11 running
+ with your DISPLAY set.
+
+Building XTrackCAD on Windows
+
+- Obtain the current sources from Mercurial; I assume that they are
+ stored locally at "c:/src/xtrkcad". Note that the correct URL for
+ read-only access to Mercurial is
+ http://xtrkcad-fork.hg.sourceforge.net:8000/hgroot/xtrkcad-fork/xtrkcad
+- Use the Windows Start menu to run CMake (cmake-gui).
+- Specify the source and build directories in the CMake window. You
+ must provide a build directory outside the source tree - I
+ use "c:/build/xtrkcad".
+- Press the "Configure" button to configure the build. You will be
+ prompted for the type of build to generate. Choose your desired
+ tool - I used "Visual Studio 10". After a few moments you will see
+ three options to configure: CMAKE_INSTALL_PREFIX, XTRKCAD_USE_GTK,
+ and XTRKCAD_USE_GTK_CAIRO.
+- Use CMAKE_INSTALL_PREFIX to control where the software will be
+ installed. The default "c:/Program Files/XTrkCAD" is a good choice.
+- Use XTRKCAD_USE_GETTEXT to add new locales (language translations).
+ Choose "OFF" to use XTrackCAD's default language (English). Refer to
+ http://www.xtrkcad.org/Wikka/Internationalization for
+ additional information.
+- Use XTRKCAD_USE_GTK to control the user-interface back-end. Choose
+ "OFF" for Windows.
+- Use XTRKCAD_USE_GTK_CAIRO to enable optional high-quality
+ antialiased Cairo rendering for the GTK back-end. This option has no
+ effect unless on Windows.
+- Use XTRKCAD_USE_DOXYGEN to enable the production of type, function,
+ etc., documentation from the the source code. Requires doxygen if
+ enabled. Enable if and only if you intend to hack on the code.
+- If you made any changes, press the "Configure" button again to
+ update your new configuration.
+- Once everything is configured to your satisfaction, press the "OK"
+ button to generate project files for your build.
+- Compile XTrackCad using the new project files. For example, start
+ MSVC and open the "XTrkCAD.sln" solution file which is located in
+ your build directory.
+- Build the "BUILD_ALL" project to build the software.
+- Build the "INSTALL" project to install the software.
+- Run XTrackCAD by double-clicking its icon located in the install
+ directory - for example: c:/Program Files/XTrkCAD/bin/xtrkcad.exe.
+
+
+Where to go for support
+
+The following web addresses will be helpful for any questions or bug
+reports
+
+- The Yahoo!Group mailing list
+ http://groups.yahoo.com/projects/XTrkCad
+- The project website for the open source development
+ http://www.xtrackcad.org/
+- The official Sourceforge site
+ http://www.sourceforge.net/groups/xtrkcad-fork/
+
+Thanks for your interest in XTrackCAD.
diff --git a/app/lib/astylerc b/app/lib/astylerc
new file mode 100644
index 0000000..e0815ce
--- /dev/null
+++ b/app/lib/astylerc
@@ -0,0 +1,8 @@
+style=1tbs
+break-blocks
+unpad-paren
+pad-header
+max-code-length=80
+break-after-logical
+mode=c
+
diff --git a/app/lib/params/HO-Frateschi.xtp b/app/lib/params/HO-Frateschi.xtp
new file mode 100644
index 0000000..60b63eb
--- /dev/null
+++ b/app/lib/params/HO-Frateschi.xtp
@@ -0,0 +1,196 @@
+CONTENTS Frateschi HO Track
+SUBCONTENTS Frateschi HO Track - Straight
+TURNOUT HO "Frateschi HO Track Straight 880mm 4880/4980"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 34.645669 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 34.645669 0.000000
+END
+TURNOUT HO "Frateschi HO Track Straight 220mm 4220/4920"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 8.661417 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 8.661417 0.000000
+END
+TURNOUT HO "Frateschi HO Track Straight 110mm 4110/4910"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 4.330709 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 4.330709 0.000000
+END
+TURNOUT HO "Frateschi HO Track Straight 55mm 4055/4955"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 2.165354 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 2.165354 0.000000
+END
+TURNOUT HO "Frateschi HO Track Straight(old geometry) 45mm 4045"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.771654 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 1.771654 0.000000
+END
+SUBCONTENTS Frateschi HO Track - Misc
+TURNOUT HO "Frateschi HO Track Uncoupler Straight 110mm 4110D/4910D"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 4.330709 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 4.330709 0.000000
+ F 0 0.000000 4
+ 1.443570 0.250000 0
+ 2.887139 0.250000 0
+ 2.887139 -0.250000 0
+ 1.443570 -0.250000 0
+END
+STRUCTURE HO "Frateschi HO Track Bumper 1525"
+ X pier 0.000000 "B"
+ L 0 0.100000 0.000000 0.300000 -1.000000 0.300000
+ L 0 0.100000 -0.500000 0.600000 -0.500000 -0.600000
+ L 0 0.100000 0.000000 -0.300000 -1.000000 -0.300000
+END
+SUBCONTENTS Frateschi HO Track - Curve
+TURNOUT HO "Frateschi HO Track Curve 360mm 30° 4188/4988"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 7.086614 -1.898853 120.000000
+ C 0 0.000000 14.173228 0.000000 -14.173228 0.000000 30.000000
+END
+TURNOUT HO "Frateschi HO Track Curve 418mm 30° 4219/4919"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 8.228346 -2.204779 120.000000
+ C 0 0.000000 16.456693 0.000000 -16.456693 0.000000 30.000000
+END
+TURNOUT HO "Frateschi HO Track Curve 480mm 20° 4166/4966"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.463373 -1.139667 110.000000
+ C 0 0.000000 18.897638 0.000000 -18.897638 0.000000 20.000000
+END
+TURNOUT HO "Frateschi HO Track Curve 480mm 10° 4083/4983"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 3.281540 -0.287098 100.000000
+ C 0 0.000000 18.897638 0.000000 -18.897638 0.000000 10.000000
+END
+TURNOUT HO "Frateschi HO Track Curve(old) 482mm 20° 4166"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.490304 -1.144416 110.000000
+ C 0 0.000000 18.976378 0.000000 -18.976378 0.000000 20.000000
+END
+TURNOUT HO "Frateschi HO Track Curve(old) 482mm 10° 4083"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 3.295213 -0.288294 100.000000
+ C 0 0.000000 18.976378 0.000000 -18.976378 0.000000 10.000000
+END
+SUBCONTENTS Frateschi HO Track - Turnouts
+TURNOUT HO "Frateschi HO Track Left Remote Turnout 4200L/4900L"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 8.661417 0.000000 90.000000
+ E 8.661417 1.141732 75.000000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 8.661417 0.000000
+ C 0 0.000000 -28.490603 0.649638 28.490603 164.999924 15.000152
+ S 0 0.000000 8.023578 0.970812 8.661417 1.141732
+ F 0 0.000000 6
+ 2.887139 -0.600000 0
+ 5.774278 -0.600000 0
+ 5.774278 -1.050000 0
+ 5.574278 -1.250000 0
+ 3.087139 -1.250000 0
+ 2.887139 -1.050000 0
+END
+TURNOUT HO "Frateschi HO Track Curve 850mm 15° 4222/4922"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 8.661267 -1.140277 105.000000
+ C 0 0.000000 33.464567 0.000000 -33.464567 0.000000 15.000000
+END
+TURNOUT HO "Frateschi HO Track Right Remote Turnout 4200R/4900R"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 8.661417 0.000000 90.000000
+ E 8.661417 -1.141732 105.000000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 8.661417 0.000000
+ C 0 0.000000 28.490603 0.649487 -28.490603 0.000076 15.000152
+ S 0 0.000000 8.023578 -0.970812 8.661417 -1.141732
+ F 0 0.000000 6
+ 2.887139 0.600000 0
+ 5.774278 0.600000 0
+ 5.774278 1.050000 0
+ 5.574278 1.250000 0
+ 3.087139 1.250000 0
+ 2.887139 1.050000 0
+END
+TURNOUT HO "Frateschi HO Track Left Turnout (OLD) 4165L"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 6.496063 0.000000 90.000000
+ E 6.496063 1.144416 70.000000
+ S 0 0.000000 0.000000 0.000000 0.655402 0.000000
+ S 0 0.000000 0.655402 0.000000 6.496063 0.000000
+ C 0 0.000000 -15.292205 0.655422 15.292205 159.999924 20.000152
+ S 0 0.000000 5.885678 0.922245 6.496063 1.144416
+END
+TURNOUT HO "Frateschi HO Track Right Turnout (OLD) 4165R"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 6.496063 0.000000 90.000000
+ E 6.496063 -1.144416 110.000000
+ S 0 0.000000 0.000000 0.000000 0.655402 0.000000
+ S 0 0.000000 0.655402 0.000000 6.496063 0.000000
+ C 0 0.000000 15.292205 0.655341 -15.292205 0.000076 20.000152
+ S 0 0.000000 5.885678 -0.922245 6.496063 -1.144416
+END
+SUBCONTENTS Frateschi HO Track - TurnTable
+TURNOUT HO "Frateschi Turntable 220mm 20d 4500"
+ P "1" 1
+ P "2" 2
+ P "3" 3
+ P "4" 4
+ P "5" 5
+ P "6" 6
+ P "7" 7
+ P "8" 8
+ P "9" 9
+ E 0.000000 0.000000 180.000000
+ E 0.000000 4.330709 0.000000
+ E 1.481190 4.069535 20.000000
+ E 2.783726 3.317515 40.000000
+ E 3.750504 2.165354 60.000000
+ E 4.264915 0.752020 80.000000
+ E 4.264915 -0.752020 100.000000
+ E 3.750504 -2.165354 120.000000
+ E 2.783726 -3.317515 140.000000
+ E 1.481190 -4.069535 160.000000
+ E 0.000000 -4.330709 180.000000
+ E -1.481190 -4.069535 200.000000
+ E -2.783726 -3.317515 220.000000
+ E -3.750504 -2.165354 240.000000
+ E -4.264915 -0.752020 260.000000
+ E -4.264915 0.752020 280.000000
+ E -3.750504 2.165354 300.000000
+ E -2.783726 3.317515 320.000000
+ E -1.481190 4.069535 340.000000
+ S 16777215 0 0.000000 4.330709 0.000000 -4.330709
+ S 16777215 0 1.481190 4.069535 -1.481190 -4.069535
+ S 16777215 0 2.783726 3.317515 -2.783726 -3.317515
+ S 16777215 0 3.750504 2.165354 -3.750504 -2.165354
+ S 16777215 0 4.264915 0.752020 -4.264915 -0.752020
+ S 16777215 0 4.264915 -0.752020 -4.264915 0.752020
+ S 16777215 0 3.750504 -2.165354 -3.750504 2.165354
+ S 16777215 0 2.783726 -3.317515 -2.783726 3.317515
+ S 16777215 0 1.481190 -4.069535 -1.481190 4.069535
+ A 0 0.031250 4.330709 0.000000 0.000000 0.000000 360.000000
+ A 0 0.031250 5.080709 0.000000 0.000000 0.000000 360.000000
+ A 0 0.031250 1.377727 0.000000 0.000000 0.000000 360.000000
+ G 0 0.000000 0.750000 0.000000 0.000000 0.000000 360.000000
+END \ No newline at end of file
diff --git a/app/lib/params/HOn3-BlackStoneProTraxx.xtp b/app/lib/params/HOn3-BlackStoneProTraxx.xtp
new file mode 100644
index 0000000..d47e2b8
--- /dev/null
+++ b/app/lib/params/HOn3-BlackStoneProTraxx.xtp
@@ -0,0 +1,21 @@
+CONTENTS Blackstone ProTraxx HOn3 Snap-Track
+
+SUBCONTENTS Blackstone ProTraxx HOn3 Snap-Track - Straight Track
+TURNOUT HOn3 "ProTraxx HOn3 Snap-Track Straight 6.535 228mm B500100"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 8.976378 0.000000 90.000000
+ S 0 0 0.000000 0.000000 8.976378 0.000000
+ L 11579568 0.053333 0.000000 0.629921 8.976378 0.629921
+ L 11579568 0.053333 0.000000 -0.629921 8.976378 -0.629921
+END
+
+SUBCONTENTS Blackstone ProTraxx HOn3 Snap-Track - Curve Track
+TURNOUT HOn3 "ProTraxx HOn3 Snap-Track Curve 18.90R 480mm 22.5° B500200"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 7.231813 -1.438497 112.500000
+ C 0 0 18.897638 0.000000 -18.897638 0.000000 22.500000
+ A 11579568 0.053333 18.267717 0.000000 -18.897638 0.000000 22.500000
+ A 11579568 0.053333 19.527559 0.000000 -18.897638 0.000000 22.500000
+END
diff --git a/app/lib/params/Lego-Track.xtp b/app/lib/params/Lego-Track.xtp
new file mode 100644
index 0000000..784635a
--- /dev/null
+++ b/app/lib/params/Lego-Track.xtp
@@ -0,0 +1,152 @@
+CONTENTS Lego Track Components
+# Created By Dwyane Ward 01Jan2013
+
+SUBCONTENTS Lego - 9V Track
+TURNOUT LEGO "Lego Straight Track (9V) 2865/4515"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.039370 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 5.039370 0.000000
+ END
+TURNOUT LEGO "Lego Curve Track (9V) 28674520"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 4.821209 0.958998 67.500000
+ C 0 0.000000 -12.598425 0.000000 12.598425 157.500000 22.500000
+ END
+TURNOUT LEGO "Lego Crossing Track (9V) 320874519"
+ P "Normal" 1 0 2
+ E 0.000000 0.000000 270.000000
+ E 5.039370 0.000000 90.000000
+ E 2.519692 2.519685 0.000000
+ E 2.519678 -2.519685 180.000000
+ S 0 0.000000 0.000000 0.000000 5.039370 0.000000
+ S 0 0.000000 2.519692 2.519685 2.519678 -2.519685
+ END
+TURNOUT LEGO "Lego Left Switch (9V) 2861/4531"
+ P "P0" 1 5 4 3
+ P "P1" 2
+ E 0.000000 0.000000 270.000000
+ E 10.078740 -0.000027 90.000000
+ E 10.236648 4.068369 67.500000
+ C 0 0.000000 -6.377953 0.000017 6.377953 166.446760 13.553240
+ S 0 0.000000 0.000000 0.000000 10.078740 -0.000027
+ C 0 0.000000 6.377953 12.677383 -1.824092 323.058181 14.441819
+ C 0 0.000000 -15.666120 -0.571293 15.794471 143.057808 23.388952
+ S 0 0.000000 1.494665 0.177605 3.100081 0.564621
+ END
+TURNOUT LEGO "Lego Right Switch (9V) 2859/4531"
+ P "P0" 1 5 4 3
+ P "P1" 2
+ E 0.000000 0.000000 269.999924
+ E 10.078723 0.000000 90.000000
+ E -0.157881 4.068390 292.500000
+ C 0 0.000000 6.377953 10.078740 6.377953 180.000000 13.553240
+ S 0 0.000000 10.078740 0.000000 0.000000 0.000000
+ C 0 0.000000 -6.377953 -2.598648 -1.824058 22.500000 14.441819
+ C 0 0.000000 15.666120 10.650075 15.794470 193.553240 23.388952
+ S 0 0.000000 8.584076 0.177609 6.978661 0.564629
+ END
+
+SUBCONTENTS Lego - 12V Track
+TURNOUT LEGO "Lego Straight Track (12V) 3242"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.039370 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 5.039370 0.000000
+ END
+TURNOUT LEGO "Lego Curve Track (12V) 3241"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 4.821209 0.958998 67.500000
+ C 0 0.000000 -12.598425 0.000000 12.598425 157.500000 22.500000
+ END
+TURNOUT LEGO "Lego Crossing Track (12V) 3232"
+ P "Normal" 1 0 2
+ E 0.000000 0.000000 270.000000
+ E 5.039370 0.000000 90.000000
+ E 2.519692 2.519685 360.000000
+ E 2.519678 -2.519685 180.000000
+ S 0 0.000000 0.000000 0.000000 5.039370 0.000000
+ S 0 0.000000 2.519692 2.519685 2.519678 -2.519685
+ END
+TURNOUT LEGO "Lego Left Switch (12V) 73697/7859"
+ P "P0" 1
+ P "P1" 2 3 4
+ E 0.000000 0.000000 270.000000
+ E 10.078740 2.519685 90.000000
+ E 10.078740 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 10.078740 0.000000
+ C 0 0.000000 -10.236220 0.000000 10.236220 156.774050 23.225950
+ S 0 0.000000 4.036786 0.829585 6.042006 1.690111
+ C 0 0.000000 10.236220 10.078740 -7.716535 336.774050 23.225950
+ END
+TURNOUT LEGO "Lego Right Switch (12V) 73696/7859"
+ P "P0" 1
+ P "P1" 2 3 4
+ E 0.000000 0.000000 270.000000
+ E 0.000000 2.519685 270.000000
+ E 10.078740 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 10.078740 0.000000
+ C 0 0.000000 10.236220 10.078740 10.236220 180.000000 23.225950
+ S 0 0.000000 6.042006 0.829585 4.036787 1.690111
+ C 0 0.000000 -10.236220 0.000000 -7.716535 0.000000 23.225950
+ END
+
+SUBCONTENTS Lego - RC Track
+TURNOUT LEGO "Lego Straight Track (RC) 53401"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.039370 0.000000 90.000000
+ S 0 0.000000 0.000000 0.000000 5.039370 0.000000
+ END
+TURNOUT LEGO "Lego Curve Track (RC) 53400"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 4.821209 0.958998 67.500000
+ C 0 0.000000 -12.598425 0.000000 12.598425 157.500000 22.500000
+ END
+TURNOUT LEGO "Lego Left Switch (RC) 53407"
+ P "P0" 1 5 4 3
+ P "P1" 2
+ E 0.000000 0.000000 270.000000
+ E 10.078740 -0.000027 90.000000
+ E 10.236648 4.068369 67.500000
+ C 0 0.000000 -6.377953 0.000017 6.377953 166.446760 13.553240
+ S 0 0.000000 0.000000 0.000000 10.078740 -0.000027
+ C 0 0.000000 6.377953 12.677383 -1.824092 323.058181 14.441819
+ C 0 0.000000 -15.666120 -0.571293 15.794471 143.057808 23.388952
+ S 0 0.000000 1.494665 0.177605 3.100081 0.564621
+ END
+TURNOUT LEGO "Lego Right Switch (RC) 53404"
+ P "P0" 1 5 4 3
+ P "P1" 2
+ E 0.000000 0.000000 269.999924
+ E 10.078723 0.000000 90.000000
+ E -0.157881 4.068390 292.500000
+ C 0 0.000000 6.377953 10.078740 6.377953 180.000000 13.553240
+ S 0 0.000000 10.078740 0.000000 0.000000 0.000000
+ C 0 0.000000 -6.377953 -2.598648 -1.824058 22.500000 14.441819
+ C 0 0.000000 15.666120 10.650075 15.794470 193.553240 23.388952
+ S 0 0.000000 8.584076 0.177609 6.978661 0.564629
+ END
+TURNOUT LEGO "Lego Double Crossover (RC) 60128"
+ P "Normal" 1 2 3 0 4 5 6
+ P "Reverse" 1 7 8 9 6 0 4 10 11 12 3
+ E 0.000000 0.000000 270.000000
+ E 15.118110 0.000000 90.000000
+ E 0.000000 5.039370 270.000000
+ E 15.118110 5.039370 90.000000
+ S 0 0.000000 0.000000 0.000000 2.220991 0.000000
+ S 0 0.000000 2.220991 0.000000 12.897119 0.000000
+ S 0 0.000000 12.897119 0.000000 15.118110 0.000000
+ S 0 0.000000 0.000000 5.039370 2.220991 5.039370
+ S 0 0.000000 2.220991 5.039370 12.897119 5.039370
+ S 0 0.000000 12.897119 5.039370 15.118110 5.039370
+ C 0 0.000000 -6.425198 2.221000 6.425198 139.921630 40.078446
+ S 0 0.000000 6.357761 1.508868 8.760349 3.530502
+ C 0 0.000000 6.425198 12.897126 -1.385823 319.921630 40.078446
+ C 0 0.000000 6.425198 2.220966 -1.385828 0.000076 40.078446
+ S 0 0.000000 6.357761 3.530502 8.760349 1.508868
+ C 0 0.000000 -6.425198 12.897126 6.425193 180.000076 40.078446
+ END
diff --git a/app/lib/params/S-MTH S-Trax.xtp b/app/lib/params/S-MTH S-Trax.xtp
new file mode 100644
index 0000000..964c2a9
--- /dev/null
+++ b/app/lib/params/S-MTH S-Trax.xtp
@@ -0,0 +1,156 @@
+CONTENTS MTH S-Trax S Scale Track
+SUBCONTENTS MTH S-Trax S Scale Track - Straight Track
+TURNOUT S "MTH S-Trax 5"" Straight 35-1003"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+END
+TURNOUT S "MTH S-Trax 10"" Straight 35-1002"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 10.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 10.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 10.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 10.000000 -1.281250
+END
+TURNOUT S "MTH S-Trax 15"" Straight 35-1001"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 15.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 15.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 15.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 15.000000 -1.281250
+END
+TURNOUT S "MTH S-Trax 40"" Flex Straight 35-1004/5"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 40.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 40.000000 0.000000
+END
+
+SUBCONTENTS MTH S-Trax S Scale Track - Curve Track
+TURNOUT S "MTH S-Trax 20"" 30D Curve 35-1006"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 10.000000 -2.679492 120.000000
+ C 0 0 20.000000 0.000000 -20.000000 0.000000 30.000000
+ A 11579568 0.053333 21.281250 0.000000 -20.000000 0.000000 30.000000
+ A 11579568 0.053333 18.718750 0.000000 -20.000000 0.000000 30.000000
+END
+TURNOUT S "MTH S-Trax 20"" 15D Curve 35-1007"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.176381 -0.681483 105.000000
+ C 0 0 20.000000 0.000000 -20.000000 0.000000 15.000000
+ A 11579568 0.053333 21.281250 0.000000 -20.000000 0.000000 15.000000
+ A 11579568 0.053333 18.718750 0.000000 -20.000000 0.000000 15.000000
+END
+TURNOUT S "MTH S-Trax 25"" 30D Curve 35-1008"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 12.500000 -3.349365 120.000000
+ C 0 0 25.000000 0.000000 -25.000000 0.000000 30.000000
+ A 11579568 0.053333 26.281250 0.000000 -25.000000 0.000000 30.000000
+ A 11579568 0.053333 23.718750 0.000000 -25.000000 0.000000 30.000000
+END
+TURNOUT S "MTH S-Trax 25"" 15D Curve 35-1009"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.470476 -0.851854 105.000000
+ C 0 0 25.000000 0.000000 -25.000000 0.000000 15.000000
+ A 11579568 0.053333 26.281250 0.000000 -25.000000 0.000000 15.000000
+ A 11579568 0.053333 23.718750 0.000000 -25.000000 0.000000 15.000000
+END
+TURNOUT S "MTH S-Trax 30"" 30D Curve 35-1010"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 15.000000 -4.019238 120.000000
+ C 0 0 30.000000 0.000000 -30.000000 0.000000 30.000000
+ A 11579568 0.053333 31.281250 0.000000 -30.000000 0.000000 30.000000
+ A 11579568 0.053333 28.718750 0.000000 -30.000000 0.000000 30.000000
+END
+TURNOUT S "MTH S-Trax 30"" 15D Curve 35-1011"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 7.764571 -1.022225 105.000000
+ C 0 0 30.000000 0.000000 -30.000000 0.000000 15.000000
+ A 11579568 0.053333 31.281250 0.000000 -30.000000 0.000000 15.000000
+ A 11579568 0.053333 28.718750 0.000000 -30.000000 0.000000 15.000000
+END
+
+SUBCONTENTS MTH S-Trax S Scale Track - Misc Track
+TURNOUT S "MTH S-Trax 5"" Bumper 35-1021"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 6.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 6.000000 -1.281250
+ L 11579568 0.053333 6.000000 1.281250 6.000000 -1.281250
+ L 0 0.070000 4.000000 0.000000 5.000000 0.437000
+ L 0 0.070000 4.000000 0.000000 5.000000 -0.437000
+ L 0 0.070000 4.000000 0.437000 4.000000 -0.437000
+END
+TURNOUT S "MTH S-Trax 5"" Uncoupler 35-1022"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+ L 11579568 0.053333 1.000000 0.000000 4.000000 0.000000
+ F 12566463 0.000000 4
+ 1.000000 0.250000 0
+ 1.500000 0.250000 0
+ 1.500000 -0.250000 0
+ 1.000000 -0.250000 0
+ F 12566463 0.000000 4
+ 3.500000 0.250000 0
+ 4.000000 0.250000 0
+ 4.000000 -0.250000 0
+ 3.500000 -0.250000 0
+END
+TURNOUT S "MTH S-Trax 5"" Acc. Operator 35-1023"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+END
+
+SUBCONTENTS MTH S-Trax S Scale Track - Turnout
+TURNOUT S "MTH S-Trax #3 Left Turnout 35-1019"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 10.000000 0.000000 90.000000
+ E 10.000000 2.500000 60.000000
+ S 0 0.000000 0.000000 0.000000 1.543918 0.000000
+ S 0 0.000000 1.543918 0.000000 10.000000 0.000000
+ C 0 0.000000 -15.398371 1.543938 15.398371 149.999924 30.000152
+ S 0 0.000000 9.243132 2.063007 10.000000 2.500000
+ L 11579568 0.053333 -0.000003 -1.281250 9.999997 -1.281239
+ L 11579568 0.053333 0.000000 1.281250 1.543918 1.281252
+ A 11579568 0.053333 14.117121 1.543938 15.398371 149.999924 30.000152
+ L 11579568 0.053333 10.356817 1.226543 10.640643 1.390415
+ L 11579568 0.053333 8.602493 3.172594 9.359360 3.609587
+END
+TURNOUT S "MTH S-Trax #3 Right Turnout 35-1018"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 10.000000 0.000000 90.000000
+ E 10.000000 -2.500000 120.000000
+ S 0 0.000000 0.000000 0.000000 1.543918 0.000000
+ S 0 0.000000 1.543918 0.000000 10.000000 0.000000
+ C 0 0.000000 15.398371 1.543856 -15.398371 0.000076 30.000152
+ S 0 0.000000 9.243132 -2.063007 10.000000 -2.500000
+ L 11579568 0.053333 -0.000003 -1.281250 1.543914 -1.281248
+ L 11579568 0.053333 0.000000 1.281250 10.000000 1.281261
+ A 11579568 0.053333 14.117121 1.543856 -15.398371 0.000076 30.000152
+ L 11579568 0.053333 8.602487 -3.172591 9.359354 -3.609583
+ L 11579568 0.053333 10.356817 -1.226543 10.640643 -1.390415
+END \ No newline at end of file
diff --git a/app/lib/params/S-SHelper S-Trax.xtp b/app/lib/params/S-SHelper S-Trax.xtp
new file mode 100644
index 0000000..5be8270
--- /dev/null
+++ b/app/lib/params/S-SHelper S-Trax.xtp
@@ -0,0 +1,200 @@
+CONTENTS S Helper Showcase Line Code 131 S Scale
+SUBCONTENTS S Helper Showcase Line Code 131 - Straight Track
+TURNOUT S "S Helper Showcase Line C131 5"" Straight 297"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+ END
+TURNOUT S "S Helper Showcase Line C131 10"" Straight 258"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 10.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 10.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 10.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 10.000000 -1.281250
+ END
+TURNOUT S "S Helper Showcase Line C131 15"" Straight 257"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 15.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 15.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 15.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 15.000000 -1.281250
+ END
+TURNOUT S "S Helper Showcase Line C131 36"" Straight 465"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 36.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 36.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 36.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 36.000000 -1.281250
+ END
+
+SUBCONTENTS S Helper Showcase Line Code 131 - Curve Track
+TURNOUT S "S Helper Showcase Line C131 20"" 30D Curve 259"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 10.000000 -2.679492 120.000000
+ C 0 0 20.000000 0.000000 -20.000000 0.000000 30.000000
+ A 11579568 0.053333 21.281250 0.000000 -20.000000 0.000000 30.000000
+ A 11579568 0.053333 18.718750 0.000000 -20.000000 0.000000 30.000000
+ END
+TURNOUT S "S Helper Showcase Line C131 20"" 15D Curve 291"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.176381 -0.681483 105.000000
+ C 0 0 20.000000 0.000000 -20.000000 0.000000 15.000000
+ A 11579568 0.053333 21.281250 0.000000 -20.000000 0.000000 15.000000
+ A 11579568 0.053333 18.718750 0.000000 -20.000000 0.000000 15.000000
+ END
+TURNOUT S "S Helper Showcase Line C131 25"" 30D Curve 292"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 12.500000 -3.349365 120.000000
+ C 0 0 25.000000 0.000000 -25.000000 0.000000 30.000000
+ A 11579568 0.053333 26.281250 0.000000 -25.000000 0.000000 30.000000
+ A 11579568 0.053333 23.718750 0.000000 -25.000000 0.000000 30.000000
+ END
+TURNOUT S "S Helper Showcase Line C131 25"" 15D Curve 293"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.470476 -0.851854 105.000000
+ C 0 0 25.000000 0.000000 -25.000000 0.000000 15.000000
+ A 11579568 0.053333 26.281250 0.000000 -25.000000 0.000000 15.000000
+ A 11579568 0.053333 23.718750 0.000000 -25.000000 0.000000 15.000000
+ END
+TURNOUT S "S Helper Showcase Line C131 30"" 30D Curve 294"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 15.000000 -4.019238 120.000000
+ C 0 0 30.000000 0.000000 -30.000000 0.000000 30.000000
+ A 11579568 0.053333 31.281250 0.000000 -30.000000 0.000000 30.000000
+ A 11579568 0.053333 28.718750 0.000000 -30.000000 0.000000 30.000000
+ END
+TURNOUT S "S Helper Showcase Line C131 30"" 15D Curve 296"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 7.764571 -1.022225 105.000000
+ C 0 0 30.000000 0.000000 -30.000000 0.000000 15.000000
+ A 11579568 0.053333 31.281250 0.000000 -30.000000 0.000000 15.000000
+ A 11579568 0.053333 28.718750 0.000000 -30.000000 0.000000 15.000000
+ END
+
+
+SUBCONTENTS S Helper Showcase Line Code 131 - Crossings
+TURNOUT S "S Helper Showcase Line C131 5"" 90D Crossing 467"
+ P "Normal" 1 0 2
+ E 0.000000 0.000000 270.000000
+ E 5.000000 0.000000 90.000000
+ E 2.500000 2.500000 0.000000
+ E 2.500000 -2.500000 180.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ S 0 0 2.500000 2.500000 2.500000 -2.500000
+ L 11579568 0.053333 0.000000 1.281250 1.218750 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 1.218750 -1.281250
+ L 11579568 0.053333 3.781250 1.281250 5.000000 1.281250
+ L 11579568 0.053333 3.781250 -1.281250 5.000000 -1.281250
+ L 11579568 0.053333 1.218750 2.500000 1.218750 1.281250
+ L 11579568 0.053333 3.781250 2.500000 3.781250 1.281250
+ L 11579568 0.053333 1.218750 -1.281250 1.218750 -2.500000
+ L 11579568 0.053333 3.781250 -1.281250 3.781250 -2.500000
+ END
+
+
+
+SUBCONTENTS S Helper Showcase Line Code 131 - Misc Track
+TURNOUT S "S Helper Showcase Line C131 5"" LED Bumper 468"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ S 0 0 0.000000 0.000000 4.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+ L 11579568 0.053333 5.000000 1.281250 5.000000 -1.281250
+ L 0 0.053333 3.126000 0.437000 4.000000 0.437000
+ L 0 0.053333 3.126000 -0.437000 4.000000 -0.437000
+ L 0 0.053333 4.000000 0.437000 4.000000 -0.437000
+ L 0 0.053333 3.126000 0.437000 3.126000 -0.437000
+ L 0 0.053333 3.126000 0.437000 4.000000 -0.437000
+ L 0 0.053333 3.126000 -0.437000 4.000000 0.437000
+ G 16711680 0.000000 0.150000 3.563000 0.000000 0
+ END
+TURNOUT S "S Helper Showcase Line C131 5"" Bumper 926"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ S 0 0 0.000000 0.000000 4.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+ L 11579568 0.053333 5.000000 1.281250 5.000000 -1.281250
+ L 0 0.053333 3.126000 0.437000 4.000000 0.437000
+ L 0 0.053333 3.126000 -0.437000 4.000000 -0.437000
+ L 0 0.053333 4.000000 0.437000 4.000000 -0.437000
+ L 0 0.053333 3.126000 0.437000 3.126000 -0.437000
+ L 0 0.053333 3.126000 0.437000 4.000000 -0.437000
+ L 0 0.053333 3.126000 -0.437000 4.000000 0.437000
+ END
+TURNOUT S "S Helper Showcase Line C131 5"" Uncoupler 670"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+ L 11579568 0.053333 1.000000 0.000000 4.000000 0.000000
+ F 12566463 0.000000 4
+ 1.000000 0.250000 0
+ 1.500000 0.250000 0
+ 1.500000 -0.250000 0
+ 1.000000 -0.250000 0
+ F 12566463 0.000000 4
+ 3.500000 0.250000 0
+ 4.000000 0.250000 0
+ 4.000000 -0.250000 0
+ 3.500000 -0.250000 0
+ END
+TURNOUT S "S Helper Showcase Line C131 5"" Third Rail 671"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.000000 0.000000 90.000000
+ S 0 0 0.000000 0.000000 5.000000 0.000000
+ L 11579568 0.053333 0.000000 1.281250 5.000000 1.281250
+ L 11579568 0.053333 0.000000 -1.281250 5.000000 -1.281250
+ L 0 0.053333 0.000000 1.281250 5.000000 1.281250
+ END
+
+
+SUBCONTENTS S Helper Showcase Line Code 131 - Turnout
+TURNOUT S "S Helper Showcase Line #3 Left Turnout 299"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 10.000000 0.000000 90.000000
+ E 10.000000 2.500000 60.000000
+ S 0 0.000000 0.000000 0.000000 1.543918 0.000000
+ S 0 0.000000 1.543918 0.000000 10.000000 0.000000
+ C 0 0.000000 -15.398371 1.543938 15.398371 149.999924 30.000152
+ S 0 0.000000 9.243132 2.063007 10.000000 2.500000
+ L 11579568 0.053333 -0.000003 -1.281250 10.000000 -1.281239
+ L 11579568 0.053333 0.000000 1.281250 1.543918 1.281252
+ A 11579568 0.053333 14.117121 1.543938 15.398371 150.000000 30.000000
+ L 11579568 0.053333 10.356817 1.226543 10.640643 1.390415
+ L 11579568 0.053333 8.602493 3.172594 9.359360 3.609587
+ END
+TURNOUT S "S Helper Showcase Line #3 Right Turnout 298"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 10.000000 0.000000 90.000000
+ E 10.000000 -2.500000 120.000000
+ S 0 0.000000 0.000000 0.000000 1.543918 0.000000
+ S 0 0.000000 1.543918 0.000000 10.000000 0.000000
+ C 0 0.000000 15.398371 1.543856 -15.398371 0.000076 30.000152
+ S 0 0.000000 9.243132 -2.063007 10.000000 -2.500000
+ L 11579568 0.053333 -0.000003 -1.281250 1.543914 -1.281248
+ L 11579568 0.053333 0.000000 1.281250 10.000000 1.281261
+ A 11579568 0.053333 14.117121 1.543856 -15.398371 0.000000 30.000000
+ L 11579568 0.053333 8.602487 -3.172591 9.359354 -3.609583
+ L 11579568 0.053333 10.356817 -1.226543 10.640643 -1.390415
+END \ No newline at end of file
diff --git a/app/lib/params/TT-Kuehn.xtp b/app/lib/params/TT-Kuehn.xtp
index 12585a5..a71f195 100644
--- a/app/lib/params/TT-Kuehn.xtp
+++ b/app/lib/params/TT-Kuehn.xtp
@@ -56,16 +56,16 @@ TURNOUT TT "Kuehn Track R2 Curve 14.37R 365mm 10° 72210"
E 2.495338 -0.218314 100.000000
C 0 0 14.370079 0.000000 -14.370079 0.000000 10.000000
END
-TURNOUT TT "Kuehn Track R2 Curve 14.37R 353mm 20° 72220"
+TURNOUT TT "Kuehn Track R2 Curve 14.37R 365mm 20° 72220"
P "Normal" 1
E 0.000000 0.000000 270.000000
E 4.914856 -0.866622 110.000000
C 0 0 14.370079 0.000000 -14.370079 0.000000 20.000000
END
-TURNOUT TT "Kuehn Track R2 Curve 14.37R 353mm 30° 72230"
+TURNOUT TT "Kuehn Track R2 Curve 14.37R 365mm 30° 72230"
P "Normal" 1
E 0.000000 0.000000 270.000000
- E 7.1185039 -1.925225 120.000000
+ E 7.1850394 -1.925225 120.000000
C 0 0 14.370079 0.000000 -14.370079 0.000000 30.000000
END
diff --git a/app/lib/params/TTi-AuhagenNG.xtp b/app/lib/params/TTi-AuhagenNG.xtp
new file mode 100644
index 0000000..4dc194c
--- /dev/null
+++ b/app/lib/params/TTi-AuhagenNG.xtp
@@ -0,0 +1,40 @@
+CONTENTS Auhagen Narrow Gauge TT Scale Track System
+SUBCONTENTS Auhagen TTi Narrow Gauge Track - Straight Track
+TURNOUT TTi "Auhagen TTi Track G44 Straight 1.65 41.7mm 43700-1"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.641732 0.000000 90.000000
+ S 0 0 0.000000 0.000000 1.641732 0.000000
+ END
+
+SUBCONTENTS Auhagen TTi Narrow Gauge Track - Curve Track
+TURNOUT TTi "Auhagen TTi Track Curve 1.65R 42mm 30° 43700-2"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 0.820866 -0.219950 120.000000
+ C 0 0 1.641732 0.000000 -1.641732 0.000000 30.000000
+ END
+
+SUBCONTENTS Auhagen TTi Narrow Gauge Track - Turnouts
+TURNOUT TTi "Auhagen TTi Track Left Turnout 43700-3"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 1.212598 0.000000 90.000000
+ E 1.212598 0.437530 60.000000
+ S 0 0.000000 0.000000 0.000000 0.177000 0.000000
+ S 0 0.000000 0.177000 0.000000 1.212598 0.000000
+ C 0 0.000000 -1.036677 0.177001 1.036677 149.999924 30.000152
+ S 0 0.000000 0.695340 0.138889 1.212598 0.437530
+ END
+TURNOUT TTi "Auhagen TTi Track Right Turnout 43700-4"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 1.212598 0.000000 90.000000
+ E 1.212598 -0.437530 120.000000
+ S 0 0.000000 0.000000 0.000000 0.177000 0.000000
+ S 0 0.000000 0.177000 0.000000 1.212598 0.000000
+ C 0 0.000000 1.036677 0.176996 -1.036677 0.000076 30.000152
+ S 0 0.000000 0.695340 -0.138889 1.212598 -0.437530
+ END
diff --git a/app/lib/params/TilligAdvTT.xtp b/app/lib/params/TilligAdvTT.xtp
index 20d085e..b9ddf8b 100644
--- a/app/lib/params/TilligAdvTT.xtp
+++ b/app/lib/params/TilligAdvTT.xtp
@@ -1,304 +1,323 @@
-CONTENTS Pilz/Tillig Advance Track System
-SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Straight Track
-TURNOUT TT "Pilz/Tillig Track G1 Straight 6.535 166mm 83101"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 6.535433 0.000000 90.000000
- S 0 0 0.000000 0.000000 6.535433 0.000000
- END
-TURNOUT TT "Pilz/Tillig Track G2 Straight 3.268 83mm 83102"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 3.267717 0.000000 90.000000
- S 0 0 0.000000 0.000000 3.267717 0.000000
- END
-TURNOUT TT "Pilz/Tillig Track G3 Straight 1.692 43mm 83105"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 1.692913 0.000000 90.000000
- S 0 0 0.000000 0.000000 1.692913 0.000000
- END
-TURNOUT TT "Pilz/Tillig Track G4 Straight 1.633 41.5mm 83103"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 1.633858 0.000000 90.000000
- S 0 0 0.000000 0.000000 1.633858 0.000000
- END
-TURNOUT TT "Pilz/Tillig Track G5 Straight 1.437 36.5mm 83104"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 1.437008 0.000000 90.000000
- S 0 0 0.000000 0.000000 1.437008 0.000000
- END
-TURNOUT TT "Pilz/Tillig Track Adapter Track 2.244 57mm 83132"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 2.244094 0.000000 90.000000
- S 0 0 0.000000 0.000000 2.244094 0.000000
- END
-
-SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Curve Track
-TURNOUT TT "Pilz/Tillig Track R01 Curve 10.51R 267mm 30° 83116"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 5.255906 -1.408316 120.000000
- C 0 0 10.511811 0.000000 -10.511811 0.000000 30.000000
- END
-TURNOUT TT "Pilz/Tillig Track R04 Curve 10.51R 267mm 7.5° 83115"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 1.372067 -0.089930 97.500000
- C 0 0 10.511811 0.000000 -10.511811 0.000000 7.500000
- END
-TURNOUT TT "Pilz/Tillig Track R11 Curve 12.20R 310mm 30° 83109"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 6.102362 -1.635123 120.000000
- C 0 0 12.204724 0.000000 -12.204724 0.000000 30.000000
- END
-TURNOUT TT "Pilz/Tillig Track R12 Curve 12.20R 310mm 15° 83110"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 3.158815 -0.415866 105.000000
- C 0 0 12.204724 0.000000 -12.204724 0.000000 15.000000
- END
-TURNOUT TT "Pilz/Tillig Track R14 Curve 12.20R 310mm 7.5° 83113"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 1.593036 -0.104413 97.500000
- C 0 0 12.204724 0.000000 -12.204724 0.000000 7.500000
- END
-TURNOUT TT "Pilz/Tillig Track R21 Curve 13.89R 353mm 30° 83106"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 6.948819 -1.861930 120.000000
- C 0 0 13.897638 0.000000 -13.897638 0.000000 30.000000
- END
-TURNOUT TT "Pilz/Tillig Track R22 Curve 13.89R 353mm 15° 83107"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 3.596973 -0.473551 105.000000
- C 0 0 13.897638 0.000000 -13.897638 0.000000 15.000000
- END
-TURNOUT TT "Pilz/Tillig Track R24 Curve 13.89R 353mm 7.5° 83114"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 1.814006 -0.118896 97.500000
- C 0 0 13.897638 0.000000 -13.897638 0.000000 7.500000
- END
-TURNOUT TT "Pilz/Tillig Track R31 Curve 15.59R 396mm 30° 83111"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 7.795276 -2.088738 120.000000
- C 0 0 15.590551 0.000000 -15.590551 0.000000 30.000000
- END
-TURNOUT TT "Pilz/Tillig Track R32 Curve 15.59R 396mm 15° 83112"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 4.035132 -0.531235 105.000000
- C 0 0 15.590551 0.000000 -15.590551 0.000000 15.000000
- END
-
-SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Function Track
-TURNOUT TT "Pilz/Tillig Track Straight Feeder 6.535 166mm 83149"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 6.535433 0.000000 90.000000
- S 0 0 0.000000 0.000000 6.535433 0.000000
- F 11579568 0.000000 4
- 0.500000 -0.500000 0
- 1.000000 -0.500000 0
- 1.000000 -1.000000 0
- 0.500000 -1.000000 0
- END
-TURNOUT TT "Pilz/Tillig Track Uncouple Track 3.268 83mm 83201"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 3.267717 0.000000 90.000000
- S 0 0 0.000000 0.000000 3.267717 0.000000
- F 11579568 0.000000 4
- 0.000000 -0.500000 0
- 2.750000 -0.500000 0
- 2.750000 -1.000000 0
- 0.000000 -1.000000 0
- F 11579568 0.000000 4
- 0.5000000 -0.200000 0
- 2.750000 -0.200000 0
- 2.750000 0.200000 0
- 0.500000 0.2000000 0
- END
-TURNOUT TT "Pilz/Tillig Track Isolation Track 1.633 41.5mm 83150"
- P "Normal" 1
- E 0.000000 0.000000 270.000000
- E 1.633858 0.000000 90.000000
- S 0 0 0.000000 0.000000 1.633858 0.000000
- END
-
-SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Turnouts
-TURNOUT TT "Tillig EW1-left 83322"
- P "Normal" 1
- P "Reverse" 2 3
- E 0.000000 0.000000 270.000000
- E 5.098425 0.000000 90.000000
- E 4.985016 0.845476 75.000000
- S 0 0.000000 0.000000 0.000000 5.098425 0.000000
- C 0 0.000000 -13.897638 0.000000 13.897638 165.000000 15.000000
- S 0 0.000000 3.596973 0.473551 4.985016 0.845476
- END
-TURNOUT TT "Tillig EW1-right 83321"
- P "Normal" 1
- P "Reverse" 2 3
- E 0.000000 0.000000 270.000000
- E 5.098425 0.000000 90.000000
- E 4.985016 -0.845476 105.000000
- S 0 0.000000 0.000000 0.000000 5.098425 0.000000
- C 0 0.000000 13.897638 0.000000 -13.897638 0.000000 15.000000
- S 0 0.000000 3.596973 -0.473551 4.985016 -0.845476
- END
-TURNOUT TT "Tillig EW2-left 83322"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 6.535433 0.000000 90.000000
- E 6.429717 0.846488 75.000000
- S 0 0.000000 0.000000 0.000000 0.472063 0.000000
- S 0 0.000000 0.472063 0.000000 6.535433 0.000000
- C 0 0.000000 -21.257102 0.472091 21.257102 164.999924 15.000152
- S 0 0.000000 5.973856 0.724332 6.429717 0.846488
- END
-TURNOUT TT "Tillig EW2-right 83321"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 6.535433 0.000000 90.000000
- E 6.429717 -0.846488 105.000000
- S 0 0.000000 0.000000 0.000000 0.472063 0.000000
- S 0 0.000000 0.472063 0.000000 6.535433 0.000000
- C 0 0.000000 21.257102 0.471978 -21.257102 0.000076 15.000152
- S 0 0.000000 5.973856 -0.724332 6.429717 -0.846488
- END
-TURNOUT TT "Tillig EW3-left 83342"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 8.149606 0.000000 90.000000
- E 8.054532 0.846565 78.000000
- S 0 0.000000 0.000000 0.000000 0.472100 0.000000
- S 0 0.000000 0.472100 0.000000 8.149606 0.000000
- C 0 0.000000 -34.248932 0.472145 34.248932 167.999924 12.000152
- S 0 0.000000 7.592936 0.748439 8.054532 0.846565
- END
-TURNOUT TT "Tillig EW3-right 83341"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 8.149606 0.000000 90.000000
- E 8.054532 -0.846565 102.000000
- S 0 0.000000 0.000000 0.000000 0.472100 0.000000
- S 0 0.000000 0.472100 0.000000 8.149606 0.000000
- C 0 0.000000 34.248932 0.471964 -34.248932 0.000076 12.000152
- S 0 0.000000 7.592936 -0.748439 8.054532 -0.846565
- END
-TURNOUT TT "Tillig IBW-left 83362"
- P "Normal" 1 4 5
- P "Reverse" 1 2 3
- E 0.000000 0.000000 270.000000
- E 6.429717 0.846488 75.000000
- E 6.102362 1.635123 60.000000
- S 0 0.000000 0.000000 0.000000 0.472027 0.000000
- C 0 0.000000 -10.443154 0.472041 10.443154 149.999924 30.000152
- S 0 0.000000 5.693624 1.399129 6.102362 1.635123
- C 0 0.000000 -21.257102 0.472091 21.257102 164.999924 15.000249
- S 0 0.000000 5.973856 0.724332 6.429717 0.846488
- END
-TURNOUT TT "Tillig IBW-right 83361"
- P "Normal" 1 4 5
- P "Reverse" 1 2 3
- E 0.000000 0.000000 270.000000
- E 6.429717 -0.846488 105.000000
- E 6.102362 -1.635123 120.000000
- S 0 0.000000 0.000000 0.000000 0.472027 0.000000
- C 0 0.000000 10.443154 0.471985 -10.443154 0.000076 30.000152
- S 0 0.000000 5.693624 -1.399129 6.102362 -1.635123
- C 0 0.000000 21.257102 0.472091 -21.257102 359.999979 15.000249
- S 0 0.000000 5.973856 -0.724332 6.429717 -0.846488
- END
-TURNOUT TT "Tillig ABW-15 Wye 83380"
- P "Left" 1 2 3
- P "Right" 1 4 5
- E 0.000000 0.000000 270.000000
- E 6.552004 0.429441 82.500000
- E 6.552004 -0.429441 97.500000
- S 0 0.000000 0.000000 0.000000 0.472128 0.000000
- C 0 0.000000 -42.994583 0.472185 42.994583 172.499924 7.500152
- S 0 0.000000 6.084156 0.367839 6.552004 0.429441
- C 0 0.000000 42.994583 0.471957 -42.994583 0.000076 7.500152
- S 0 0.000000 6.084156 -0.367839 6.552004 -0.429441
- END
-TURNOUT TT "Tillig ABW-12 Wye 83382"
- P "Left" 1 2 3
- P "Right" 1 4 5
- E 0.000000 0.000000 270.000000
- E 8.172974 0.428327 84.000000
- E 8.172974 -0.428327 96.000000
- S 0 0.000000 0.000000 0.000000 0.472209 0.000000
- C 0 0.000000 -69.180753 0.472300 69.180753 173.999924 6.000152
- S 0 0.000000 7.703743 0.378998 8.172974 0.428327
- C 0 0.000000 69.180753 0.471933 -69.180753 0.000076 6.000152
- S 0 0.000000 7.703743 -0.378998 8.172974 -0.428327
- END
-TURNOUT TT "Tillig DKW15 DOuble-Slip 83300"
- P "Normal" 1 2 3 0 4 5 6
- P "Reverse" 1 7 6 0 4 8 3
- E 0.000000 0.000000 270.000000
- E 6.535433 0.000000 90.000000
- E 0.111343 0.845742 285.000000
- E 6.424090 -0.845742 105.000000
- S 0 0.000000 0.000000 0.000000 0.944089 0.000000
- S 0 0.000000 0.944089 0.000000 5.591344 0.000000
- S 0 0.000000 5.591344 0.000000 6.535433 0.000000
- S 0 0.000000 0.111343 0.845742 1.023131 0.601422
- S 0 0.000000 1.023131 0.601422 5.512302 -0.601422
- S 0 0.000000 5.512302 -0.601422 6.424090 -0.845742
- C 0 0.000000 17.650057 0.944019 -17.650057 0.000076 15.000152
- C 0 0.000000 -17.650057 5.591366 17.650051 180.000076 15.000152
- END
-TURNOUT TT "Tillig DGV Dbl. Crossover 83210"
- P "Normal" 1 2 3 0 4 5 6
- P "Reverse" 1 7 8 9 6 0 4 10 11 12 3
- E 0.000000 0.000000 270.000000
- E 9.881890 0.000000 90.000000
- E 0.000000 1.692913 270.000000
- E 9.881890 1.692913 90.000000
- S 0 0.000000 0.000000 0.000000 0.789084 0.000000
- S 0 0.000000 0.789084 0.000000 9.092806 0.000000
- S 0 0.000000 9.092806 0.000000 9.881890 0.000000
- S 0 0.000000 0.000000 1.692913 0.789084 1.692913
- S 0 0.000000 0.789084 1.692913 9.092806 1.692913
- S 0 0.000000 9.092806 1.692913 9.881890 1.692913
- C 0 0.000000 -10.474132 0.789097 10.474132 159.252360 20.747716
- S 0 0.000000 4.499581 0.679253 5.382309 1.013660
- C 0 0.000000 10.474132 9.092819 -8.781214 339.252360 20.747716
- C 0 0.000000 10.474132 0.789042 -8.781219 0.000076 20.747716
- S 0 0.000000 4.499581 1.013660 5.382309 0.679253
- C 0 0.000000 -10.474132 9.092819 10.474127 180.000076 20.747716
- END
-SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Crossings
-TURNOUT TT "Tillig K1-15 Crossing 83160"
- P "Normal" 1 0 2
- E 0.000000 0.000000 270.000000
- E 6.535433 0.000000 90.000000
- E 0.111343 0.845742 285.000000
- E 6.424090 -0.845742 105.000000
- S 0 0.000000 0.000000 0.000000 6.535433 0.000000
- S 0 0.000000 0.111343 0.845742 6.424090 -0.845742
- END
-TURNOUT TT "Tillig K2-30 Crossing 83170"
- P "Normal" 1 0 2
- E 0.000000 0.000000 270.000000
- E 3.267717 0.000000 90.000000
- E 0.218894 0.816927 300.000000
- E 3.048823 -0.816927 120.000000
- S 0 0.000000 0.000000 0.000000 3.267717 0.000000
- S 0 0.000000 0.218894 0.816927 3.048823 -0.816927
- END
+CONTENTS Pilz/Tillig Advance Track System
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Straight Track
+TURNOUT TT "Pilz/Tillig Track G1 Straight 6.535 166mm 83101"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.535433 0.000000 90.000000
+ S 0 0 0.000000 0.000000 6.535433 0.000000
+ END
+TURNOUT TT "Pilz/Tillig Track G2 Straight 3.268 83mm 83102"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 3.267717 0.000000 90.000000
+ S 0 0 0.000000 0.000000 3.267717 0.000000
+ END
+TURNOUT TT "Pilz/Tillig Track G3 Straight 1.692 43mm 83105"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.692913 0.000000 90.000000
+ S 0 0 0.000000 0.000000 1.692913 0.000000
+ END
+TURNOUT TT "Pilz/Tillig Track G4 Straight 1.633 41.5mm 83103"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.633858 0.000000 90.000000
+ S 0 0 0.000000 0.000000 1.633858 0.000000
+ END
+TURNOUT TT "Pilz/Tillig Track G5 Straight 1.437 36.5mm 83104"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.437008 0.000000 90.000000
+ S 0 0 0.000000 0.000000 1.437008 0.000000
+ END
+TURNOUT TT "Pilz/Tillig Track Adapter Track 2.244 57mm 83132"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 2.244094 0.000000 90.000000
+ S 0 0 0.000000 0.000000 2.244094 0.000000
+ END
+
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Curve Track
+TURNOUT TT "Pilz/Tillig Track R01 Curve 10.51R 267mm 30° 83116"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 5.255906 -1.408316 120.000000
+ C 0 0 10.511811 0.000000 -10.511811 0.000000 30.000000
+ END
+TURNOUT TT "Pilz/Tillig Track R04 Curve 10.51R 267mm 7.5° 83115"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.372067 -0.089930 97.500000
+ C 0 0 10.511811 0.000000 -10.511811 0.000000 7.500000
+ END
+TURNOUT TT "Pilz/Tillig Track R11 Curve 12.20R 310mm 30° 83109"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.102362 -1.635123 120.000000
+ C 0 0 12.204724 0.000000 -12.204724 0.000000 30.000000
+ END
+TURNOUT TT "Pilz/Tillig Track R12 Curve 12.20R 310mm 15° 83110"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 3.158815 -0.415866 105.000000
+ C 0 0 12.204724 0.000000 -12.204724 0.000000 15.000000
+ END
+TURNOUT TT "Pilz/Tillig Track R14 Curve 12.20R 310mm 7.5° 83113"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.593036 -0.104413 97.500000
+ C 0 0 12.204724 0.000000 -12.204724 0.000000 7.500000
+ END
+TURNOUT TT "Pilz/Tillig Track R21 Curve 13.89R 353mm 30° 83106"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.948819 -1.861930 120.000000
+ C 0 0 13.897638 0.000000 -13.897638 0.000000 30.000000
+ END
+TURNOUT TT "Pilz/Tillig Track R22 Curve 13.89R 353mm 15° 83107"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 3.596973 -0.473551 105.000000
+ C 0 0 13.897638 0.000000 -13.897638 0.000000 15.000000
+ END
+TURNOUT TT "Pilz/Tillig Track R24 Curve 13.89R 353mm 7.5° 83114"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.814006 -0.118896 97.500000
+ C 0 0 13.897638 0.000000 -13.897638 0.000000 7.500000
+ END
+TURNOUT TT "Pilz/Tillig Track R31 Curve 15.59R 396mm 30° 83111"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 7.795276 -2.088738 120.000000
+ C 0 0 15.590551 0.000000 -15.590551 0.000000 30.000000
+ END
+TURNOUT TT "Pilz/Tillig Track R32 Curve 15.59R 396mm 15° 83112"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 4.035132 -0.531235 105.000000
+ C 0 0 15.590551 0.000000 -15.590551 0.000000 15.000000
+ END
+
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Function Track
+TURNOUT TT "Pilz/Tillig Track Straight Feeder 6.535 166mm 83149"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 6.535433 0.000000 90.000000
+ S 0 0 0.000000 0.000000 6.535433 0.000000
+ F 11579568 0.000000 4
+ 0.500000 -0.500000 0
+ 1.000000 -0.500000 0
+ 1.000000 -1.000000 0
+ 0.500000 -1.000000 0
+ END
+TURNOUT TT "Pilz/Tillig Track Uncouple Track 3.268 83mm 83201"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 3.267717 0.000000 90.000000
+ S 0 0 0.000000 0.000000 3.267717 0.000000
+ F 11579568 0.000000 4
+ 0.000000 -0.500000 0
+ 2.750000 -0.500000 0
+ 2.750000 -1.000000 0
+ 0.000000 -1.000000 0
+ F 11579568 0.000000 4
+ 0.5000000 -0.200000 0
+ 2.750000 -0.200000 0
+ 2.750000 0.200000 0
+ 0.500000 0.2000000 0
+ END
+TURNOUT TT "Pilz/Tillig Track Isolation Track 1.633 41.5mm 83150"
+ P "Normal" 1
+ E 0.000000 0.000000 270.000000
+ E 1.633858 0.000000 90.000000
+ S 0 0 0.000000 0.000000 1.633858 0.000000
+ END
+
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Turnouts
+TURNOUT TT "Tillig EW1-left 15d 83322/27"
+ P "Normal" 1
+ P "Reverse" 2 3
+ E 0.000000 0.000000 270.000000
+ E 5.098425 0.000000 90.000000
+ E 4.985016 0.845476 75.000000
+ S 0 0.000000 0.000000 0.000000 5.098425 0.000000
+ C 0 0.000000 -13.897638 0.000000 13.897638 165.000000 15.000000
+ S 0 0.000000 3.596973 0.473551 4.985016 0.845476
+ END
+TURNOUT TT "Tillig EW1-right 15d 83321/26"
+ P "Normal" 1
+ P "Reverse" 2 3
+ E 0.000000 0.000000 270.000000
+ E 5.098425 0.000000 90.000000
+ E 4.985016 -0.845476 105.000000
+ S 0 0.000000 0.000000 0.000000 5.098425 0.000000
+ C 0 0.000000 13.897638 0.000000 -13.897638 0.000000 15.000000
+ S 0 0.000000 3.596973 -0.473551 4.985016 -0.845476
+ END
+TURNOUT TT "Tillig EW2-left 15d 83332"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 6.535433 0.000000 90.000000
+ E 6.429717 0.846488 75.000000
+ S 0 0.000000 0.000000 0.000000 0.472063 0.000000
+ S 0 0.000000 0.472063 0.000000 6.535433 0.000000
+ C 0 0.000000 -21.257102 0.472091 21.257102 164.999924 15.000152
+ S 0 0.000000 5.973856 0.724332 6.429717 0.846488
+ END
+TURNOUT TT "Tillig EW2-right 15d 83331"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 6.535433 0.000000 90.000000
+ E 6.429717 -0.846488 105.000000
+ S 0 0.000000 0.000000 0.000000 0.472063 0.000000
+ S 0 0.000000 0.472063 0.000000 6.535433 0.000000
+ C 0 0.000000 21.257102 0.471978 -21.257102 0.000076 15.000152
+ S 0 0.000000 5.973856 -0.724332 6.429717 -0.846488
+ END
+TURNOUT TT "Tillig EW3-left 12d 83342"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 8.149606 0.000000 90.000000
+ E 8.054532 0.846565 78.000000
+ S 0 0.000000 0.000000 0.000000 0.472100 0.000000
+ S 0 0.000000 0.472100 0.000000 8.149606 0.000000
+ C 0 0.000000 -34.248932 0.472145 34.248932 167.999924 12.000152
+ S 0 0.000000 7.592936 0.748439 8.054532 0.846565
+ END
+TURNOUT TT "Tillig EW3-right 12d 83341"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 8.149606 0.000000 90.000000
+ E 8.054532 -0.846565 102.000000
+ S 0 0.000000 0.000000 0.000000 0.472100 0.000000
+ S 0 0.000000 0.472100 0.000000 8.149606 0.000000
+ C 0 0.000000 34.248932 0.471964 -34.248932 0.000076 12.000152
+ S 0 0.000000 7.592936 -0.748439 8.054532 -0.846565
+ END
+TURNOUT TT "Tillig IBW-left 83362"
+ P "Normal" 1 4 5
+ P "Reverse" 1 2 3
+ E 0.000000 0.000000 270.000000
+ E 6.429717 0.846488 75.000000
+ E 6.102362 1.635123 60.000000
+ S 0 0.000000 0.000000 0.000000 0.472027 0.000000
+ C 0 0.000000 -10.443154 0.472041 10.443154 149.999924 30.000152
+ S 0 0.000000 5.693624 1.399129 6.102362 1.635123
+ C 0 0.000000 -21.257102 0.472091 21.257102 164.999924 15.000249
+ S 0 0.000000 5.973856 0.724332 6.429717 0.846488
+ END
+TURNOUT TT "Tillig IBW-right 83361"
+ P "Normal" 1 4 5
+ P "Reverse" 1 2 3
+ E 0.000000 0.000000 270.000000
+ E 6.429717 -0.846488 105.000000
+ E 6.102362 -1.635123 120.000000
+ S 0 0.000000 0.000000 0.000000 0.472027 0.000000
+ C 0 0.000000 10.443154 0.471985 -10.443154 0.000076 30.000152
+ S 0 0.000000 5.693624 -1.399129 6.102362 -1.635123
+ C 0 0.000000 21.257102 0.472091 -21.257102 359.999979 15.000249
+ S 0 0.000000 5.973856 -0.724332 6.429717 -0.846488
+ END
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Wyes
+TURNOUT TT "Tillig ABW-15 Wye 83380"
+ P "Left" 1 2 3
+ P "Right" 1 4 5
+ E 0.000000 0.000000 270.000000
+ E 6.552004 0.429441 82.500000
+ E 6.552004 -0.429441 97.500000
+ S 0 0.000000 0.000000 0.000000 0.472128 0.000000
+ C 0 0.000000 -42.994583 0.472185 42.994583 172.499924 7.500152
+ S 0 0.000000 6.084156 0.367839 6.552004 0.429441
+ C 0 0.000000 42.994583 0.471957 -42.994583 0.000076 7.500152
+ S 0 0.000000 6.084156 -0.367839 6.552004 -0.429441
+END
+TURNOUT TT "Tillig ABW-12 Wye 83382"
+ P "Left" 1 2 3
+ P "Right" 1 4 5
+ E 0.000000 0.000000 270.000000
+ E 8.172974 0.428327 84.000000
+ E 8.172974 -0.428327 96.000000
+ S 0 0.000000 0.000000 0.000000 0.472209 0.000000
+ C 0 0.000000 -69.180753 0.472300 69.180753 173.999924 6.000152
+ S 0 0.000000 7.703743 0.378998 8.172974 0.428327
+ C 0 0.000000 69.180753 0.471933 -69.180753 0.000076 6.000152
+ S 0 0.000000 7.703743 -0.378998 8.172974 -0.428327
+END
+TURNOUT TT "Tillig DW-15 Asymmetrical 3-Way 83230"
+ P "Normal" 1 2 3
+ P "Right" 1 4 5
+ P "Left" 1 2 6 7
+ E 0.000000 0.000000 270.000000
+ E 6.535433 0.000000 90.000000
+ E 6.429717 0.846488 75.000000
+ E 6.429717 -0.846488 105.000000
+ S 0 0.000000 0.000000 0.000000 0.472063 0.000000
+ S 0 0.000000 0.472063 0.000000 0.964945 0.000000
+ S 0 0.000000 0.964945 0.000000 6.535433 0.000000
+ C 0 0.000000 -21.257102 0.472091 21.257102 165.000000 15.000000
+ S 0 0.000000 5.973856 0.724332 6.429717 0.846488
+ C 0 0.000000 21.257102 0.964945 -21.257102 0.000000 15.000000
+ S 0 0.000000 6.938801 -0.724332 7.394662 -0.846488
+END
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Slips
+TURNOUT TT "Tillig DKW15 Double-Slip 83300/391"
+ P "Normal" 1 2 3 0 4 5 6
+ P "Reverse" 1 7 6 0 4 8 3
+ E 0.000000 0.000000 270.000000
+ E 6.535433 0.000000 90.000000
+ E 0.111343 0.845742 285.000000
+ E 6.424090 -0.845742 105.000000
+ S 0 0.000000 0.000000 0.000000 0.944089 0.000000
+ S 0 0.000000 0.944089 0.000000 5.591344 0.000000
+ S 0 0.000000 5.591344 0.000000 6.535433 0.000000
+ S 0 0.000000 0.111343 0.845742 1.023131 0.601422
+ S 0 0.000000 1.023131 0.601422 5.512302 -0.601422
+ S 0 0.000000 5.512302 -0.601422 6.424090 -0.845742
+ C 0 0.000000 17.650057 0.944019 -17.650057 0.000076 15.000152
+ C 0 0.000000 -17.650057 5.591366 17.650051 180.000076 15.000152
+END
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Double Crossover
+TURNOUT TT "Tillig DGV Dbl. Crossover 83210"
+ P "Normal" 1 2 3 0 4 5 6
+ P "Reverse" 1 7 8 9 6 0 4 10 11 12 3
+ E 0.000000 0.000000 270.000000
+ E 9.881890 0.000000 90.000000
+ E 0.000000 1.692913 270.000000
+ E 9.881890 1.692913 90.000000
+ S 0 0.000000 0.000000 0.000000 0.789084 0.000000
+ S 0 0.000000 0.789084 0.000000 9.092806 0.000000
+ S 0 0.000000 9.092806 0.000000 9.881890 0.000000
+ S 0 0.000000 0.000000 1.692913 0.789084 1.692913
+ S 0 0.000000 0.789084 1.692913 9.092806 1.692913
+ S 0 0.000000 9.092806 1.692913 9.881890 1.692913
+ C 0 0.000000 -10.474132 0.789097 10.474132 159.252360 20.747716
+ S 0 0.000000 4.499581 0.679253 5.382309 1.013660
+ C 0 0.000000 10.474132 9.092819 -8.781214 339.252360 20.747716
+ C 0 0.000000 10.474132 0.789042 -8.781219 0.000076 20.747716
+ S 0 0.000000 4.499581 1.013660 5.382309 0.679253
+ C 0 0.000000 -10.474132 9.092819 10.474127 180.000076 20.747716
+END
+SUBCONTENTS Pilz/Tillig TT-Scale Advance Track - Crossings
+TURNOUT TT "Tillig K1-15 Crossing 83160"
+ P "Normal" 1 0 2
+ E 0.000000 0.000000 270.000000
+ E 6.535433 0.000000 90.000000
+ E 0.111343 0.845742 285.000000
+ E 6.424090 -0.845742 105.000000
+ S 0 0.000000 0.000000 0.000000 6.535433 0.000000
+ S 0 0.000000 0.111343 0.845742 6.424090 -0.845742
+END
+TURNOUT TT "Tillig K2-30 Crossing 83170"
+ P "Normal" 1 0 2
+ E 0.000000 0.000000 270.000000
+ E 3.267717 0.000000 90.000000
+ E 0.218894 0.816927 300.000000
+ E 3.048823 -0.816927 120.000000
+ S 0 0.000000 0.000000 0.000000 3.267717 0.000000
+ S 0 0.000000 0.218894 0.816927 3.048823 -0.816927
+END
diff --git a/app/lib/params/atl83ho.xtp b/app/lib/params/atl83ho.xtp
index 4ce2387..d3271f4 100644
--- a/app/lib/params/atl83ho.xtp
+++ b/app/lib/params/atl83ho.xtp
@@ -385,7 +385,7 @@ TURNOUT HO "Atlas C83 Bumper 518"
S 0 0 0.000000 0.000000 3.750000 0.000000
END
-TURNOUT HO "Atlas C83 9" Warren Truss Bridge 590"
+TURNOUT HO "Atlas C83 9"" Warren Truss Bridge 590"
P "Normal" 1
E 0.000000 0.000000 270.000000
E 9.000000 0.000000 90.000000
@@ -397,7 +397,7 @@ TURNOUT HO "Atlas C83 9" Warren Truss Bridge 590"
L 11579568 0.050000 0.000000 -0.750000 0.000000 -1.200000
L 11579568 0.050000 9.000000 -0.750000 9.000000 -1.200000
END
-TURNOUT HO "Atlas C83 9" Deck Truss Bridge 591"
+TURNOUT HO "Atlas C83 9"" Deck Truss Bridge 591"
P "Normal" 1
E 0.000000 0.000000 270.000000
E 9.000000 0.000000 90.000000
@@ -409,7 +409,7 @@ TURNOUT HO "Atlas C83 9" Deck Truss Bridge 591"
L 11579568 0.050000 0.000000 -0.600000 0.000000 -0.700000
L 11579568 0.050000 9.000000 -0.600000 9.000000 -0.700000
END
-TURNOUT HO "Atlas C83 9" Plate Girder Bridge 592"
+TURNOUT HO "Atlas C83 9"" Plate Girder Bridge 592"
P "Normal" 1
E 0.000000 0.000000 270.000000
E 9.000000 0.000000 90.000000
@@ -421,7 +421,7 @@ TURNOUT HO "Atlas C83 9" Plate Girder Bridge 592"
L 11579568 0.050000 0.000000 -0.750000 0.000000 -1.300000
L 11579568 0.050000 9.000000 -0.750000 9.000000 -1.300000
END
-TURNOUT HO "Atlas C83 18" Through Truss Bridge 593/594"
+TURNOUT HO "Atlas C83 18"" Through Truss Bridge 593/594"
P "Normal" 1
E 0.000000 0.000000 270.000000
E 18.000000 0.000000 90.000000
diff --git a/app/lib/params/pecoho83.xtp b/app/lib/params/pecoho83.xtp
index 727ecaf..7af3cc2 100644
--- a/app/lib/params/pecoho83.xtp
+++ b/app/lib/params/pecoho83.xtp
@@ -1,126 +1,145 @@
-CONTENTS Peco North American Code 83 HO Scale Turnouts
-SUBCONTENTS Peco Code 83 HO Turnouts
-TURNOUT HO "PECO Code 83 #5 Left Hand Turnout SL-8352/SLE-8352"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 8.307087 0.000000 90.000000
- E 8.307087 1.019252 78.463031
- S 0 0.000000 0.000000 0.000000 0.649600 0.000000
- S 0 0.000000 0.649600 0.000000 8.307087 0.000000
- C 0 0.000000 -26.373333 0.649635 26.373333 168.462955 11.537121
- S 0 0.000000 5.924335 0.532864 8.307087 1.019252
- END
-TURNOUT HO "PECO Code 83 #5 Right Hand Turnout SL-8351/SLE-8351"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 8.307087 0.000000 90.000000
- E 8.307087 -1.019252 101.536969
- S 0 0.000000 0.000000 0.000000 0.649600 0.000000
- S 0 0.000000 0.649600 0.000000 8.307087 0.000000
- C 0 0.000000 26.373333 0.649495 -26.373333 0.000076 11.537121
- S 0 0.000000 5.924335 -0.532864 8.307087 -1.019252
- END
-TURNOUT HO "PECO Code 83 #6 Left Hand Turnout SL-8362/SLE-8362"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 9.173228 0.000000 90.000000
- E 9.173228 1.023622 77.000000
- S 0 0.000000 0.000000 0.000000 0.838713 0.000000
- S 0 0.000000 0.838713 0.000000 9.173228 0.000000
- C 0 0.000000 -34.236656 0.838759 34.236656 166.999924 13.000152
- S 0 0.000000 8.540367 0.877502 9.173228 1.023622
- END
-TURNOUT HO "PECO Code 83 #6 Right Hand Turnout SL-8361/SLE-8361"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 9.173228 0.000000 90.000000
- E 9.173228 -1.023622 103.000000
- S 0 0.000000 0.000000 0.000000 0.838713 0.000000
- S 0 0.000000 0.838713 0.000000 9.173228 0.000000
- C 0 0.000000 34.236656 0.838577 -34.236656 0.000076 13.000152
- S 0 0.000000 8.540367 -0.877502 9.173228 -1.023622
- END
-TURNOUT HO "PECO Code 83 #8 Left Hand Turnout SL-8382/SLE-8382"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 12.677165 0.000000 90.000000
- E 12.677165 1.019213 82.819238
- S 0 0.000000 0.000000 0.000000 0.649600 0.000000
- S 0 0.000000 0.649600 0.000000 12.677165 0.000000
- C 0 0.000000 -62.760069 0.649683 62.760069 172.819162 7.180914
- S 0 0.000000 8.494774 0.492264 12.677165 1.019213
- END
-TURNOUT HO "PECO Code 83 #8 Right Hand Turnout SL-8381/SLE-8381"
- P "Normal" 1 2
- P "Reverse" 1 3 4
- E 0.000000 0.000000 270.000000
- E 12.677165 0.000000 90.000000
- E 12.677165 -1.019213 97.180762
- S 0 0.000000 0.000000 0.000000 0.649600 0.000000
- S 0 0.000000 0.649600 0.000000 12.677165 0.000000
- C 0 0.000000 62.760069 0.649350 -62.760069 0.000076 7.180914
- S 0 0.000000 8.494774 -0.492264 12.677165 -1.019213
- END
-TURNOUT HO "PECO Code 83 #4 WYE Turnout SL-8348/SLE-8348"
- P "Left" 1 2 3
- P "Right" 1 4 5
- E 0.000000 0.000000 270.000000
- E 7.159055 0.500000 82.850000
- E 7.159055 -0.500000 97.150000
- S 0 0.000000 0.000000 0.000000 0.649600 0.000000
- C 0 0.000000 -40.393551 0.649654 40.393551 172.849924 7.150152
- S 0 0.000000 5.677382 0.314125 7.159055 0.500000
- C 0 0.000000 40.393551 0.649439 -40.393551 0.000076 7.150152
- S 0 0.000000 5.677382 -0.314125 7.159055 -0.500000
- END
-
-SUBCONTENTS Peco Code 83 HO Crossings
-TURNOUT HO "PECO Code 83 #6 Diamond Crossing SL-8364/SLE-8364"
- P "Normal" 1 0 2
- E 0.000000 0.000000 270.000000
- E 12.035433 0.000000 90.000000
- E 0.084167 1.002945 279.594076
- E 11.951266 -1.002945 99.594076
- S 0 0.000000 0.000000 0.000000 12.035433 0.000000
- S 0 0.000000 0.084167 1.002945 11.951266 -1.002945
- END
-TURNOUT HO "PECO Code 83 90d Crossing SL-8390"
- P "Normal" 1 0 2
- E 0.000000 0.000000 270.000000
- E 2.000000 0.000000 90.000000
- E 1.000000 -1.000000 180.000000
- E 1.000000 1.000000 0.000000
- S 0 0.000000 0.000000 0.000000 2.000000 0.000000
- S 0 0.000000 1.000000 1.000000 1.000000 -1.000000
- END
-
-SUBCONTENTS Peco Code 83 HO Curved Turnouts
-TURNOUT HO "Peco Code 83 #7 Curved Left Turnout SL-8377/SLE-8377"
- P "Normal" 1 4 5
- P "Reverse" 1 2 3
- E 0.000000 0.000000 270.000000
- E 11.106693 0.984252 81.000000
- E 10.865748 1.968504 72.000000
- S 0 0.000000 0.000000 0.000000 0.649600 0.000000
- C 0 0.000000 -26.251070 0.649635 26.251070 161.999924 18.000152
- S 0 0.000000 8.761686 1.284838 10.865748 1.968504
- C 0 0.000000 -53.910688 0.649672 53.910688 170.999924 9.000152
- S 0 0.000000 9.083224 0.663751 11.106693 0.984252
- END
-TURNOUT HO "Peco Code 83 #7 Curved Right Turnout SL-8376/SLE-8376"
- P "Normal" 1 4 5
- P "Reverse" 1 2 3
- E 0.000000 0.000000 270.000000
- E 11.106693 -0.984252 99.000000
- E 10.865748 -1.968504 108.000000
- S 0 0.000000 0.000000 0.000000 0.649600 0.000000
- C 0 0.000000 26.251070 0.649496 -26.251070 0.000076 18.000152
- S 0 0.000000 8.761686 -1.284838 10.865748 -1.968504
- C 0 0.000000 53.910688 0.649385 -53.910688 0.000076 9.000152
- S 0 0.000000 9.083224 -0.663751 11.106693 -0.984252
- END
+CONTENTS Peco North American Code 83 HO Scale Turnouts
+#Updated based on PECO Website and PDF's
+SUBCONTENTS Peco Code 83 HO Turnouts
+TURNOUT HO "PECO Code 83 #5 Left Hand Turnout SL-8352/SLE-8352"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 8.259842 0.000000 90.000000
+ E 8.259842 1.000000 78.600000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 8.259842 0.000000
+ C 0 0.000000 -26.558075 0.649635 26.558075 168.599924 11.400152
+ S 0 0.000000 5.899063 0.523973 8.259842 1.000000
+ END
+TURNOUT HO "PECO Code 83 #5 Right Hand Turnout SL-8351/SLE-8351"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 8.259842 0.000000 90.000000
+ E 8.259842 -1.000000 101.400000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 8.259842 0.000000
+ C 0 0.000000 26.558075 0.649494 -26.558075 0.000076 11.400152
+ S 0 0.000000 5.899063 -0.523973 8.259842 -1.000000
+ END
+TURNOUT HO "PECO Code 83 #6 Left Hand Turnout SL-8362/SLE-8362"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 9.192913 0.000000 90.000000
+ E 9.192913 1.000000 80.500000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 9.192913 0.000000
+ C 0 0.000000 -30.900336 0.649641 30.900336 170.499924 9.500152
+ S 0 0.000000 5.749703 0.423792 9.192913 1.000000
+ END
+TURNOUT HO "PECO Code 83 #6 Right Hand Turnout SL-8361/SLE-8361"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 9.192913 0.000000 90.000000
+ E 9.192913 -1.000000 99.500000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 9.192913 0.000000
+ C 0 0.000000 30.900336 0.649477 -30.900336 0.000076 9.500152
+ S 0 0.000000 5.749703 -0.423792 9.192913 -1.000000
+ END
+TURNOUT HO "PECO Code 83 #8 Left Hand Turnout SL-8382/SLE-8382"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 12.649606 0.000000 90.000000
+ E 12.649606 1.000000 82.850000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 12.649606 0.000000
+ C 0 0.000000 -64.478236 0.649686 64.478236 172.849924 7.150152
+ S 0 0.000000 8.675202 0.501423 12.649606 1.000000
+ END
+TURNOUT HO "PECO Code 83 #8 Right Hand Turnout SL-8381/SLE-8381"
+ P "Normal" 1 2
+ P "Reverse" 1 3 4
+ E 0.000000 0.000000 270.000000
+ E 12.649606 0.000000 90.000000
+ E 12.649606 -1.000000 97.150000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ S 0 0.000000 0.649600 0.000000 12.649606 0.000000
+ C 0 0.000000 64.478236 0.649343 -64.478236 0.000076 7.150152
+ S 0 0.000000 8.675202 -0.501423 12.649606 -1.000000
+ END
+SUBCONTENTS Peco Code 83 HO Wye Turnouts
+TURNOUT HO "PECO Code 83 #4 WYE Turnout SL-8348/SLE-8348"
+ P "Left" 1 2 3
+ P "Right" 1 4 5
+ E 0.000000 0.000000 270.000000
+ E 7.159055 0.500000 82.850000
+ E 7.159055 -0.500000 97.150000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ C 0 0.000000 -40.393551 0.649654 40.393551 172.849924 7.150152
+ S 0 0.000000 5.677382 0.314125 7.159055 0.500000
+ C 0 0.000000 40.393551 0.649439 -40.393551 0.000076 7.150152
+ S 0 0.000000 5.677382 -0.314125 7.159055 -0.500000
+ END
+
+SUBCONTENTS Peco Code 83 HO Crossings
+TURNOUT HO "PECO Code 83 #6 Diamond Crossing SL-8364/SLE-8364"
+ P "Normal" 1 0 2
+ E 0.000000 0.000000 270.000000
+ E 12.035433 0.000000 90.000000
+ E 0.082528 0.993201 279.500000
+ E 11.952905 -0.993201 99.500000
+ S 0 0.000000 0.000000 0.000000 12.035433 0.000000
+ S 0 0.000000 0.082528 0.993201 11.952905 -0.993201
+ END
+TURNOUT HO "PECO Code 83 90d Crossing SL-8390"
+ P "Normal" 1 0 2
+ E 0.000000 0.000000 270.000000
+ E 2.000000 0.000000 90.000000
+ E 1.000000 -1.000000 180.000000
+ E 1.000000 1.000000 0.000000
+ S 0 0.000000 0.000000 0.000000 2.000000 0.000000
+ S 0 0.000000 1.000000 1.000000 1.000000 -1.000000
+ END
+
+SUBCONTENTS Peco Code 83 HO Curved Turnouts
+TURNOUT HO "Peco Code 83 #7 Curved Left Turnout SL-8377/SLE-8377"
+ P "Normal" 1 4 5
+ P "Reverse" 1 2 3
+ E 0.000000 0.000000 270.000000
+ E 11.106693 0.984252 81.000000
+ E 10.865748 1.968504 72.000000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ C 0 0.000000 -26.251070 0.649635 26.251070 161.999924 18.000152
+ S 0 0.000000 8.761686 1.284838 10.865748 1.968504
+ C 0 0.000000 -53.910688 0.649672 53.910688 170.999924 9.000152
+ S 0 0.000000 9.083224 0.663751 11.106693 0.984252
+ END
+TURNOUT HO "Peco Code 83 #7 Curved Right Turnout SL-8376/SLE-8376"
+ P "Normal" 1 4 5
+ P "Reverse" 1 2 3
+ E 0.000000 0.000000 270.000000
+ E 11.106693 -0.984252 99.000000
+ E 10.865748 -1.968504 108.000000
+ S 0 0.000000 0.000000 0.000000 0.649600 0.000000
+ C 0 0.000000 26.251070 0.649496 -26.251070 0.000076 18.000152
+ S 0 0.000000 8.761686 -1.284838 10.865748 -1.968504
+ C 0 0.000000 53.910688 0.649385 -53.910688 0.000076 9.000152
+ S 0 0.000000 9.083224 -0.663751 11.106693 -0.984252
+ END
+SUBCONTENTS Peco Code 83 HO Slip Turnouts
+TURNOUT HO "Peco Code 83 #6 Double Slip Switch SL-U8363"
+ P "Normal" 1 2 3 0 4 5 6
+ P "Reverse" 1 7 6 0 4 8 3
+ E 0.000000 0.000000 270.000000
+ E 12.035433 0.000000 90.000000
+ E 0.082528 0.993201 279.500000
+ E 11.952905 -0.993201 99.500000
+ S 0 0.000000 0.000000 0.000000 1.299468 0.000000
+ S 0 0.000000 1.299468 0.000000 10.735965 0.000000
+ S 0 0.000000 10.735965 0.000000 12.035433 0.000000
+ S 0 0.000000 0.082528 0.993201 1.363761 0.778782
+ S 0 0.000000 1.363761 0.778782 10.671672 -0.778782
+ S 0 0.000000 10.671672 -0.778782 11.952905 -0.993201
+ C 0 0.000000 56.784006 1.299241 -56.784006 0.000076 9.500152
+ C 0 0.000000 -56.784006 10.736040 56.783993 180.000076 9.500152
+ END
diff --git a/app/lib/xtrkcad.desktop b/app/lib/xtrkcad.desktop
index 5b09cdc..a5f9dd6 100644
--- a/app/lib/xtrkcad.desktop
+++ b/app/lib/xtrkcad.desktop
@@ -3,7 +3,7 @@ Encoding=UTF-8
Name=XTrackCAD
Comment=Design model railroad layouts
Exec=xtrkcad
-Icon=xtrkcad
+Icon=xtrkcad.png
Terminal=false
Type=Application
-Categories=Application;Railroad;Game
+Categories=Graphics;Game \ No newline at end of file
diff --git a/app/lib/icon.png b/app/lib/xtrkcad.png
index 4cdcdba..4cdcdba 100644
--- a/app/lib/icon.png
+++ b/app/lib/xtrkcad.png
Binary files differ
diff --git a/app/lib/xtrkcad.xtq b/app/lib/xtrkcad.xtq
index be01d88..7b661e6 100644
--- a/app/lib/xtrkcad.xtq
+++ b/app/lib/xtrkcad.xtq
@@ -142,6 +142,10 @@ SCALE TTn3.5, 120.0, 0.3543
1560,37.5,1080
2160,45,1440
2640,52.5,1800
+SCALE TTi, 120.0, 0.177
+ 1560,37.5,1080
+ 2160,45,1440
+ 2640,52.5,1800
SCALE Z, 220.0, 0.256
1560,37.5,1080
2160,45,1440
diff --git a/app/tools/halibut/bk_html.c b/app/tools/halibut/bk_html.c
index 8b5443b..4f7c49b 100644
--- a/app/tools/halibut/bk_html.c
+++ b/app/tools/halibut/bk_html.c
@@ -54,7 +54,8 @@ typedef struct {
char *index_filename;
char *template_filename;
char *single_filename;
- char *chm_filename, *hhp_filename, *hhc_filename, *hhk_filename;
+ char *chm_filename, *hhp_filename, *hhc_filename, *hhk_filename;
+ char *appletoc_filename;
char **template_fragments;
int ntfragments;
char *head_end, *body_start, *body_end, *addr_start, *addr_end;
@@ -100,7 +101,7 @@ struct htmlsect {
htmlsect *next, *parent;
htmlfile *file;
paragraph *title, *text;
- enum { NORMAL, TOP, INDEX } type;
+ enum { NORMAL, TOP, INDEX, APPLEINDEX } type;
int contents_depth;
char **fragments;
};
@@ -235,7 +236,7 @@ static char *html_sanitise_filename(htmlfilelist *files, char *text);
static void html_contents_entry(htmloutput *ho, int depth, htmlsect *s,
htmlfile *thisfile, keywordlist *keywords,
- htmlconfig *cfg);
+ htmlconfig *cfg, int toc_yes);
static void html_section_title(htmloutput *ho, htmlsect *s,
htmlfile *thisfile, keywordlist *keywords,
htmlconfig *cfg, int real);
@@ -268,6 +269,7 @@ static htmlconfig html_configure(paragraph *source) {
ret.template_filename = dupstr("%n.html");
ret.chm_filename = ret.hhp_filename = NULL;
ret.hhc_filename = ret.hhk_filename = NULL;
+ ret.appletoc_filename = NULL;
ret.ntfragments = 1;
ret.template_fragments = snewn(ret.ntfragments, char *);
ret.template_fragments[0] = dupstr("%b");
@@ -517,6 +519,9 @@ static htmlconfig html_configure(paragraph *source) {
} else if (!ustricmp(k, L"html-mshtmlhelp-index")) {
sfree(ret.hhk_filename);
ret.hhk_filename = dupstr(adv(p->origkeyword));
+ } else if (!ustricmp(k, L"html-applehelp-toc")) {
+ sfree(ret.appletoc_filename);
+ ret.appletoc_filename = dupstr(adv(p->origkeyword));
}
}
}
@@ -539,6 +544,7 @@ static htmlconfig html_configure(paragraph *source) {
sfree(ret.hhc_filename); ret.hhc_filename = NULL;
sfree(ret.hhk_filename); ret.hhk_filename = NULL;
}
+
/*
* Now process fallbacks on quote characters.
@@ -839,7 +845,7 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
* output the section text
* - for each section which is not in the file but which has a
* parent that is, we output a contents entry for the
- * section if appropriate
+ * section if appropriate/
* - finally, we output the file trailer and close the file.
*/
{
@@ -1007,12 +1013,14 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
for (s = sects.head; s; s = s->next) {
if (s->file == f && s->text) {
for (p = s->text;
- p && (p == s->text || p->type == para_Title ||
- !is_heading_type(p->type));
+ p && (p == s->text || p->type == para_Title
+ || !is_heading_type(p->type)
+ );
p = p->next) {
if (p->type == para_Config) {
if (!ustricmp(p->keyword, L"html-local-head")) {
html_raw(&ho, adv(p->origkeyword));
+ html_nl(&ho);
}
}
}
@@ -1023,13 +1031,15 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
html_nl(&ho);
if (conf.body_tag)
- html_raw(&ho, conf.body_tag);
+ html_raw(&ho, conf.body_tag);
else
- element_open(&ho, "body");
+ element_open(&ho, "body");
html_nl(&ho);
- if (conf.body_start)
- html_raw(&ho, conf.body_start);
+ if (conf.body_start) {
+ html_raw(&ho, conf.body_start);
+ html_nl(&ho);
+ }
/*
* Write out a nav bar. Special case: we don't do this
@@ -1084,6 +1094,7 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
}
prevf = f;
+
/*
* Write out a prefix TOC for the file (if a leaf file).
*
@@ -1149,9 +1160,9 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
assert(hlevel >= 1);
html_contents_entry(&ho, hlevel, s,
- f, keywords, &conf);
+ f, keywords, &conf, 0);
}
- html_contents_entry(&ho, 0, NULL, f, keywords, &conf);
+ html_contents_entry(&ho, 0, NULL, f, keywords, &conf, 0);
}
}
@@ -1204,7 +1215,7 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
*/
if (adepth <= a->contents_depth) {
html_contents_entry(&ho, adepth, s,
- f, keywords, &conf);
+ f, keywords, &conf, 0);
}
}
}
@@ -1213,7 +1224,7 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
int hlevel;
char htag[3];
- html_contents_entry(&ho, 0, NULL, f, keywords, &conf);
+ html_contents_entry(&ho, 0, NULL, f, keywords, &conf, 0);
/*
* Display the section heading.
@@ -1440,7 +1451,7 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
sfree(stackhead);
}
- if (s->type == INDEX) {
+ if (s->type == INDEX ) {
indexentry *entry;
int i;
@@ -1503,7 +1514,7 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
}
}
- html_contents_entry(&ho, 0, NULL, f, keywords, &conf);
+ html_contents_entry(&ho, 0, NULL, f, keywords, &conf, 0);
html_nl(&ho);
{
@@ -1593,6 +1604,78 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
}
}
+ /* APPLE TOC only has list entries and all entries are remote */
+ /*
+ * Write out the whole TOC in the TOC file.
+ *
+ */
+
+ if (conf.appletoc_filename) {
+ htmlsect *s, *top;
+ htmlfile *f;
+ htmloutput ho;
+ ho.charset = conf.output_charset;
+ ho.restrict_charset = conf.restrict_charset;
+ ho.cstate = charset_init_state;
+ ho.ver = conf.htmlver;
+ ho.state = HO_NEUTRAL;
+ ho.contents_level = 0;
+ ho.hackflags = 0; /* none of these thankyouverymuch */
+ ho.hacklimit = -1;
+
+ ho.fp = fopen(conf.appletoc_filename, "w");
+ if (!ho.fp)
+ error(err_cantopenw, conf.appletoc_filename);
+
+ /* Find TOP section */
+ s = sects.head;
+
+ html_contents_entry(&ho, 1, s, NULL, keywords, &conf, TRUE);
+
+ /* Loop through all sections */
+ for (s = sects.head; s; s = s->next) {
+ if (s->type == TOP) {
+ /*
+ * This is the head - ignore as we just wrote out its entry.
+ */
+ } else {
+ /*
+ * Doesn't contain the TOP so it is
+ * a descendant we consider it for the
+ * main TOC.
+ */
+ htmlsect *a, *ac;
+ int depth, adepth;
+ /*
+ * Search up from this section until we find
+ * the highest-level one
+ */
+ depth = adepth = 0;
+ a = NULL;
+ for (ac = s; ac; ac = ac->parent) {
+ if (ac->type == TOP) {
+ a = ac;
+ adepth = depth;
+ }
+ depth++;
+ }
+ if (a) {
+
+ html_contents_entry(&ho, adepth, s,
+ NULL, keywords, &conf, TRUE);
+ }
+ }
+ }
+ /*
+ * Close the entries
+ */
+ html_contents_entry(&ho, 0, NULL, NULL, keywords, &conf, TRUE);
+ cleanup(&ho);
+
+ }
+
+ /* End of Apple TOC */
+
/*
* Before we start outputting the HTML Help files, check
* whether there's even going to _be_ an index file: we omit it
@@ -1703,6 +1786,9 @@ void html_backend(paragraph *sourceform, keywordlist *keywords,
fclose(ho.fp);
}
+
+
+
if (conf.hhc_filename) {
htmlfile *f;
htmlsect *s, *a;
@@ -2139,8 +2225,16 @@ static void html_words(htmloutput *ho, word *words, int flags,
sfree(c);
}
break;
+ case word_Anchor:
+ if (flags & LINKS) {
+ element_empty( ho, "a");
+ c = utoa_dup(w->text, CS_ASCII);
+ element_attr(ho, "name", c);
+ sfree(c);
+ }
+ break;
case word_Graphic:
- element_open( ho, "img");
+ element_empty( ho, "img");
c = utoa_dup(w->text, CS_ASCII);
element_attr(ho, "src", c);
return_to_neutral(ho);
@@ -2160,6 +2254,7 @@ static void html_words(htmloutput *ho, word *words, int flags,
assert(s);
html_href(ho, file, s->file, s->fragments[0]);
+
}
break;
case word_HyperEnd:
@@ -2490,7 +2585,6 @@ static void html_href(htmloutput *ho, htmlfile *thisfile,
{
rdstringc rs = { 0, 0, NULL };
char *url;
-
if (targetfile != thisfile)
rdaddsc(&rs, targetfile->filename);
if (targetfrag) {
@@ -2708,37 +2802,52 @@ static char *html_sanitise_filename(htmlfilelist *files, char *text)
static void html_contents_entry(htmloutput *ho, int depth, htmlsect *s,
htmlfile *thisfile, keywordlist *keywords,
- htmlconfig *cfg)
+ htmlconfig *cfg, int toc_yes)
{
- if (ho->contents_level >= depth && ho->contents_level > 0) {
- element_close(ho, "li");
- html_nl(ho);
+
+
+ while (ho->contents_level > depth) {
+ element_close(ho, "ul");
+ ho->contents_level--;
+ html_nl(ho);
+ if (toc_yes && ho->contents_level == 1 && depth == 1) {
+ element_close(ho, "div");
+ html_nl(ho);
+ }
}
+
- while (ho->contents_level > depth) {
- element_close(ho, "ul");
- ho->contents_level--;
- if (ho->contents_level > 0) {
- element_close(ho, "li");
- }
- html_nl(ho);
- }
while (ho->contents_level < depth) {
- html_nl(ho);
- element_open(ho, "ul");
- html_nl(ho);
- ho->contents_level++;
+ if (toc_yes && ho->contents_level == 1 && depth == 2) {
+ element_open(ho,"div");
+ element_attr(ho,"class","panel");
+ html_nl(ho);
+ }
+ element_open(ho, "ul");
+ if (toc_yes && ho->contents_level < 1)
+ element_attr(ho,"class","top-list");
+ html_nl(ho);
+ ho->contents_level++;
}
if (!s)
- return;
+ return;
element_open(ho, "li");
+ if (toc_yes && ho->contents_level > 0 && depth == 1) {
+ element_open(ho,"button");
+ element_attr(ho,"class","accordion");
+ element_close(ho,"button");
+ }
+
html_href(ho, thisfile, s->file, s->fragments[0]);
html_section_title(ho, s, thisfile, keywords, cfg, FALSE);
element_close(ho, "a");
- /* <li> will be closed by a later invocation */
+ element_close(ho, "li");
+ html_nl(ho);
+
+
}
static void html_section_title(htmloutput *ho, htmlsect *s, htmlfile *thisfile,
@@ -2778,9 +2887,9 @@ static void html_section_title(htmloutput *ho, htmlsect *s, htmlfile *thisfile,
assert(s->type != NORMAL);
/*
* If we're printing the full document title for _real_ and
- * there isn't one, we don't want to print `Preamble' at
+ * there isn't one, won't want to print `Preamble' at
* the top of what ought to just be some text. If we need
- * it in any other context such as TOCs, we need to print
+ * it in any other context such ae ds TOCs, we need to print
* `Preamble'.
*/
if (s->type == TOP && !real)
diff --git a/app/tools/halibut/halibut.h b/app/tools/halibut/halibut.h
index 8fe1f08..aa750bd 100644
--- a/app/tools/halibut/halibut.h
+++ b/app/tools/halibut/halibut.h
@@ -169,6 +169,7 @@ enum {
word_HyperLink, /* (invisible) */
word_HyperEnd, /* (also invisible; no text) */
word_Graphic, /* \G */
+ word_Anchor, /* \IA */
/*
* Back ends may define their own word types beyond here, in
* case they need to use them internally.
diff --git a/app/tools/halibut/input.c b/app/tools/halibut/input.c
index b877508..256d9c6 100644
--- a/app/tools/halibut/input.c
+++ b/app/tools/halibut/input.c
@@ -213,6 +213,7 @@ enum {
c_G, /* graphic */
c_H, /* heading */
c_I, /* invisible index mark */
+ c_IA, /* included anchor */
c_IM, /* index merge/rewrite */
c_K, /* capitalised cross-reference */
c_S, /* aux field is 0, 1, 2, ... */
@@ -1299,6 +1300,8 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx,
wd.type = word_HyperLink;
else if (t.cmd == c_G)
wd.type = word_Graphic;
+ else if (t.cmd == c_IA)
+ wd.type = word_Anchor;
else
wd.type = word_Normal;
dtor(t), t = get_token(in);
diff --git a/app/wlib/gtklib/CMakeLists.txt b/app/wlib/gtklib/CMakeLists.txt
index cce9866..a8cae9f 100644
--- a/app/wlib/gtklib/CMakeLists.txt
+++ b/app/wlib/gtklib/CMakeLists.txt
@@ -4,26 +4,51 @@ FILE(GLOB HEADERS *.h)
INCLUDE (FindGTKUnixPrint.cmake)
SET(SOURCES
- gtkbitmap.c
- gtkbutton.c
- gtkcolor.c
- gtkdraw-cairo.c
+ bitmap.c
+ boxes.c
+ button.c
+ color.c
+ control.c
+ droplist.c
filesel.c
- gtkfont.c
- gtkhelp.c
- gtklist.c
- gtkmenu.c
- gtkmisc.c
- gtksimple.c
- gtksingle.c
- gtksplash.c
- gtktext.c
- gtkwindow.c
- gtkxpm.c
+ font.c
+ help.c
+ lines.c
+ list.c
+ liststore.c
+ main.c
+ menu.c
+ message.c
+ notice.c
+ pixbuf.c
+ png.c
print.c
+ single.c
+ splash.c
+ text.c
+ timer.c
+ tooltip.c
+ treeview.c
+ util.c
+ window.c
wpref.c
+# cproto and cppcheck
+
+# end of refactored sources
+ gtkdraw-cairo.c
)
+IF(APPLE)
+ SET(SOURCES
+ ${SOURCES}
+ osxhelp.c)
+
+ELSE(APPLE)
+ SET(SOURCES
+ ${SOURCES}
+ ixhelp.c)
+ENDIF(APPLE)
+
SET_SOURCE_FILES_PROPERTIES(wpref.c PROPERTIES COMPILE_FLAGS -DEXPORT=)
INCLUDE_DIRECTORIES(${XTrkCAD_BINARY_DIR})
@@ -35,3 +60,4 @@ ADD_LIBRARY(xtrkcad-wlib ${HEADERS} ${SOURCES})
TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_LIBRARIES})
TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_UNIX_PRINT_LIBRARIES})
TARGET_LINK_LIBRARIES(xtrkcad-wlib ${GTK_WEBKIT_LIBRARIES})
+
diff --git a/app/wlib/gtklib/bitmap.c b/app/wlib/gtklib/bitmap.c
new file mode 100644
index 0000000..dc7236b
--- /dev/null
+++ b/app/wlib/gtklib/bitmap.c
@@ -0,0 +1,136 @@
+/** \file bitmap.c
+ * Bitmap creation
+ */
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2009 Daniel Spagnol, 2013 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 <stdlib.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+
+struct wBitmap_t {
+ WOBJ_COMMON
+};
+
+/**
+ * Create a static control for displaying a bitmap.
+ *
+ * \param parent IN parent window
+ * \param x, y IN position in parent window
+ * \param option IN ignored for now
+ * \param iconP IN icon to use in XPM format
+ * \return the control
+ */
+
+wControl_p
+wBitmapCreate( wWin_p parent, wPos_t x, wPos_t y, long options, wIcon_p iconP )
+{
+ wBitmap_p bt;
+ GdkPixbuf *pixbuf;
+ GtkWidget *image;
+
+ bt = wlibAlloc( parent, B_BITMAP, x, y, NULL, sizeof *bt, NULL );
+ bt->w = iconP->w;
+ bt->h = iconP->h;
+ bt->option = options;
+
+ /*
+ * Depending on the platform, parent->widget->window might still be null
+ * at this point. The window allocation should be forced before creating
+ * the pixmap.
+ */
+ if ( gtk_widget_get_window( parent->widget ) == NULL )
+ gtk_widget_realize( parent->widget ); /* force allocation, if pending */
+
+ /* create the bitmap from supplied xpm data */
+ pixbuf = gdk_pixbuf_new_from_xpm_data( (const char **)iconP->bits );
+ image = gtk_image_new_from_pixbuf( pixbuf );
+ gtk_widget_show( image );
+ g_object_unref( (gpointer)pixbuf );
+
+ bt->widget = gtk_fixed_new();
+ gtk_widget_show( bt->widget );
+ gtk_container_add( GTK_CONTAINER(bt->widget), image );
+
+ wlibComputePos( (wControl_p)bt );
+ wlibControlGetSize( (wControl_p)bt );
+ gtk_fixed_put( GTK_FIXED( parent->widget ), bt->widget, bt->realX, bt->realY );
+
+ return( (wControl_p)bt );
+}
+
+/**
+ * Create a two-tone icon
+ *
+ * \param w IN width of icon
+ * \param h IN height of icon
+ * \param bits IN bitmap
+ * \param color IN color
+ * \returns icon handle
+ */
+
+wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color )
+{
+ wIcon_p ip;
+ ip = (wIcon_p)malloc( sizeof *ip );
+ ip->gtkIconType = gtkIcon_bitmap;
+ ip->w = w;
+ ip->h = h;
+ ip->color = color;
+ ip->bits = bits;
+ return ip;
+}
+
+/**
+ * Create an icon from a pixmap
+ * \param pm IN pixmap
+ * \returns icon handle
+ */
+
+wIcon_p wIconCreatePixMap( char *pm[] )
+{
+ wIcon_p ip;
+ ip = (wIcon_p)malloc( sizeof *ip );
+ ip->gtkIconType = gtkIcon_pixmap;
+ ip->w = 0;
+ ip->h = 0;
+ ip->color = 0;
+ ip->bits = pm;
+ return ip;
+}
+
+/**
+ * Set the color a two-tone icon
+ *
+ * \param ip IN icon handle
+ * \param color IN color to use
+ */
+
+void wIconSetColor( wIcon_p ip, wDrawColor color )
+{
+ ip->color = color;
+}
+
diff --git a/app/wlib/gtklib/boxes.c b/app/wlib/gtklib/boxes.c
new file mode 100644
index 0000000..cce6649
--- /dev/null
+++ b/app/wlib/gtklib/boxes.c
@@ -0,0 +1,203 @@
+/** \file boxes.c
+ * Window for drawing a rectangle
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis,
+ * 2016 Martin Fischer <m_fischer@sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <cairo.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+
+struct wBox_t {
+ WOBJ_COMMON
+ wBoxType_e boxTyp;
+};
+
+#define B (1)
+#define W (2)
+#define SETCOLOR(ST, S, N ) \
+ if (colors[ST][S][N] == B ) { \
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); \
+ } else { \
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); \
+ }
+
+/**
+ * Set size of box window
+ *
+ * \param b IN window handle
+ * \param w IN new width
+ * \param h IN new height
+ * \return
+ *
+ */
+
+void wBoxSetSize(
+ wBox_p b,
+ wPos_t w,
+ wPos_t h)
+{
+ b->w = w;
+ b->h = h;
+}
+
+/**
+ * Draw the box
+ * \todo too many strokes, remove and test
+ *
+ * \param win IN window handle
+ * \param style IN frame style
+ * \param x IN x position
+ * \param y IN y position
+ * \param w IN width
+ * \param h IN height
+ * \return
+ */
+
+void wlibDrawBox(
+ wWin_p win,
+ wBoxType_e style,
+ wPos_t x,
+ wPos_t y,
+ wPos_t w,
+ wPos_t h)
+{
+ wPos_t x0, y0, x1, y1;
+ GdkDrawable * window;
+ cairo_t *cr;
+ static char colors[8][4][2] = {
+ { /* ThinB */ {B,0}, {B,0}, {B,0}, {B,0} },
+ { /* ThinW */ {W,0}, {W,0}, {W,0}, {W,0} },
+ { /* AboveW */ {W,0}, {W,0}, {B,0}, {B,0} },
+ { /* BelowW */ {B,0}, {B,0}, {W,0}, {W,0} },
+ { /* ThickB */ {B,B}, {B,B}, {B,B}, {B,B} },
+ { /* ThickW */ {W,W}, {W,W}, {W,W}, {W,W} },
+ { /* RidgeW */ {W,B}, {W,B}, {B,W}, {B,W} },
+ { /* TroughW*/ {B,W}, {B,W}, {W,B}, {W,B} }
+ };
+ window = gtk_widget_get_window(win->widget);
+ cr = gdk_cairo_create(window);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+ cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
+ cairo_set_line_width(cr, 1.0);
+ x0 = x;
+ x1 = x+w;
+ y0 = y;
+ y1 = y+h;
+ SETCOLOR(style, 0, 0);
+ cairo_move_to(cr, x0, y0);
+ cairo_line_to(cr, x0, y1);
+ cairo_stroke_preserve(cr);
+ SETCOLOR(style, 1, 0);
+ cairo_move_to(cr, x0, y0);
+ cairo_line_to(cr, x1, y0);
+ cairo_stroke_preserve(cr);
+ SETCOLOR(style, 2, 0);
+ cairo_move_to(cr, x1, y1);
+ cairo_line_to(cr, x0+1, y1);
+ cairo_stroke_preserve(cr);
+ SETCOLOR(style, 3, 0);
+ cairo_move_to(cr, x1, y1-1);
+ cairo_line_to(cr, x1, y0+1);
+ cairo_stroke_preserve(cr);
+
+ if (style < wBoxThickB) {
+ return;
+ }
+
+ x0++;
+ y0++;
+ x1--;
+ y1--;
+ SETCOLOR(style, 0, 1);
+ cairo_move_to(cr, x0, y0);
+ cairo_line_to(cr, x0, y1);
+ cairo_stroke_preserve(cr);
+ SETCOLOR(style, 1, 1);
+ cairo_move_to(cr, x0+1, y0);
+ cairo_line_to(cr, x1, y0);
+ cairo_stroke_preserve(cr);
+ SETCOLOR(style, 2, 1);
+ cairo_move_to(cr, x1, y1);
+ cairo_line_to(cr, x0+1, y1);
+ cairo_stroke_preserve(cr);
+ SETCOLOR(style, 3, 1);
+ cairo_move_to(cr, x1, y1-1);
+ cairo_line_to(cr, x1, y0+1);
+ cairo_stroke_preserve(cr);
+ cairo_destroy(cr);
+}
+
+/**
+ * Force repainting of box window
+ *
+ * \param b IN box window
+ * \return
+ */
+
+static void boxRepaint(wControl_p b)
+{
+ wBox_p bb = (wBox_p)(b);
+ wWin_p win = bb->parent;
+ wlibDrawBox(win, bb->boxTyp, bb->realX, bb->realY, bb->w, bb->h);
+}
+
+/**
+ * Create new box
+ *
+ * \param parent IN parent window
+ * \param bx IN x position
+ * \param by IN y position
+ * \param labelStr IN label text (ignored)
+ * \param boxTyp IN style
+ * \param bw IN x width
+ * \param by IN y width
+ * \return window handle for newly created box
+ */
+
+wBox_p wBoxCreate(
+ wWin_p parent,
+ wPos_t bx,
+ wPos_t by,
+ const char * labelStr,
+ wBoxType_e boxTyp,
+ wPos_t bw,
+ wPos_t bh)
+{
+ wBox_p b;
+ b = (wBox_p)wlibAlloc(parent, B_BOX, bx, by, labelStr, sizeof *b, NULL);
+ wlibComputePos((wControl_p)b);
+ b->boxTyp = boxTyp;
+ b->w = bw;
+ b->h = bh;
+ b->repaintProc = boxRepaint;
+ wlibAddButton((wControl_p)b);
+ return b;
+}
diff --git a/app/wlib/gtklib/button.c b/app/wlib/gtklib/button.c
new file mode 100644
index 0000000..d9f4880
--- /dev/null
+++ b/app/wlib/gtklib/button.c
@@ -0,0 +1,630 @@
+/** \file button.c
+ * Toolbar button creation and handling
+ */
+
+/* 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 <stdlib.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+#define MIN_BUTTON_WIDTH (80)
+
+/*
+ *****************************************************************************
+ *
+ * Simple Buttons
+ *
+ *****************************************************************************
+ */
+
+/**
+ * Set the state of the button
+ *
+ * \param bb IN the button
+ * \param value IN TRUE for active, FALSE for inactive
+ */
+
+void wButtonSetBusy(wButton_p bb, int value)
+{
+ bb->recursion++;
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bb->widget), value);
+ bb->recursion--;
+ bb->busy = value;
+}
+
+/**
+ * Set the label of a button, does also allow to set an icon
+ *
+ * \param widget IN
+ * \param option IN
+ * \param labelStr IN
+ * \param labelG IN
+ * \param imageG IN
+ */
+
+void wlibSetLabel(
+ GtkWidget *widget,
+ long option,
+ const char * labelStr,
+ GtkLabel * * labelG,
+ GtkWidget * * imageG)
+{
+ wIcon_p bm;
+ GdkBitmap * mask;
+
+ if (widget == 0) {
+ abort();
+ }
+
+ if (labelStr) {
+ if (option&BO_ICON) {
+ GdkPixbuf *pixbuf;
+
+ bm = (wIcon_p)labelStr;
+
+ if (bm->gtkIconType == gtkIcon_pixmap) {
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)bm->bits);
+ } else {
+ pixbuf = wlibPixbufFromXBM( bm );
+ }
+ if (*imageG==NULL) {
+ *imageG = gtk_image_new_from_pixbuf(pixbuf);
+ gtk_container_add(GTK_CONTAINER(widget), *imageG);
+ gtk_widget_show(*imageG);
+ } else {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(*imageG), pixbuf);
+ }
+
+ g_object_unref(pixbuf);
+ } else {
+ if (*labelG==NULL) {
+ *labelG = (GtkLabel*)gtk_label_new(wlibConvertInput(labelStr));
+ gtk_container_add(GTK_CONTAINER(widget), (GtkWidget*)*labelG);
+ gtk_widget_show((GtkWidget*)*labelG);
+ } else {
+ gtk_label_set_text(*labelG, wlibConvertInput(labelStr));
+ }
+ }
+ }
+}
+
+/**
+ * Change only the text label of a button
+ * \param bb IN button handle
+ * \param labelStr IN new label string
+ */
+
+void wButtonSetLabel(wButton_p bb, const char * labelStr)
+{
+ wlibSetLabel(bb->widget, bb->option, labelStr, &bb->labelG, &bb->imageG);
+}
+
+/**
+ * Perform the user callback function
+ *
+ * \param bb IN button handle
+ */
+
+void wlibButtonDoAction(
+ wButton_p bb)
+{
+ if (bb->action) {
+ bb->action(bb->data);
+ }
+}
+
+/**
+ * Signal handler for button push
+ * \param widget IN the widget
+ * \param value IN the button handle (same as widget???)
+ */
+
+static void pushButt(
+ GtkWidget *widget,
+ gpointer value)
+{
+ wButton_p b = (wButton_p)value;
+
+ if (debugWindow >= 2) {
+ printf("%s button pushed\n", b->labelStr?b->labelStr:"No label");
+ }
+
+ if (b->recursion) {
+ return;
+ }
+
+ if (b->action) {
+ b->action(b->data);
+ }
+
+ if (!b->busy) {
+ b->recursion++;
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b->widget), FALSE);
+ b->recursion--;
+ }
+}
+
+/**
+ * Create a button
+ *
+ * \param parent IN parent window
+ * \param x IN X-position
+ * \param y IN Y-position
+ * \param helpStr IN Help string
+ * \param labelStr IN Label
+ * \param option IN Options
+ * \param width IN Width of button
+ * \param action IN Callback
+ * \param data IN User data as context
+ * \returns button widget
+ */
+
+wButton_p wButtonCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ wButtonCallBack_p action,
+ void * data)
+{
+ wButton_p b;
+ b = wlibAlloc(parent, B_BUTTON, x, y, labelStr, sizeof *b, data);
+ b->option = option;
+ b->action = action;
+ wlibComputePos((wControl_p)b);
+
+ b->widget = gtk_toggle_button_new();
+ g_signal_connect(GTK_OBJECT(b->widget), "clicked",
+ G_CALLBACK(pushButt), b);
+ if (width > 0) {
+ gtk_widget_set_size_request(b->widget, width, -1);
+ }
+ if( labelStr ){
+ wButtonSetLabel(b, labelStr);
+ }
+
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+
+ if (option & BB_DEFAULT) {
+ gtk_widget_set_can_default(b->widget, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(b->widget);
+ gtk_window_set_default(GTK_WINDOW(parent->gtkwin), b->widget);
+ }
+
+ wlibControlGetSize((wControl_p)b);
+
+ if (width == 0 && b->w < MIN_BUTTON_WIDTH && (b->option&BO_ICON)==0) {
+ b->w = MIN_BUTTON_WIDTH;
+ gtk_widget_set_size_request(b->widget, b->w, b->h);
+ }
+
+ gtk_widget_show(b->widget);
+ wlibAddButton((wControl_p)b);
+ wlibAddHelpString(b->widget, helpStr);
+ return b;
+}
+
+
+/*
+ *****************************************************************************
+ *
+ * Choice Boxes
+ *
+ *****************************************************************************
+ */
+
+struct wChoice_t {
+ WOBJ_COMMON
+ long *valueP;
+ wChoiceCallBack_p action;
+ int recursion;
+};
+
+
+/**
+ * Get the state of a group of buttons. If the group consists of
+ * radio buttons, the return value is the index of the selected button
+ * or -1 for none. If toggle buttons are checked, a bit is set for each
+ * button that is active.
+ *
+ * \param bc IN
+ * \returns state of group
+ */
+
+static long choiceGetValue(
+ wChoice_p bc)
+{
+ GList * child, * children;
+ long value, inx;
+
+ if (bc->type == B_TOGGLE) {
+ value = 0;
+ } else {
+ value = -1;
+ }
+
+ for (children=child=gtk_container_get_children(GTK_CONTAINER(bc->widget)),inx=0;
+ child; child=child->next,inx++) {
+ if (gtk_toggle_button_get_active(child->data)) {
+ if (bc->type == B_TOGGLE) {
+ value |= (1<<inx);
+ } else {
+ value = inx;
+ }
+ }
+ }
+
+ if (children) {
+ g_list_free(children);
+ }
+
+ return value;
+}
+
+/**
+ * Set the active radio button in a group
+ *
+ * \param bc IN button group
+ * \param value IN index of active button
+ */
+
+void wRadioSetValue(
+ wChoice_p bc, /* Radio box */
+ long value) /* Value */
+{
+ GList * child, * children;
+ long inx;
+
+ for (children=child=gtk_container_get_children(GTK_CONTAINER(bc->widget)),inx=0;
+ child; child=child->next,inx++) {
+ if (inx == value) {
+ bc->recursion++;
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(child->data), TRUE);
+ bc->recursion--;
+ }
+ }
+
+ if (children) {
+ g_list_free(children);
+ }
+}
+
+/**
+ * Get the active button from a group of radio buttons
+ *
+ * \param bc IN
+ * \returns
+ */
+
+long wRadioGetValue(
+ wChoice_p bc) /* Radio box */
+{
+ return choiceGetValue(bc);
+}
+
+/**
+ * Set a group of toggle buttons from a bitfield
+ *
+ * \param bc IN button group
+ * \param value IN bitfield
+ */
+
+void wToggleSetValue(
+ wChoice_p bc, /* Toggle box */
+ long value) /* Values */
+{
+ GList * child, * children;
+ long inx;
+ bc->recursion++;
+
+ for (children=child=gtk_container_get_children(GTK_CONTAINER(bc->widget)),inx=0;
+ child; child=child->next,inx++) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(child->data),
+ (value&(1<<inx))!=0);
+ }
+
+ if (children) {
+ g_list_free(children);
+ }
+
+ bc->recursion--;
+}
+
+
+/**
+ * Get the active buttons from a group of toggle buttons
+ *
+ * \param b IN
+ * \returns
+ */
+
+long wToggleGetValue(
+ wChoice_p b) /* Toggle box */
+{
+ return choiceGetValue(b);
+}
+
+/**
+ * Signal handler for button selection in radio buttons and toggle
+ * button group
+ *
+ * \param widget IN the button group
+ * \param b IN user data (button group????)
+ * \returns always 1
+ */
+
+static int pushChoice(
+ GtkWidget *widget,
+ gpointer b)
+{
+ wChoice_p bc = (wChoice_p)b;
+ long value = choiceGetValue(bc);
+
+ if (debugWindow >= 2) {
+ printf("%s choice pushed = %ld\n", bc->labelStr?bc->labelStr:"No label",
+ value);
+ }
+
+ if (bc->type == B_RADIO &&
+ !(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))) {
+ return 1;
+ }
+
+ if (bc->recursion) {
+ return 1;
+ }
+
+ if (bc->valueP) {
+ *bc->valueP = value;
+ }
+
+ if (bc->action) {
+ bc->action(value, bc->data);
+ }
+
+ return 1;
+}
+
+/**
+ * Signal handler used to draw a frame around a widget, used to visually
+ * group several buttons together
+ *
+ * \param b IN widget
+ */
+
+static void choiceRepaint(
+ wControl_p b)
+{
+ wChoice_p bc = (wChoice_p)b;
+
+ if (gtk_widget_get_visible(b->widget)) {
+ wlibDrawBox(bc->parent, wBoxBelow, bc->realX-1, bc->realY-1, bc->w+1, bc->h+1);
+ }
+}
+
+/**
+ * Create a group of radio buttons.
+ *
+ * \param parent IN parent window
+ * \param x IN X-position
+ * \param y IN Y-position
+ * \param helpStr IN Help string
+ * \param labelStr IN Label
+ * \param option IN Options
+ * \param labels IN Labels
+ * \param valueP IN Selected value
+ * \param action IN Callback
+ * \param data IN User data as context
+ * \returns radio button widget
+ */
+
+wChoice_p wRadioCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ const char **labels,
+ long *valueP,
+ wChoiceCallBack_p action,
+ void *data)
+{
+ wChoice_p b;
+ const char ** label;
+ GtkWidget *butt0=NULL, *butt;
+
+ if ((option & BC_NOBORDER)==0) {
+ if (x>=0) {
+ x++;
+ } else {
+ x--;
+ }
+
+ if (y>=0) {
+ y++;
+ } else {
+ y--;
+ }
+ }
+
+ b = wlibAlloc(parent, B_RADIO, x, y, labelStr, sizeof *b, data);
+ b->option = option;
+ b->action = action;
+ b->valueP = valueP;
+ wlibComputePos((wControl_p)b);
+
+ if (option&BC_HORZ) {
+ b->widget = gtk_hbox_new(FALSE, 0);
+ } else {
+ b->widget = gtk_vbox_new(FALSE, 0);
+ }
+
+ if (b->widget == 0) {
+ abort();
+ }
+
+ for (label=labels; *label; label++) {
+ butt = gtk_radio_button_new_with_label(
+ butt0?gtk_radio_button_get_group(GTK_RADIO_BUTTON(butt0)):NULL, _(*label));
+
+ if (butt0==NULL) {
+ butt0 = butt;
+ }
+
+ gtk_box_pack_start(GTK_BOX(b->widget), butt, TRUE, TRUE, 0);
+ gtk_widget_show(butt);
+ g_signal_connect(GTK_OBJECT(butt), "toggled",
+ G_CALLBACK(pushChoice), b);
+ wlibAddHelpString(butt, helpStr);
+ }
+
+ if (option & BB_DEFAULT) {
+ gtk_widget_set_can_default(b->widget, TRUE);
+ gtk_widget_grab_default(b->widget);
+ }
+
+ if (valueP) {
+ wRadioSetValue(b, *valueP);
+ }
+
+ if ((option & BC_NOBORDER)==0) {
+ b->repaintProc = choiceRepaint;
+ b->w += 2;
+ b->h += 2;
+ }
+
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+ wlibControlGetSize((wControl_p)b);
+
+ if (labelStr) {
+ b->labelW = wlibAddLabel((wControl_p)b, labelStr);
+ }
+
+ gtk_widget_show(b->widget);
+ wlibAddButton((wControl_p)b);
+ return b;
+}
+
+/**
+ * Create a group of toggle buttons.
+ *
+ * \param parent IN parent window
+ * \param x IN X-position
+ * \param y IN Y-position
+ * \param helpStr IN Help string
+ * \param labelStr IN Label
+ * \param option IN Options
+ * \param labels IN Labels
+ * \param valueP IN Selected value
+ * \param action IN Callback
+ * \param data IN User data as context
+ * \returns toggle button widget
+ */
+
+wChoice_p wToggleCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ const char **labels,
+ long *valueP,
+ wChoiceCallBack_p action,
+ void *data)
+{
+ wChoice_p b;
+ const char ** label;
+
+ if ((option & BC_NOBORDER)==0) {
+ if (x>=0) {
+ x++;
+ } else {
+ x--;
+ }
+
+ if (y>=0) {
+ y++;
+ } else {
+ y--;
+ }
+ }
+
+ b = wlibAlloc(parent, B_TOGGLE, x, y, labelStr, sizeof *b, data);
+ b->option = option;
+ b->action = action;
+ wlibComputePos((wControl_p)b);
+
+ if (option&BC_HORZ) {
+ b->widget = gtk_hbox_new(FALSE, 0);
+ } else {
+ b->widget = gtk_vbox_new(FALSE, 0);
+ }
+
+ if (b->widget == 0) {
+ abort();
+ }
+
+ for (label=labels; *label; label++) {
+ GtkWidget *butt;
+
+ butt = gtk_check_button_new_with_label(_(*label));
+ gtk_box_pack_start(GTK_BOX(b->widget), butt, TRUE, TRUE, 0);
+ gtk_widget_show(butt);
+ g_signal_connect(GTK_OBJECT(butt), "toggled",
+ G_CALLBACK(pushChoice), b);
+ wlibAddHelpString(butt, helpStr);
+ }
+
+ if (valueP) {
+ wToggleSetValue(b, *valueP);
+ }
+
+ if ((option & BC_NOBORDER)==0) {
+ b->repaintProc = choiceRepaint;
+ b->w += 2;
+ b->h += 2;
+ }
+
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+ wlibControlGetSize((wControl_p)b);
+
+ if (labelStr) {
+ b->labelW = wlibAddLabel((wControl_p)b, labelStr);
+ }
+
+ gtk_widget_show(b->widget);
+ wlibAddButton((wControl_p)b);
+ return b;
+}
diff --git a/app/wlib/gtklib/color.c b/app/wlib/gtklib/color.c
new file mode 100644
index 0000000..64b96ef
--- /dev/null
+++ b/app/wlib/gtklib/color.c
@@ -0,0 +1,466 @@
+/** \file color.c
+ * code for the color selection dialog and color button
+ */
+
+/* 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 <assert.h>
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+
+wDrawColor wDrawColorWhite;
+wDrawColor wDrawColorBlack;
+
+#define RGB(R,G,B) ( ((long)((R)&0xFF)<<16) | ((long)((G)&0xFF)<<8) | ((long)((B)&0xFF)) )
+
+#define MAX_COLOR_DISTANCE (3)
+
+static GArray *colorMap_garray = NULL; // Change to use glib array
+
+static colorMap_t colorMap[] = {
+ { 255, 255, 255 }, /* White */
+ { 0, 0, 0 }, /* Black */
+ { 255, 0, 0 }, /* Red */
+ { 0, 255, 0 }, /* Green */
+ { 0, 0, 255 }, /* Blue */
+ { 255, 255, 0 }, /* Yellow */
+ { 255, 0, 255 }, /* Purple */
+ { 0, 255, 255 }, /* Aqua */
+ { 128, 0, 0 }, /* Dk. Red */
+ { 0, 128, 0 }, /* Dk. Green */
+ { 0, 0, 128 }, /* Dk. Blue */
+ { 128, 128, 0 }, /* Dk. Yellow */
+ { 128, 0, 128 }, /* Dk. Purple */
+ { 0, 128, 128 }, /* Dk. Aqua */
+ { 65, 105, 225 }, /* Royal Blue */
+ { 0, 191, 255 }, /* DeepSkyBlue */
+ { 125, 206, 250 }, /* LightSkyBlue */
+ { 70, 130, 180 }, /* Steel Blue */
+ { 176, 224, 230 }, /* Powder Blue */
+ { 127, 255, 212 }, /* Aquamarine */
+ { 46, 139, 87 }, /* SeaGreen */
+ { 152, 251, 152 }, /* PaleGreen */
+ { 124, 252, 0 }, /* LawnGreen */
+ { 50, 205, 50 }, /* LimeGreen */
+ { 34, 139, 34 }, /* ForestGreen */
+ { 255, 215, 0 }, /* Gold */
+ { 188, 143, 143 }, /* RosyBrown */
+ { 139, 69, 19 }, /* SaddleBrown */
+ { 245, 245, 220 }, /* Beige */
+ { 210, 180, 140 }, /* Tan */
+ { 210, 105, 30 }, /* Chocolate */
+ { 165, 42, 42 }, /* Brown */
+ { 255, 165, 0 }, /* Orange */
+ { 255, 127, 80 }, /* Coral */
+ { 255, 99, 71 }, /* Tomato */
+ { 255, 105, 180 }, /* HotPink */
+ { 255, 192, 203 }, /* Pink */
+ { 176, 48, 96 }, /* Maroon */
+ { 238, 130, 238 }, /* Violet */
+ { 160, 32, 240 }, /* Purple */
+ { 16, 16, 16 }, /* Gray */
+ { 32, 32, 32 }, /* Gray */
+ { 48, 48, 48 }, /* Gray */
+ { 64, 64, 64 }, /* Gray */
+ { 80, 80, 80 }, /* Gray */
+ { 96, 96, 96 }, /* Gray */
+ { 112, 112, 122 }, /* Gray */
+ { 128, 128, 128 }, /* Gray */
+ { 144, 144, 144 }, /* Gray */
+ { 160, 160, 160 }, /* Gray */
+ { 176, 176, 176 }, /* Gray */
+ { 192, 192, 192 }, /* Gray */
+ { 208, 208, 208 }, /* Gray */
+ { 224, 224, 224 }, /* Gray */
+ { 240, 240, 240 }, /* Gray */
+ { 0, 0, 0 } /* BlackPixel */
+};
+
+#define NUM_GRAYS (16)
+
+static GdkColormap * gtkColorMap;
+
+static char lastColorChar = '!';
+
+/**
+ * Get a gray color
+ *
+ * \param percent IN gray value required
+ * \return definition for gray color
+ */
+
+wDrawColor wDrawColorGray(
+ int percent)
+{
+ int n;
+ long rgb;
+ n = (percent * (NUM_GRAYS+1)) / 100;
+
+ if (n <= 0) {
+ return wDrawColorBlack;
+ } else if (n > NUM_GRAYS) {
+ return wDrawColorWhite;
+ } else {
+ n = (n*256)/NUM_GRAYS;
+ rgb = RGB(n, n, n);
+ return wDrawFindColor(rgb);
+ }
+}
+
+/**
+ * Get the color map for the main window
+ *
+ * \return
+ */
+
+void wlibGetColorMap(void)
+{
+ if (gtkColorMap) {
+ return;
+ }
+
+ gtkColorMap = gtk_widget_get_colormap(gtkMainW->widget);
+ return;
+}
+
+/**
+ * Initialize a colorMap entry
+ * \todo no idea what this is required for
+ *
+ * \param t IN color code
+ * \return
+ */
+
+static void init_colorMapValue(colorMap_t * t)
+{
+ t->rgb = RGB(t->red, t->green, t->blue);
+ t->normalColor.red = t->red*65535/255;
+ t->normalColor.green = t->green*65535/255;
+ t->normalColor.blue = t->blue*65535/255;
+ gdk_colormap_alloc_color(gtkColorMap, &t->normalColor, FALSE, TRUE);
+ t->invertColor = t->normalColor;
+ t->invertColor.pixel ^= g_array_index(colorMap_garray, colorMap_t,
+ wDrawColorWhite).normalColor.pixel;
+ t->colorChar = lastColorChar++;
+
+ if (lastColorChar >= 0x7F) {
+ lastColorChar = '!'+1;
+ } else if (lastColorChar == '"') {
+ lastColorChar++;
+ }
+}
+
+/**
+ * Allocate a color map and initialize with application default colors
+ *
+ * \return
+ */
+
+static void init_colorMap(void)
+{
+ int gint;
+ colorMap_garray = g_array_sized_new(TRUE, TRUE, sizeof(colorMap_t),
+ sizeof(colorMap)/sizeof(colorMap_t));
+ g_array_append_vals(colorMap_garray, &colorMap,
+ sizeof(colorMap)/sizeof(colorMap_t));
+
+ for (gint=0; gint<colorMap_garray->len; gint++) {
+ init_colorMapValue(&g_array_index(colorMap_garray, colorMap_t, gint));
+ }
+}
+
+/**
+ * Find the closest color from the palette and add a new color if there
+ * is no close match
+ * \todo improve method for finding best match (squared distances)
+ *
+ * \param rgb0 IN desired color
+ * \return palette index of matching color
+ */
+
+wDrawColor wDrawFindColor(
+ long rgb0)
+{
+ wDrawColor cc;
+ int r0, g0, b0;
+ int d0;
+ int i;
+ colorMap_t tempMapValue;
+ wlibGetColorMap();
+ cc = wDrawColorBlack;
+ r0 = (int)(rgb0>>16)&0xFF;
+ g0 = (int)(rgb0>>8)&0xFF;
+ b0 = (int)(rgb0)&0xFF;
+ d0 = 256*3;
+
+ // Initialize garray if needed
+ if (colorMap_garray == NULL) {
+ init_colorMap();
+ }
+
+ // Iterate over entire garray
+ for (i=0; i<colorMap_garray->len; i++) {
+ int d1;
+ colorMap_t * cm_p;
+
+ cm_p = &g_array_index(colorMap_garray, colorMap_t, i);
+ d1 = abs(r0-cm_p->red) + abs(g0-cm_p->green) + abs(b0-cm_p->blue);
+
+ if (d1 == 0) {
+ return i;
+ }
+
+ if (d1 < d0) {
+ d0 = d1;
+ cc = i;
+ }
+ }
+
+ if (d0 <= MAX_COLOR_DISTANCE) {
+ return cc;
+ }
+
+ // No good value - so add one
+ tempMapValue.red = r0;
+ tempMapValue.green = g0;
+ tempMapValue.blue = b0;
+ init_colorMapValue(&tempMapValue);
+ g_array_append_val(colorMap_garray,tempMapValue);
+ return i;
+}
+
+/**
+ * Get the RGB code for a palette entry
+ *
+ * \param color IN the palette index
+ * \return RGB code
+ */
+
+long wDrawGetRGB(
+ wDrawColor color)
+{
+ colorMap_t * colorMap_e;
+ wlibGetColorMap();
+
+ if (colorMap_garray == NULL) {
+ init_colorMap();
+ }
+
+ if (color < 0 || color > colorMap_garray->len) {
+ abort();
+ }
+
+ colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color);
+ return colorMap_e->rgb;
+}
+
+/**
+ * Get the color definition from the palette index
+ *
+ * \param color IN index into palette
+ * \param normal IN normal or inverted color
+ * \return the selected color definition
+ */
+
+GdkColor* wlibGetColor(
+ wDrawColor color,
+ wBool_t normal)
+{
+ colorMap_t * colorMap_e;
+ wlibGetColorMap();
+
+ if (colorMap_garray == NULL) {
+ init_colorMap();
+ }
+
+ if (color < 0 || color > colorMap_garray->len) {
+ abort();
+ }
+
+ colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color);
+
+ if (normal) {
+ return &colorMap_e->normalColor;
+ } else {
+ return &colorMap_e->invertColor;
+ }
+}
+
+
+/*
+ *****************************************************************************
+ *
+ * Color Selection Button
+ *
+ *****************************************************************************
+ */
+
+typedef struct {
+ wDrawColor * valueP;
+ const char * labelStr;
+ wColorSelectButtonCallBack_p action;
+ void * data;
+ wDrawColor color;
+ wButton_p button;
+} colorData_t;
+
+/**
+ * Handle the color-set signal.
+ *
+ * \param widget color button
+ * \param user_data
+ */
+
+static void
+colorChange(GtkColorButton *widget, gpointer user_data)
+{
+ colorData_t *cd = user_data;
+ GdkColor newcolor;
+ long rgb;
+
+ gtk_color_button_get_color(widget, &newcolor);
+
+ rgb = RGB((int)(newcolor.red/256), (int)(newcolor.green/256),
+ (int)(newcolor.blue/256));
+ cd->color = wDrawFindColor(rgb);
+
+ if (cd->valueP) {
+ *(cd->valueP) = cd->color;
+ }
+
+ if (cd->action) {
+ cd->action(cd->data, cd->color);
+ }
+}
+
+/**
+ * Set the color for a color button
+ *
+ * \param bb IN button
+ * \param color IN palette index for color to use
+ * \return describe the return value
+ */
+
+void wColorSelectButtonSetColor(
+ wButton_p bb,
+ wDrawColor color)
+{
+ GdkColor *colorOfButton = wlibGetColor(color, TRUE);
+
+ gtk_color_button_set_color(GTK_COLOR_BUTTON(bb->widget),
+ colorOfButton);
+ ((colorData_t*)((wControl_p)bb)->data)->color = color;
+}
+
+
+/**
+ * Get the current palette index for a color button
+ *
+ * \param bb IN button handle
+ * \return palette index
+ */
+
+wDrawColor wColorSelectButtonGetColor(
+ wButton_p bb)
+{
+ return ((colorData_t*)((wControl_p)bb)->data)->color;
+}
+
+/**
+ * Create the button showing the current paint color and starting the color selection dialog.
+ *
+ * \param IN parent parent window
+ * \param IN x x coordinate
+ * \param IN Y y coordinate
+ * \param IN helpStr balloon help string
+ * \param IN labelStr Button label ???
+ * \param IN option
+ * \param IN width
+ * \param IN valueP Current color ???
+ * \param IN action Button callback procedure
+ * \param IN data ???
+ * \return bb handle for created button
+ */
+
+wButton_p wColorSelectButtonCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ wPos_t width,
+ wDrawColor *valueP,
+ wColorSelectButtonCallBack_p action,
+ void * data)
+{
+ wButton_p b;
+ colorData_t * cd;
+ cd = malloc(sizeof(colorData_t));
+ cd->valueP = valueP;
+ cd->action = action;
+ cd->data = data;
+ cd->labelStr = labelStr;
+ cd->color = (valueP?*valueP:0);
+
+ b = wlibAlloc(parent, B_BUTTON, x, y, labelStr, sizeof *b, cd);
+ b->option = option;
+ wlibComputePos((wControl_p)b);
+
+ b->widget = gtk_color_button_new();
+ GtkStyle *style;
+ style = gtk_widget_get_style(b->widget);
+ style->xthickness = 1;
+ style->ythickness = 1;
+ gtk_widget_set_style(b->widget, style);
+ gtk_widget_set_size_request(GTK_WIDGET(b->widget), 22, 22);
+ g_signal_connect(GTK_OBJECT(b->widget), "color-set",
+ G_CALLBACK(colorChange), cd);
+
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+
+ if (option & BB_DEFAULT) {
+ gtk_widget_set_can_default(b->widget, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default(b->widget);
+ gtk_window_set_default(GTK_WINDOW(parent->gtkwin), b->widget);
+ }
+
+ wlibControlGetSize((wControl_p)b);
+
+ gtk_widget_show(b->widget);
+ wlibAddButton((wControl_p)b);
+ wlibAddHelpString(b->widget, helpStr);
+ wColorSelectButtonSetColor(b, (valueP?*valueP:0));
+
+ if (labelStr) {
+ ((wControl_p)b)->labelW = wlibAddLabel((wControl_p)b, labelStr);
+ }
+ return b;
+}
diff --git a/app/wlib/gtklib/control.c b/app/wlib/gtklib/control.c
new file mode 100644
index 0000000..e824c94
--- /dev/null
+++ b/app/wlib/gtklib/control.c
@@ -0,0 +1,283 @@
+/** \file control.c
+ * Control Utilities
+ */
+/*
+ * Copyright 2016 Martin Fischer <m_fischer@sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+
+#define GTKCONTROLHILITEWIDTH (3)
+
+/**
+ * Cause the control <b> to be displayed or hidden.
+ * Used to hide control (such as a list) while it is being updated.
+ *
+ * \param b IN Control
+ * \param show IN TRUE for visible
+ */
+
+void wControlShow(
+ wControl_p b,
+ wBool_t show)
+{
+ if (b->type == B_LINES) {
+ wlibLineShow((wLine_p)b, show);
+ return;
+ }
+
+ if (b->widget == NULL) {
+ abort();
+ }
+
+ if (show) {
+ gtk_widget_show(b->widget);
+
+ if (b->label) {
+ gtk_widget_show(b->label);
+ }
+ } else {
+ gtk_widget_hide(b->widget);
+
+ if (b->label) {
+ gtk_widget_hide(b->label);
+ }
+ }
+}
+
+/**
+ * Cause the control <b> to be marked active or inactive.
+ * Inactive controls donot respond to actions.
+ *
+ * \param b IN Control
+ * \param active IN TRUE for active
+ */
+
+void wControlActive(
+ wControl_p b,
+ int active)
+{
+ if (b->widget == NULL) {
+ abort();
+ }
+
+ gtk_widget_set_sensitive(GTK_WIDGET(b->widget), active);
+}
+
+/**
+ * Returns the width of <label>.
+ * This is used for computing window layout.
+ * Typically the width to the longest label is computed and used as
+ * the X-position for <controls>.
+ *
+ * \param label IN label
+ * \returns width of label including some space
+*/
+
+wPos_t wLabelWidth(
+ const char * label)
+{
+ GtkWidget * widget;
+ GtkRequisition requisition;
+ widget = gtk_label_new(wlibConvertInput(label));
+ gtk_widget_size_request(widget, &requisition);
+ gtk_widget_destroy(widget);
+ return requisition.width+8;
+}
+
+/**
+ * Get width of a control
+ *
+ * \param b IN Control
+ * \returns width
+ */
+
+wPos_t wControlGetWidth(
+ wControl_p b)
+{
+ return b->w;
+}
+
+/**
+ * Get height of a control
+ *
+ * \param b IN Control
+ * \returns height
+ */
+
+wPos_t wControlGetHeight(
+ wControl_p b)
+{
+ return b->h;
+}
+
+/**
+ * Get x position of a control
+ *
+ * \param b IN Control
+ * \returns position
+ */
+
+wPos_t wControlGetPosX(
+ wControl_p b) /* Control */
+{
+ return b->realX;
+}
+
+/**
+ * Get y position of a control
+ *
+ * \param b IN Control
+ * \returns position
+ */
+
+wPos_t wControlGetPosY(
+ wControl_p b) /* Control */
+{
+ return b->realY - BORDERSIZE - ((b->parent->option&F_MENUBAR)?MENUH:0);
+}
+
+/**
+ * Set the fixed position of a control within its parent window
+ *
+ * \param b IN control
+ * \param x IN x position
+ * \param y IN y position
+ */
+
+void wControlSetPos(
+ wControl_p b,
+ wPos_t x,
+ wPos_t y)
+{
+ b->realX = x;
+ b->realY = y + BORDERSIZE + ((b->parent->option&F_MENUBAR)?MENUH:0);
+
+ if (b->widget) {
+ gtk_fixed_move(GTK_FIXED(b->parent->widget), b->widget, b->realX, b->realY);
+ }
+
+ if (b->label) {
+ gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW,
+ b->realY+LABEL_OFFSET);
+ }
+}
+
+/**
+ * Set the label for a control
+ *
+ * \param b IN control
+ * \param labelStr IN the new label
+ */
+
+void wControlSetLabel(
+ wControl_p b,
+ const char * labelStr)
+{
+ GtkRequisition requisition;
+
+ if (b->label) {
+ gtk_label_set_text(GTK_LABEL(b->label), wlibConvertInput(labelStr));
+ gtk_widget_size_request(b->label, &requisition);
+ b->labelW = requisition.width+8;
+ gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW,
+ b->realY+LABEL_OFFSET);
+ } else {
+ b->labelW = wlibAddLabel(b, labelStr);
+ }
+}
+
+/**
+ * Set the context ie. additional user data for a control
+ *
+ * \param b IN control
+ * \param context IN user date
+ */
+
+void wControlSetContext(
+ wControl_p b,
+ void * context)
+{
+ b->data = context;
+}
+
+/**
+ * Not implemented
+ *
+ * \param b IN
+ */
+
+void wControlSetFocus(
+ wControl_p b)
+{
+}
+
+/**
+ * Draw a rectangle around a control
+ * \param b IN the control
+ * \param hilite IN unused
+ * \returns
+ *
+ *
+ */
+void wControlHilite(
+ wControl_p b,
+ wBool_t hilite)
+{
+ cairo_t *cr;
+ int off = GTKCONTROLHILITEWIDTH/2+1;
+
+ if (b->widget == NULL) {
+ return;
+ }
+
+ if (! gtk_widget_get_visible(b->widget)) {
+ return;
+ }
+
+ if (! gtk_widget_get_visible(b->parent->widget)) {
+ return;
+ }
+
+ cr = gdk_cairo_create(gtk_widget_get_window(b->parent->gtkwin));
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_set_operator(cr, CAIRO_OPERATOR_XOR);
+ cairo_set_line_width(cr, GTKCONTROLHILITEWIDTH);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+ cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
+ cairo_rectangle(cr,
+ b->realX - GTKCONTROLHILITEWIDTH,
+ b->realY - off,
+ b->w + GTKCONTROLHILITEWIDTH,
+ b->h + off + 1);
+ cairo_stroke(cr);
+ cairo_destroy(cr);
+}
diff --git a/app/wlib/gtklib/droplist.c b/app/wlib/gtklib/droplist.c
new file mode 100644
index 0000000..3252905
--- /dev/null
+++ b/app/wlib/gtklib/droplist.c
@@ -0,0 +1,456 @@
+/** \file droplist.c
+ * Dropdown list functions
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) Dave Bullis 2005, Martin Fischer 2016
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include "gtkint.h"
+#include "i18n.h"
+
+/* define the column count for the tree model */
+#define DROPLIST_TEXTCOLUMNS 1
+
+/**
+ * Add the data columns to the droplist. If dropList has an entry field
+ * the first text column is not added here as this is done by GTK
+ * automatically.
+ *
+ * \param dropList IN
+ * \param columns IN
+ * \returns number of columns created
+ */
+
+int
+wlibDropListAddColumns(GtkWidget *dropList, int columns)
+{
+ int i;
+ int start = 0;
+ GtkCellRenderer *cell;
+
+ if (gtk_combo_box_get_has_entry(GTK_COMBO_BOX(dropList))) {
+ start = 1;
+ }
+
+ /* Create cell renderer. */
+ cell = gtk_cell_renderer_text_new();
+
+ for (i = start; i < columns; i++) {
+ /* Pack it into the droplist */
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropList), cell, TRUE);
+
+ /* Connect renderer to data source */
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropList),
+ cell,
+ "text",
+ LISTCOL_TEXT + i,
+ NULL);
+ }
+
+ return (i);
+}
+
+/**
+ * Get the number of rows in drop list
+ *
+ * \param b IN widget
+ * \return number of rows
+ */
+
+wIndex_t wDropListGetCount(wList_p b)
+{
+ return (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(b->listStore), NULL));
+}
+
+/**
+ * Clear the whole droplist
+ *
+ * \param b IN the droplist
+ * \return
+ */
+
+void
+wDropListClear(wList_p b)
+{
+ wlibListStoreClear(b->listStore);
+}
+
+/**
+ * Get the user data / context information for a row in the droplist
+ * \param b IN widget
+ * \param inx IN row
+ * \returns pointer to context information
+ */
+
+void *wDropListGetItemContext(wList_p b, wIndex_t inx)
+{
+ GtkTreeIter iter;
+ wListItem_p data = NULL;
+
+ if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), &iter, NULL,
+ inx)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(b->listStore),
+ &iter,
+ LISTCOL_DATA, (void *)&data,
+ -1);
+ }
+
+ if (data) {
+ return (data->itemData);
+ } else {
+ return (NULL);
+ }
+}
+
+/**
+ * Add an entry to a dropdown list. Only single text entries are allowed
+ *
+ * \param b IN the widget
+ * \param text IN string to add
+ * \return describe the return value
+ */
+
+void wDropListAddValue(
+ wList_p b,
+ char *text,
+ wListItem_p data)
+{
+ GtkTreeIter iter;
+
+ assert(b != NULL);
+ assert(text != NULL);
+
+ gtk_list_store_append(b->listStore, &iter); // append new row to tree store
+
+ gtk_list_store_set(b->listStore, &iter,
+ LISTCOL_TEXT, text,
+ LISTCOL_DATA, (void *)data,
+ -1);
+}
+
+/**
+ * Set the value to the entry field of a droplist
+ * \param bl IN
+ * \param val IN
+ */
+
+void wListSetValue(
+ wList_p bl,
+ const char * val)
+{
+ assert(bl->listStore!=NULL);
+
+ bl->recursion++;
+
+ if (bl->type == B_DROPLIST) {
+ bl->editted = TRUE;
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(bl->widget))), val);
+
+ if (bl->action) {
+ bl->action(-1, val, 0, bl->data, NULL);
+ }
+ } else {
+ assert(FALSE);
+ }
+
+ bl->recursion--;
+}
+
+/**
+ * Makes the <val>th entry (0-origin) the current selection.
+ * If <val> if '-1' then no entry is selected.
+ *
+ * \param b IN the widget
+ * \param val IN the index
+ *
+ * \todo it seems BL_NONE is not used in current code, check and clean up
+ */
+
+void wDropListSetIndex(wList_p b, int val)
+{
+ if ((b->option&BL_NONE)!=0 && val < 0) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(b->widget), -1);
+ } else {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(b->widget), val);
+ }
+}
+
+/**
+ * Set the values for a row in the droplist
+ *
+ * \param b IN drop list widget
+ * \param row IN index
+ * \param labelStr IN new text
+ * \param bm IN ignored
+ * \param itemData IN ignored
+ * \return
+ */
+
+wBool_t wDropListSetValues(
+ wList_p b,
+ wIndex_t row,
+ const char * labelStr,
+ wIcon_p bm,
+ void *itemData)
+{
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore), &iter, NULL,
+ row)) {
+ gtk_list_store_set(b->listStore,
+ &iter,
+ LISTCOL_TEXT, labelStr,
+ -1);
+ return (TRUE);
+ } else {
+ return (FALSE);
+ }
+}
+
+/**
+ * Signal handler for the "changed"-signal in drop list's entry field.
+ * Get the entered text and calls the 'action' for handling of entered
+ * value.
+ * *
+ * \param entry IN entry field of the droplist
+ * \param data IN the drop list handle
+ * \return
+ */
+
+static void DropListEntryEntered(
+ GtkEntry * entry,
+ gpointer userData)
+{
+ const gchar * text;
+
+ text = gtk_entry_get_text(entry);
+
+ if (text && *text != '\0') {
+ gchar *copyOfText = g_strdup(text);
+ ((wList_p)userData)->editted = TRUE;
+ ((wList_p)userData)->action(-1, copyOfText, 1, ((wList_p)userData)->data, NULL);
+ g_free((gpointer)copyOfText);
+ } else {
+ wBeep();
+ }
+}
+
+/**
+ * Signal handler for the "changed"-signal in drop list. Gets the selected
+ * text and determines the selected row in the tree model.
+ *
+ * \param comboBox IN the combo_box
+ * \param data IN the drop list handle
+ * \return
+ */
+
+static int DropListSelectChild(
+ GtkComboBox * comboBox,
+ gpointer data)
+{
+ wList_p bl = (wList_p)data;
+ GtkTreeIter iter;
+
+ wIndex_t inx = 0;
+ gchar *string;
+ wListItem_p addData;
+
+ if (bl->recursion) {
+ return 0;
+ }
+
+ bl->editted = FALSE;
+
+ /* Obtain currently selected item from combo box.
+ * If nothing is selected, do nothing. */
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(comboBox), &iter)) {
+ GtkTreeModel *model;
+
+ /* Obtain data model from combo box. */
+ model = gtk_combo_box_get_model(comboBox);
+
+ /* get the selected row */
+ string = gtk_tree_model_get_string_from_iter(model,
+ &iter);
+ inx = atoi(string);
+ g_free(string);
+
+ /* Obtain string from model. */
+ gtk_tree_model_get(model, &iter,
+ LISTCOL_TEXT, &string,
+ LISTCOL_DATA, (void *)&addData,
+ -1);
+
+ } else {
+ return 0;
+ }
+
+ /* selection changed, store new selections and call back */
+ if (bl->last != inx) {
+
+ bl->last = inx;
+
+ if (bl->valueP) {
+ *bl->valueP = inx;
+ }
+
+ /* selection changed -> callback */
+ if (string && bl->action) {
+ bl->action(inx, string, 1, bl->data, addData->itemData);
+ }
+ }
+
+ g_free(string);
+ return 1;
+}
+
+/**
+ * Create a droplist for a given liststore
+ *
+ * \param ls IN list store for dropbox
+ * \param editable IN droplist with entry field
+ * \returns the newly created widget
+ */
+
+GtkWidget *
+wlibNewDropList(GtkListStore *ls, int editable)
+{
+ GtkWidget *widget;
+
+ if (editable) {
+ widget = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(ls));
+ } else {
+ widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(ls));
+ }
+
+ return (widget);
+}
+
+/**
+ * Create a drop down list. The drop down is created and intialized with the supplied values.
+ *
+ * \param IN parent Parent window
+ * \param IN x, X-position
+ * \param IN y Y-position
+ * \param IN helpStr Help string
+ * \param IN labelStr Label
+ * \param IN option Options
+ * \param IN number Number of displayed entries
+ * \param IN width Width
+ * \param IN valueP Selected index
+ * \param IN action Callback
+ * \param IN data Context
+ */
+
+wList_p wDropListCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ long number,
+ wPos_t width,
+ long *valueP,
+ wListCallBack_p action,
+ void *data)
+{
+ wList_p b;
+
+ b = (wList_p)wlibAlloc(parent, B_DROPLIST, x, y, labelStr, sizeof *b, data);
+ b->option = option;
+ b->number = number;
+ b->count = 0;
+ b->last = -1;
+ b->valueP = valueP;
+ b->action = action;
+ b->listX = b->realX;
+ b->colCnt = 0;
+ b->colWidths = NULL;
+ b->colRightJust = NULL;
+ b->editable = ((option & BL_EDITABLE) != 0);
+
+ assert(width != 0);
+
+ wlibComputePos((wControl_p)b);
+
+
+ // create tree store for storing the contents
+ b->listStore = wlibNewListStore(DROPLIST_TEXTCOLUMNS);
+
+ if (!b->listStore) {
+ abort();
+ }
+
+ // create the droplist
+ b->widget = wlibNewDropList(b->listStore,
+ option & BL_EDITABLE);
+
+ if (b->widget == 0) {
+ abort();
+ }
+
+ g_object_unref(G_OBJECT(b->listStore));
+
+ wlibDropListAddColumns(b->widget, DROPLIST_TEXTCOLUMNS);
+
+ gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(b->widget),
+ LISTCOL_TEXT);
+
+ // combo's style
+ gtk_rc_parse_string("style \"my-style\" { GtkComboBox::appears-as-list = 1 } widget \"*.mycombo\" style \"my-style\" ");
+ gtk_widget_set_name(b->widget,"mycombo");
+
+ g_signal_connect(GTK_OBJECT(b->widget), "changed",
+ G_CALLBACK(DropListSelectChild), b);
+
+ if (option & BL_EDITABLE) {
+ g_signal_connect(gtk_bin_get_child(GTK_BIN(b->widget)),
+ "changed",
+ G_CALLBACK(DropListEntryEntered),
+ b);
+ }
+
+ gtk_widget_set_size_request(b->widget, width, -1);
+
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+ wlibControlGetSize((wControl_p)b);
+
+ if (labelStr) {
+ b->labelW = wlibAddLabel((wControl_p)b, labelStr);
+ }
+
+ gtk_widget_show(b->widget);
+ wlibAddButton((wControl_p)b);
+ wlibAddHelpString(b->widget, helpStr);
+
+ return b;
+}
+
diff --git a/app/wlib/gtklib/dynarr.h b/app/wlib/gtklib/dynarr.h
index 13c0ede..2adf115 100644
--- a/app/wlib/gtklib/dynarr.h
+++ b/app/wlib/gtklib/dynarr.h
@@ -17,6 +17,10 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+
+#ifndef DYNARR_H_SEEN
+#define DYNARR_H_SEEN
+
typedef struct {
int cnt;
int max;
@@ -47,3 +51,4 @@ typedef struct {
abort(); \
} \
(DA).cnt = 0; }
+#endif /* DYNARR_H_SEEN */
diff --git a/app/wlib/gtklib/filesel.c b/app/wlib/gtklib/filesel.c
index 4b92389..ca30c7f 100644
--- a/app/wlib/gtklib/filesel.c
+++ b/app/wlib/gtklib/filesel.c
@@ -28,6 +28,12 @@
#include <unistd.h>
#include <string.h>
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
#include "gtkint.h"
#include "i18n.h"
@@ -71,9 +77,6 @@ struct wFilSel_t * wFilSelCreate(
void * data )
{
struct wFilSel_t *fs;
- int count;
- char * cp;
- GtkFileFilter *filter;
fs = (struct wFilSel_t*)malloc(sizeof *fs);
if (!fs)
@@ -88,9 +91,10 @@ struct wFilSel_t * wFilSelCreate(
fs->data = data;
if (pattList) {
+ char * cp = strdup(pattList);
+ int count = 0;
+
//create filters for the passed filter list
- cp = strdup(pattList);
- count = 0;
// names and patterns are separated by |
cp = strtok( cp, "|" );
while ( cp && count < (MAX_ALLOWEDFILTERS - 1)) {
@@ -130,15 +134,9 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName )
char name[1024];
char *host;
char *file;
- char *namePart;
int i;
- GSList *fileNameList;
GError *err = NULL;
- GtkFileFilter *activeFilter;
-
- char **fileNames;
-
- char * cp;
+
if (fs->window == NULL) {
fs->window = gtk_file_chooser_dialog_new( fs->title,
GTK_WINDOW( fs->parent->gtkwin ),
@@ -164,20 +162,25 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName )
}
strcpy( name, dirName );
- cp = name+strlen(name);
- if (cp[-1] != '/') {
- *cp++ = '/';
- *cp = 0;
- }
- if( fs->mode == FS_SAVE )
- gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER(fs->window), name );
+ if( fs->mode == FS_SAVE )
+ gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(fs->window), name );
+ // Add a current folder and a shortcut to it for Load/import dialogs
+ if( fs->mode == FS_LOAD ) {
+ gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(fs->window), name );
+ gtk_file_chooser_add_shortcut_folder( GTK_FILE_CHOOSER(fs->window), name, NULL );
+ }
+
if( gtk_dialog_run( GTK_DIALOG( fs->window )) == GTK_RESPONSE_ACCEPT ) {
+ char **fileNames;
+ GSList *fileNameList;
fileNameList = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER(fs->window) );
fileNames = calloc( sizeof(char *), g_slist_length (fileNameList) );
for (i=0; i < g_slist_length (fileNameList); i++ ) {
+ char *namePart;
+
file = g_filename_from_uri( g_slist_nth_data( fileNameList, i ), &host, &err );
// check for presence of file extension
@@ -205,7 +208,7 @@ int wFilSelect( struct wFilSel_t * fs, const char * dirName )
}
free( fileNames );
g_slist_free (fileNameList);
- }
+ }
gtk_widget_hide( GTK_WIDGET( fs->window ));
return 1;
diff --git a/app/wlib/gtklib/font.c b/app/wlib/gtklib/font.c
new file mode 100644
index 0000000..c54f7de
--- /dev/null
+++ b/app/wlib/gtklib/font.c
@@ -0,0 +1,403 @@
+/** \file font.c
+ * Font selection and loading.
+ */
+
+/* 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 <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "wlib.h"
+#include "gtkint.h"
+#include "i18n.h"
+
+/*
+ * Macro for debug purposes. Possible debug macro values:
+ *
+ * 0 - no messages to console (use this value when building in release mode)
+ * 1 - send errors
+ * 2 - send details
+ * 3 - send more details
+ */
+#define WLIB_FONT_DEBUG 0
+
+static gchar sampleText[] = "AbCdE0129!@$&()[]{}";
+
+static GtkWidget *fontSelectionDialog;
+
+
+/*****************************************************************************
+ * FONT HANDLERS
+ */
+
+#define FW_MEDIUM (0)
+#define FW_BOLD (1)
+#define FS_REGULAR (0)
+#define FS_ITALIC (1)
+
+/* absoluteFontSize was introduced to keep the font size information synchron
+ * between the Dt.size of ctext.c and it's drop list on the status bar and
+ * the font size coming from the gtk font dialog which is located in this file */
+int absoluteFontSize = 18;
+
+struct wFont_t {
+ PangoFontDescription *fontDescription;
+};
+
+static wFont_p standardFonts[F_HELV-F_TIMES+1][2][2];
+static wFont_p curFont = NULL;
+
+/**
+ * Callback for font selection dialog
+ *
+ * \param fontSelectionDialog IN dialog
+ * \param response IN response code from dialog
+ * \param data IN unused
+ * \return
+ */
+
+static void fontSelectionDialogCallback(GtkFontSelectionDialog
+ *fontSelectionDialog, gint response, gpointer data)
+{
+ if (response == GTK_RESPONSE_APPLY || response == GTK_RESPONSE_OK) {
+ gchar *fontName;
+
+ fontName = gtk_font_selection_dialog_get_font_name(fontSelectionDialog);
+ wPrefSetString("font", "name", fontName);
+ pango_font_description_free(curFont->fontDescription);
+ curFont->fontDescription = pango_font_description_from_string(fontName);
+ absoluteFontSize = (pango_font_description_get_size(
+ curFont->fontDescription))/PANGO_SCALE;
+#if WLIB_FONT_DEBUG >= 2
+ fprintf(stderr, "new font selection:\n");
+ fprintf(stderr, " font name \"%s\"\n", fontName);
+ fprintf(stderr, " font size is %d\n",
+ pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE);
+ fprintf(stderr, " font size is absolute %d\n",
+ pango_font_description_get_size_is_absolute(curFont->fontDescription));
+#endif
+ g_free(fontName);
+ }
+
+ if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_CANCEL) {
+ gtk_widget_hide(GTK_WIDGET(fontSelectionDialog));
+ }
+}
+
+static wBool_t fontInitted = FALSE;
+
+static wBool_t fontInit()
+{
+ const char *fontNames[] = {
+ "times 18",
+ "times italic 18",
+ "times bold 18",
+ "times bold italic 18",
+ "helvetica 18",
+ "helvetica oblique 18",
+ "helvetica bold 18",
+ "helvetica bold oblique 18",
+ };
+ int s = 0;
+ int i, j, k;
+
+ for (i = F_TIMES; i <= F_HELV; ++i) {
+ for (j = FW_MEDIUM; j <= FW_BOLD; ++j) {
+ for (k = FS_REGULAR; k <= FS_ITALIC; ++k) {
+ PangoFontDescription *fontDescription = pango_font_description_from_string(
+ fontNames[s++]);
+ wFont_p standardFont = (wFont_p) malloc(sizeof(struct wFont_t));
+ standardFont->fontDescription = fontDescription;
+ standardFonts[i-F_TIMES][j][k] = standardFont;
+ }
+ }
+ }
+
+ if (curFont == NULL) {
+ curFont = (wFont_p) malloc(sizeof(struct wFont_t));
+
+ if (curFont == NULL) {
+ return FALSE;
+ }
+
+ const char *fontName = wPrefGetString("font", "name");
+ curFont->fontDescription = pango_font_description_from_string(
+ fontName ? fontName : "helvetica 18");
+ absoluteFontSize = (int) PANGO_PIXELS(pango_font_description_get_size(
+ curFont->fontDescription));
+ }
+
+ fontInitted = TRUE;
+ return TRUE;
+}
+
+
+static double fontFactor = 1.0;
+
+#define FONTSIZE_TO_PANGOSIZE(fs) ((gint) ((fs) * (fontFactor) + .5))
+
+/**
+ * Create a Pango layout with a specified font and font size
+ *
+ * \param widget IN
+ * \param cairo IN cairo context
+ * \param fp IN font
+ * \param fs IN size
+ * \param s IN ???
+ * \param width_p OUT width of layout
+ * \param height_p OUT height of layout
+ * \param ascent_p OUT ascent of layout
+ * \param descent_p OUT descent of layout
+ * \return the created Pango layout
+ */
+
+PangoLayout *wlibFontCreatePangoLayout(GtkWidget *widget,
+ void *cairo,
+ wFont_p fp,
+ wFontSize_t fs,
+ const char *s,
+ int *width_p,
+ int *height_p,
+ int *ascent_p,
+ int *descent_p)
+{
+ if (!fontInitted) {
+ fontInit();
+ }
+
+ PangoLayout *layout = NULL;
+ gchar *utf8 = wlibConvertInput(s);
+ /* RPH -- pango_cairo_create_layout() is missing in CentOS 4.8.
+ CentOS 4.8 only has GTK 2.4.13 and Pango 1.6.0 and does not have
+ libpangocairo at all.
+ pango_cairo_create_layout() was introduced with Pango 1.10. */
+#if PANGO_VERSION_MAJOR >= 1 && PANGO_VERSION_MINOR >= 10
+
+ if (cairo != NULL) {
+ layout = pango_cairo_create_layout((cairo_t *) cairo);
+ pango_layout_set_text(layout, utf8, -1);
+ } else
+#endif
+ layout = gtk_widget_create_pango_layout(widget, utf8);
+
+ PangoFontDescription *fontDescription = (fp ? fp : curFont)->fontDescription;
+ PangoContext *context;
+ PangoFontMetrics *metrics;
+ /* set attributes */
+ pango_font_description_set_size(fontDescription,
+ FONTSIZE_TO_PANGOSIZE(fs) * PANGO_SCALE);
+ pango_layout_set_font_description(layout, fontDescription);
+ /* get layout measures */
+ pango_layout_get_pixel_size(layout, width_p, height_p);
+ context = gtk_widget_get_pango_context(widget);
+ metrics = pango_context_get_metrics(context, fontDescription,
+ pango_context_get_language(context));
+ *ascent_p = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics));
+ *descent_p = PANGO_PIXELS(pango_font_metrics_get_descent(metrics));
+ pango_font_metrics_unref(metrics);
+#if WLIB_FONT_DEBUG >= 3
+ fprintf(stderr, "font layout created:\n");
+ fprintf(stderr, " widget: %p\n", widget);
+ //fprintf(stderr, " font description:%p\n", fp);
+ fprintf(stderr, " font size: %f\n", fs);
+ fprintf(stderr, " layout text: \"%s\" (utf8)\n", utf8);
+ fprintf(stderr, " layout width: %d\n", *width_p);
+ fprintf(stderr, " layout height: %d\n", *height_p);
+ fprintf(stderr, " layout ascent: %d (pixels)\n", *ascent_p);
+ fprintf(stderr, " layout descent: %d (pixels)\n", *descent_p);
+#endif
+ return layout;
+}
+
+/**
+ * Destroy a previously allocated Pango layout
+ * \return
+ */
+
+void wlibFontDestroyPangoLayout(PangoLayout *layout)
+{
+ g_object_unref(G_OBJECT(layout));
+}
+
+/**
+ * Initialize font data
+ * \return
+ */
+
+void wInitializeFonts()
+{
+ if (!fontInitted) {
+ fontInit();
+ }
+}
+
+/**
+ * Initialize and run the font dialog
+ *
+ * \param title IN dialog box title
+ * \return
+ */
+
+void wSelectFont(
+ const char * title)
+{
+ if (!fontInitted) {
+ fontInit();
+ }
+
+ if (fontSelectionDialog == NULL) {
+ fontSelectionDialog = gtk_font_selection_dialog_new(_("Font Select"));
+ gtk_window_set_position(GTK_WINDOW(fontSelectionDialog), GTK_WIN_POS_MOUSE);
+ gtk_window_set_modal(GTK_WINDOW(fontSelectionDialog), TRUE);
+ gtk_font_selection_dialog_set_preview_text(GTK_FONT_SELECTION_DIALOG(
+ fontSelectionDialog), sampleText);
+ g_signal_connect(G_OBJECT(fontSelectionDialog), "response",
+ G_CALLBACK(fontSelectionDialogCallback), NULL);
+ g_signal_connect(G_OBJECT(fontSelectionDialog), "destroy",
+ G_CALLBACK(gtk_widget_destroyed), &fontSelectionDialog);
+ }
+
+ gtk_window_set_title(GTK_WINDOW(fontSelectionDialog), title);
+
+ if (curFont != NULL) {
+ gchar *fontName;
+
+ /* the curFont description contains the latest font info
+ * which is depended on the current scale
+ * overwrite it with the absoluteFontSize */
+ pango_font_description_set_size(curFont->fontDescription,
+ FONTSIZE_TO_PANGOSIZE(absoluteFontSize) * PANGO_SCALE);
+ fontName = pango_font_description_to_string(curFont->fontDescription);
+ gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(
+ fontSelectionDialog), fontName);
+ g_free(fontName);
+ }
+
+ gtk_widget_show(fontSelectionDialog);
+}
+
+/**
+ * Get the current font
+ *
+ * \return describe the return value
+ */
+
+static wFont_p wlibSelectedFont(void)
+{
+ if (!fontInitted) {
+ fontInit();
+ }
+
+ return curFont;
+}
+
+/**
+ * Get the default font size
+ *
+ * \return describe the return value
+ */
+
+wFontSize_t wSelectedFontSize(void)
+{
+ if (!fontInitted) {
+ fontInit();
+ }
+
+#if WLIB_FONT_DEBUG >= 3
+ fprintf(stderr, "the font size of current font description is: %d\n",
+ pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE);
+ fprintf(stderr, "the font size of absoluteFontSize is: %d\n",absoluteFontSize);
+#endif
+ return absoluteFontSize;
+}
+
+/**
+ * Set the default font size
+ *
+ * \param size IN font size
+ * \return describe the return value
+ */
+
+void wSetSelectedFontSize(int size)
+{
+ absoluteFontSize = (wFontSize_t)size;
+}
+
+/**
+ * get the Pango font description as a string from a font definition.
+ * If the font definition is NULL, a default font is return. This is
+ * the current font if one is set. If not the first font from the font
+ * list is returned.
+ *
+ * \param fp IN the font definition
+ * \return the font description
+ */
+
+const char *wlibFontTranslate(wFont_p fp)
+{
+ static gchar *fontName = NULL;
+
+ if (fontName != NULL) {
+ g_free(fontName);
+ }
+
+ if (!fontInitted) {
+ fontInit();
+ }
+
+ if (fp == NULL) {
+ fp = wlibSelectedFont();
+ }
+
+ if (fp == NULL) {
+ fp = standardFonts[0][FW_MEDIUM][FS_REGULAR];
+ }
+
+ fontName = pango_font_description_to_string(fp->fontDescription);
+#if WLIB_FONT_DEBUG >= 2
+ fprintf(stderr, "font translation: ");
+ fprintf(stderr, " \"%s\"\n", fontName);
+#endif
+ return (const char *) fontName;
+}
+
+/**
+ * Return description for one of the standard fonts
+ *
+ * \return
+ */
+
+wFont_p wStandardFont(int face, wBool_t bold, wBool_t italic)
+{
+ if (!fontInitted) {
+ fontInit();
+ }
+
+ return standardFonts[face-F_TIMES][bold][italic];
+}
diff --git a/app/wlib/gtklib/gtkbitmap.c b/app/wlib/gtklib/gtkbitmap.c
deleted file mode 100644
index 8f85951..0000000
--- a/app/wlib/gtklib/gtkbitmap.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkbitmap.c,v 1.5 2009-09-27 04:28:03 dspagnol Exp $
- */
-/* XTrkCad - Model Railroad CAD
- * Copyright (C) 2009 Daniel Spagnol
- *
- * 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 <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#include <unistd.h>
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-
-#include "gtkint.h"
-
-
-struct wBitmap_t {
- WOBJ_COMMON
-};
-
-/**
- * Create a static control for displaying a bitmap.
- *
- * \param parent IN parent window
- * \param x, y IN position in parent window
- * \param option IN ignored for now
- * \param iconP IN icon to use
- * \return the control
- */
-
-wControl_p
-wBitmapCreate( wWin_p parent, wPos_t x, wPos_t y, long options, wIcon_p iconP )
-{
- wBitmap_p bt;
- GdkPixbuf *pixbuf;
-
- bt = gtkAlloc( parent, B_BITMAP, x, y, NULL, sizeof *bt, NULL );
- bt->w = iconP->w;
- bt->h = iconP->h;
- bt->option = options;
-
- /*
- * Depending on the platform, parent->widget->window might still be null
- * at this point. The window allocation should be forced before creating
- * the pixmap.
- */
- if ( parent->widget->window == NULL )
- gtk_widget_realize( parent->widget ); /* force allocation, if pending */
-
- pixbuf = gdk_pixbuf_new_from_xpm_data( (const char**)iconP->bits );
- GtkWidget *image = gtk_image_new_from_pixbuf( pixbuf );
-
- gtk_widget_show( image );
-
- bt->widget = gtk_fixed_new();
- gtk_container_add( GTK_CONTAINER(bt->widget), image );
- gtk_widget_show( bt->widget );
-
- gtkComputePos( (wControl_p)bt );
- gtkControlGetSize( (wControl_p)bt );
- gtk_fixed_put( GTK_FIXED( parent->widget ), bt->widget, bt->realX, bt->realY );
-
- g_object_unref( pixbuf );
-
- return( (wControl_p)bt );
-}
-
diff --git a/app/wlib/gtklib/gtkbutton.c b/app/wlib/gtklib/gtkbutton.c
deleted file mode 100644
index 7780535..0000000
--- a/app/wlib/gtklib/gtkbutton.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/** \file gtkbutton.c
- * Toolbar button creation and handling
- *
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkbutton.c,v 1.8 2009-10-03 04:49:01 dspagnol Exp $
- */
-
-/* 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 <stdlib.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "gtkint.h"
-#include "i18n.h"
-
-#define MIN_BUTTON_WIDTH (80)
-
-/*
- *****************************************************************************
- *
- * Simple Buttons
- *
- *****************************************************************************
- */
-
-struct wButton_t {
- WOBJ_COMMON
- GtkLabel * labelG;
- GtkWidget * imageG;
- wButtonCallBack_p action;
- int busy;
- int recursion;
- };
-
-
-void wButtonSetBusy( wButton_p bb, int value ) {
- bb->recursion++;
- gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(bb->widget), value );
- bb->recursion--;
- bb->busy = value;
-}
-
-
-void gtkSetLabel(
- GtkWidget *widget,
- long option,
- const char * labelStr,
- GtkLabel * * labelG,
- GtkWidget * * imageG )
-{
- wIcon_p bm;
- GdkPixbuf *pixbuf;
-
- GdkPixmap * pixmap;
- GdkBitmap * mask;
-
- GtkWidget * hbox;
- if (widget == 0) abort();
- if (labelStr){
- if (option&BO_ICON) {
- bm = (wIcon_p)labelStr;
-
- // for XPM files use the pixbuf functions
- if( bm->gtkIconType == gtkIcon_pixmap ) {
- pixbuf = gdk_pixbuf_new_from_xpm_data( (const char**)bm->bits );
- if (*imageG==NULL) {
- *imageG = gtk_image_new_from_pixbuf( pixbuf );
- gtk_container_add( GTK_CONTAINER( widget ), *imageG );
- gtk_widget_show( *imageG );
- } else {
- gtk_image_set_from_pixbuf( GTK_IMAGE(*imageG), pixbuf );
- }
- g_object_unref( pixbuf );
- } else {
- // otherwise use the conversion to XPM
- /** \todo { Should use the way via a pixbuf as well } */
- pixmap = gtkMakeIcon( widget, bm, &mask );
- if (*imageG==NULL) {
- *imageG = gtk_image_new_from_pixmap( pixmap, NULL );
- gtk_widget_show( *imageG );
- gtk_container_add( GTK_CONTAINER( widget ), *imageG );
- } else {
- gtk_image_set_from_pixmap( GTK_IMAGE(*imageG), pixmap, NULL );
- }
- gdk_pixmap_unref( pixmap );
- gdk_bitmap_unref( mask );
- }
- } else {
- if (*labelG==NULL) {
- *labelG = (GtkLabel*)gtk_label_new( gtkConvertInput(labelStr) );
- gtk_container_add( GTK_CONTAINER(widget), (GtkWidget*)*labelG );
- gtk_widget_show( (GtkWidget*)*labelG );
- } else {
- gtk_label_set( *labelG, gtkConvertInput(labelStr) );
- }
- }
- }
-}
-
-void wButtonSetLabel( wButton_p bb, const char * labelStr) {
- gtkSetLabel( bb->widget, bb->option, labelStr, &bb->labelG, &bb->imageG );
-}
-
-
-
-void gtkButtonDoAction(
- wButton_p bb )
-{
- if (bb->action)
- bb->action( bb->data );
-}
-
-
-static void pushButt(
- GtkWidget *widget,
- gpointer value )
-{
- wButton_p b = (wButton_p)value;
- if (debugWindow >= 2) printf("%s button pushed\n", b->labelStr?b->labelStr:"No label" );
- if (b->recursion)
- return;
- if (b->action)
- b->action(b->data);
- if (!b->busy) {
- b->recursion++;
- gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(b->widget), FALSE );
- b->recursion--;
- }
-}
-
-wButton_p wButtonCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- long option,
- wPos_t width,
- wButtonCallBack_p action,
- void * data )
-{
- wButton_p b;
- b = gtkAlloc( parent, B_BUTTON, x, y, labelStr, sizeof *b, data );
- b->option = option;
- b->action = action;
- gtkComputePos( (wControl_p)b );
-
- b->widget = gtk_toggle_button_new();
-
- gtk_signal_connect (GTK_OBJECT(b->widget), "clicked",
- GTK_SIGNAL_FUNC(pushButt), b );
- if (width > 0)
- gtk_widget_set_size_request( b->widget, width, -1 );
- wButtonSetLabel( b, labelStr );
-
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
- if (option & BB_DEFAULT) {
- GTK_WIDGET_SET_FLAGS( b->widget, GTK_CAN_DEFAULT );
- gtk_widget_grab_default( b->widget );
- gtk_window_set_default( GTK_WINDOW(parent->gtkwin), b->widget );
- }
- gtkControlGetSize( (wControl_p)b );
- if (width == 0 && b->w < MIN_BUTTON_WIDTH && (b->option&BO_ICON)==0) {
- b->w = MIN_BUTTON_WIDTH;
- gtk_widget_set_size_request( b->widget, b->w, b->h );
- }
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- gtkAddHelpString( b->widget, helpStr );
- return b;
-}
-
-
-/*
- *****************************************************************************
- *
- * Choice Boxes
- *
- *****************************************************************************
- */
-
-struct wChoice_t {
- WOBJ_COMMON
- long *valueP;
- wChoiceCallBack_p action;
- int recursion;
- };
-
-
-static long choiceGetValue(
- wChoice_p bc )
-{
- GList * child, * children;
- long value, inx;
- if (bc->type == B_TOGGLE)
- value = 0;
- else
- value = -1;
- for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) {
- if ( GTK_TOGGLE_BUTTON(child->data)->active ) {
- if (bc->type == B_TOGGLE) {
- value |= (1<<inx);
- } else {
- value = inx;
- }
- }
- }
- if ( children )
- g_list_free( children );
- return value;
-}
-
-EXPORT void wRadioSetValue(
- wChoice_p bc, /* Radio box */
- long value ) /* Value */
-/*
-*/
-{
- GList * child, * children;
- long inx;
- for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) {
- if (inx == value) {
- bc->recursion++;
- gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(child->data), TRUE );
- bc->recursion--;
- }
- }
- if ( children )
- g_list_free( children );
-}
-
-
-EXPORT long wRadioGetValue(
- wChoice_p bc ) /* Radio box */
-/*
-*/
-{
- return choiceGetValue(bc);
-}
-
-
-EXPORT void wToggleSetValue(
- wChoice_p bc, /* Toggle box */
- long value ) /* Values */
-/*
-*/
-{
- GList * child, * children;
- long inx;
- bc->recursion++;
- for ( children=child=gtk_container_children(GTK_CONTAINER(bc->widget)),inx=0; child; child=child->next,inx++ ) {
- gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON(child->data), (value&(1<<inx))!=0 );
- }
- if ( children )
- g_list_free( children );
- bc->recursion--;
-}
-
-
-EXPORT long wToggleGetValue(
- wChoice_p b ) /* Toggle box */
-/*
-*/
-{
- return choiceGetValue(b);
-}
-
-
-static int pushChoice(
- GtkWidget *widget,
- gpointer b )
-{
- wChoice_p bc = (wChoice_p)b;
- long value = choiceGetValue( bc );
- if (debugWindow >= 2) printf("%s choice pushed = %ld\n", bc->labelStr?bc->labelStr:"No label", value );
- if ( bc->type == B_RADIO && !(GTK_TOGGLE_BUTTON(widget))->active )
- return 1;
- if (bc->recursion)
- return 1;
- if (bc->valueP)
- *bc->valueP = value;
- if (bc->action)
- bc->action( value, bc->data);
- return 1;
-}
-
-
-static void choiceRepaint(
- wControl_p b )
-{
- wChoice_p bc = (wChoice_p)b;
- if ( GTK_WIDGET_VISIBLE( b->widget ) )
- gtkDrawBox( bc->parent, wBoxBelow, bc->realX-1, bc->realY-1, bc->w+1, bc->h+1 );
-}
-
-
-EXPORT wChoice_p wRadioCreate(
- wWin_p parent, /* Parent window */
- wPos_t x, /* X-position */
- wPos_t y, /* Y-position */
- const char * helpStr, /* Help string */
- const char * labelStr, /* Label */
- long option, /* Options */
- const char **labels, /* Labels */
- long *valueP, /* Selected value */
- wChoiceCallBack_p action, /* Callback */
- void *data ) /* Context */
-/*
-*/
-{
- wChoice_p b;
- const char ** label;
- GtkWidget *butt0=NULL, *butt;
-
- if ((option & BC_NOBORDER)==0) {
- if (x>=0)
- x++;
- else
- x--;
- if (y>=0)
- y++;
- else
- y--;
- }
- b = gtkAlloc( parent, B_RADIO, x, y, labelStr, sizeof *b, data );
- b->option = option;
- b->action = action;
- b->valueP = valueP;
- gtkComputePos( (wControl_p)b );
-
- if (option&BC_HORZ)
- b->widget = gtk_hbox_new( FALSE, 0 );
- else
- b->widget = gtk_vbox_new( FALSE, 0 );
- if (b->widget == 0) abort();
- for ( label=labels; *label; label++ ) {
- butt = gtk_radio_button_new_with_label(
- butt0?gtk_radio_button_group(GTK_RADIO_BUTTON(butt0)):NULL, _(*label) );
- if (butt0==NULL)
- butt0 = butt;
- gtk_box_pack_start( GTK_BOX(b->widget), butt, TRUE, TRUE, 0 );
- gtk_widget_show( butt );
- gtk_signal_connect (GTK_OBJECT(butt), "toggled",
- GTK_SIGNAL_FUNC( pushChoice ), b );
- gtkAddHelpString( butt, helpStr );
- }
- if (option & BB_DEFAULT) {
- GTK_WIDGET_SET_FLAGS( b->widget, GTK_CAN_DEFAULT );
- gtk_widget_grab_default( b->widget );
- /*gtk_window_set_default( GTK_WINDOW(parent->gtkwin), b->widget );*/
- }
- if (valueP)
- wRadioSetValue( b, *valueP );
-
- if ((option & BC_NOBORDER)==0) {
- if (parent->gc == NULL) {
- parent->gc = gdk_gc_new( parent->gtkwin->window );
- gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] );
- parent->gc_linewidth = 0;
- gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- }
- b->repaintProc = choiceRepaint;
- b->w += 2;
- b->h += 2;
- }
-
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- return b;
-}
-
-wChoice_p wToggleCreate(
- wWin_p parent, /* Parent window */
- wPos_t x, /* X-position */
- wPos_t y, /* Y-position */
- const char * helpStr, /* Help string */
- const char * labelStr, /* Label */
- long option, /* Options */
- const char **labels, /* Labels */
- long *valueP, /* Selected value */
- wChoiceCallBack_p action, /* Callback */
- void *data ) /* Context */
-/*
-*/
-{
- wChoice_p b;
- const char ** label;
- GtkWidget *butt;
-
- if ((option & BC_NOBORDER)==0) {
- if (x>=0)
- x++;
- else
- x--;
- if (y>=0)
- y++;
- else
- y--;
- }
- b = gtkAlloc( parent, B_TOGGLE, x, y, labelStr, sizeof *b, data );
- b->option = option;
- b->action = action;
- gtkComputePos( (wControl_p)b );
-
- if (option&BC_HORZ)
- b->widget = gtk_hbox_new( FALSE, 0 );
- else
- b->widget = gtk_vbox_new( FALSE, 0 );
- if (b->widget == 0) abort();
- for ( label=labels; *label; label++ ) {
- butt = gtk_check_button_new_with_label(_(*label));
- gtk_box_pack_start( GTK_BOX(b->widget), butt, TRUE, TRUE, 0 );
- gtk_widget_show( butt );
- gtk_signal_connect (GTK_OBJECT(butt), "toggled",
- GTK_SIGNAL_FUNC( pushChoice ), b );
- gtkAddHelpString( butt, helpStr );
- }
- if (valueP)
- wToggleSetValue( b, *valueP );
-
- if ((option & BC_NOBORDER)==0) {
- if (parent->gc == NULL) {
- parent->gc = gdk_gc_new( parent->gtkwin->window );
- gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] );
- parent->gc_linewidth = 0;
- gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- }
- b->repaintProc = choiceRepaint;
- b->w += 2;
- b->h += 2;
- }
-
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- return b;
-}
diff --git a/app/wlib/gtklib/gtkcolor.c b/app/wlib/gtklib/gtkcolor.c
deleted file mode 100644
index cf17199..0000000
--- a/app/wlib/gtklib/gtkcolor.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/** \file gtkcolor.c
- * code for the color selection dialog and color button
- *
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkcolor.c,v 1.3 2007-11-24 19:48:21 tshead Exp $
- */
-
-/* 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 <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "gtkint.h"
-
-#include "square10.bmp"
-
-EXPORT wDrawColor wDrawColorWhite;
-EXPORT wDrawColor wDrawColorBlack;
-
-#define RGB(R,G,B) ( ((long)((R)&0xFF)<<16) | ((long)((G)&0xFF)<<8) | ((long)((B)&0xFF)) )
-
-#define MAX_COLOR_DISTANCE (3)
-
-typedef struct {
- unsigned char red;
- unsigned char green;
- unsigned char blue;
- GdkColor normalColor;
- GdkColor invertColor;
- long rgb;
- int colorChar;
- } colorMap_t;
-static GArray *colorMap_garray = NULL; // Change to use glib array
-
-static colorMap_t colorMap[] = {
- { 255, 255, 255 }, /* White */
- { 0, 0, 0 }, /* Black */
- { 255, 0, 0 }, /* Red */
- { 0, 255, 0 }, /* Green */
- { 0, 0, 255 }, /* Blue */
- { 255, 255, 0 }, /* Yellow */
- { 255, 0, 255 }, /* Purple */
- { 0, 255, 255 }, /* Aqua */
- { 128, 0, 0 }, /* Dk. Red */
- { 0, 128, 0 }, /* Dk. Green */
- { 0, 0, 128 }, /* Dk. Blue */
- { 128, 128, 0 }, /* Dk. Yellow */
- { 128, 0, 128 }, /* Dk. Purple */
- { 0, 128, 128 }, /* Dk. Aqua */
- { 65, 105, 225 }, /* Royal Blue */
- { 0, 191, 255 }, /* DeepSkyBlue */
- { 125, 206, 250 }, /* LightSkyBlue */
- { 70, 130, 180 }, /* Steel Blue */
- { 176, 224, 230 }, /* Powder Blue */
- { 127, 255, 212 }, /* Aquamarine */
- { 46, 139, 87 }, /* SeaGreen */
- { 152, 251, 152 }, /* PaleGreen */
- { 124, 252, 0 }, /* LawnGreen */
- { 50, 205, 50 }, /* LimeGreen */
- { 34, 139, 34 }, /* ForestGreen */
- { 255, 215, 0 }, /* Gold */
- { 188, 143, 143 }, /* RosyBrown */
- { 139, 69, 19 }, /* SaddleBrown */
- { 245, 245, 220 }, /* Beige */
- { 210, 180, 140 }, /* Tan */
- { 210, 105, 30 }, /* Chocolate */
- { 165, 42, 42 }, /* Brown */
- { 255, 165, 0 }, /* Orange */
- { 255, 127, 80 }, /* Coral */
- { 255, 99, 71 }, /* Tomato */
- { 255, 105, 180 }, /* HotPink */
- { 255, 192, 203 }, /* Pink */
- { 176, 48, 96 }, /* Maroon */
- { 238, 130, 238 }, /* Violet */
- { 160, 32, 240 }, /* Purple */
- { 16, 16, 16 }, /* Gray */
- { 32, 32, 32 }, /* Gray */
- { 48, 48, 48 }, /* Gray */
- { 64, 64, 64 }, /* Gray */
- { 80, 80, 80 }, /* Gray */
- { 96, 96, 96 }, /* Gray */
- { 112, 112, 122 }, /* Gray */
- { 128, 128, 128 }, /* Gray */
- { 144, 144, 144 }, /* Gray */
- { 160, 160, 160 }, /* Gray */
- { 176, 176, 176 }, /* Gray */
- { 192, 192, 192 }, /* Gray */
- { 208, 208, 208 }, /* Gray */
- { 224, 224, 224 }, /* Gray */
- { 240, 240, 240 }, /* Gray */
- { 0, 0, 0 } /* BlackPixel */
- };
-
-#define NUM_GRAYS (16)
-
-static GdkColormap * gtkColorMap;
-
-static char lastColorChar = '!';
-
-/*****************************************************************************
- *
- *
- *
- */
-
-
-EXPORT wDrawColor wDrawColorGray(
- int percent )
-{
- int n;
- long rgb;
- n = (percent * (NUM_GRAYS+1)) / 100;
- if ( n <= 0 )
- return wDrawColorBlack;
- else if ( n > NUM_GRAYS )
- return wDrawColorWhite;
- else {
- n = (n*256)/NUM_GRAYS;
- rgb = RGB( n, n, n );
- return wDrawFindColor( rgb );
- }
-}
-
-
-void gtkGetColorMap( void )
-{
- if (gtkColorMap)
- return;
- gtkColorMap = gtk_widget_get_colormap( gtkMainW->widget );
- return;
-}
-
-void init_colorMapValue( colorMap_t * t) {
-
- t->rgb = RGB( t->red, t->green, t->blue );
- t->normalColor.red = t->red*65535/255;
- t->normalColor.green = t->green*65535/255;
- t->normalColor.blue = t->blue*65535/255;
- gdk_color_alloc( gtkColorMap, &t->normalColor );
- t->invertColor = t->normalColor;
- t->invertColor.pixel ^= g_array_index(colorMap_garray, colorMap_t, wDrawColorWhite).normalColor.pixel;
- t->colorChar = lastColorChar++;
- if (lastColorChar >= 0x7F)
- lastColorChar = '!'+1;
- else if (lastColorChar == '"')
- lastColorChar++;
-
-}
-
-
-void init_colorMap( void )
-{
- colorMap_garray = g_array_sized_new(TRUE, TRUE, sizeof(colorMap_t), sizeof(colorMap)/sizeof(colorMap_t));
- g_array_append_vals(colorMap_garray, &colorMap, sizeof(colorMap)/sizeof(colorMap_t));
-
- int gint;
-
- for(gint=0; gint<colorMap_garray->len; gint++) {
- init_colorMapValue(&g_array_index(colorMap_garray, colorMap_t, gint));
- }
-}
-
-
-EXPORT wDrawColor wDrawFindColor(
- long rgb0 )
-{
- wDrawColor cc;
- int r0, g0, b0;
- int d0, d1;
- long rgb1;
- colorMap_t * cm_p;
-
- gtkGetColorMap();
-
- cc = wDrawColorBlack;
- r0 = (int)(rgb0>>16)&0xFF;
- g0 = (int)(rgb0>>8)&0xFF;
- b0 = (int)(rgb0)&0xFF;
- d0 = 256*3;
-
- // Initialize garray if needed
- if (colorMap_garray == NULL) {
- init_colorMap();
- }
-
- int gint;
-
- // Iterate over entire garray
- for (gint=0; gint<colorMap_garray->len; gint++) {
- cm_p = &g_array_index(colorMap_garray, colorMap_t, gint);
- rgb1 = cm_p->rgb;
- d1 = abs(r0-cm_p->red) + abs(g0-cm_p->green) + abs(b0-cm_p->blue);
- if (d1 == 0)
- return gint;
- if (d1 < d0) {
- d0 = d1;
- cc = gint;
- }
- }
- if (d0 <= MAX_COLOR_DISTANCE) {
- return cc;
- }
- // No good value - so add one
- colorMap_t tempMapValue;
- //DYNARR_APPEND( colorMap_t, colorMap_da, 10 );
- tempMapValue.red = r0;
- tempMapValue.green = g0;
- tempMapValue.blue = b0;
- init_colorMapValue(&tempMapValue);
- g_array_append_val(colorMap_garray,tempMapValue);
- return gint;
-}
-
-
-EXPORT long wDrawGetRGB(
- wDrawColor color )
-{
- gtkGetColorMap();
-
- if(colorMap_garray == NULL)
- init_colorMap();
-
- if (color < 0 || color > colorMap_garray->len)
- abort();
- colorMap_t * colorMap_e;
- colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color);
- return colorMap_e->rgb;
-}
-
-
-EXPORT GdkColor* gtkGetColor(
- wDrawColor color,
- wBool_t normal )
-{
- gtkGetColorMap();
-
- if(colorMap_garray == NULL)
- init_colorMap();
-
- if (color < 0 || color > colorMap_garray->len)
- abort();
- colorMap_t * colorMap_e;
- colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color);
-
- if ( normal )
- return &colorMap_e->normalColor;
- else
- return &colorMap_e->invertColor;
-}
-
-
-EXPORT int gtkGetColorChar(
- wDrawColor color )
-{
- /*gtkGetColorMap();*/
- if(colorMap_garray == NULL)
- init_colorMap();
-
- if (color < 0 || color > colorMap_garray->len)
- abort();
- colorMap_t * colorMap_e;
- colorMap_e = &g_array_index(colorMap_garray, colorMap_t, color);
- return colorMap_e->colorChar;
-}
-
-
-EXPORT int gtkMapPixel(
- long pixel )
-{
- colorMap_t * mapValue;
- int gint;
-
- if(colorMap_garray == NULL)
- init_colorMap();
-
- for (gint=0; gint<colorMap_garray->len; gint++ ) {
- mapValue = &g_array_index(colorMap_garray, colorMap_t, gint);
- if ( mapValue->normalColor.pixel == pixel ) {
- return mapValue->colorChar;
- }
- }
- mapValue = &g_array_index(colorMap_garray, colorMap_t, wDrawColorBlack);
- return mapValue->colorChar;
-}
-
-
-/*
- *****************************************************************************
- *
- * Color Selection Dialog
- *
- *****************************************************************************
- */
-
-
-static int colorSelectValid;
-static int colorSelectOk(
- GtkWidget * widget,
- GtkWidget * * window )
-{
- gtkDoModal( NULL, FALSE );
- gtk_widget_hide( GTK_WIDGET(*window) );
- colorSelectValid = TRUE;
- return FALSE;
-}
-
-
-static int colorSelectCancel(
- GtkWidget * widget,
- GtkWidget * * window )
-{
- gtkDoModal( NULL, FALSE );
- gtk_widget_hide( GTK_WIDGET(*window) );
- colorSelectValid = FALSE;
- if (widget == *window)
- /* Called by destroy event, window is gone */
- *window = NULL;
- return FALSE;
-}
-
-
-EXPORT wBool_t wColorSelect(
- const char * title,
- wDrawColor * color )
-{
- static GtkWidget * colorSelectD = NULL;
- long rgb;
- gdouble colors[4]; // Remember opacity!
-
- if (colorSelectD == NULL) {
- colorSelectD = gtk_color_selection_dialog_new( title );
- gtk_signal_connect( GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->ok_button), "clicked", (GtkSignalFunc)colorSelectOk, (gpointer)&colorSelectD );
- gtk_signal_connect( GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->cancel_button), "clicked", (GtkSignalFunc)colorSelectCancel, (gpointer)&colorSelectD );
- gtk_signal_connect( GTK_OBJECT(colorSelectD), "destroy", (GtkSignalFunc)colorSelectCancel, (gpointer)&colorSelectD );
- } else {
- gtk_window_set_title( GTK_WINDOW(colorSelectD), title );
- }
-
- colorMap_t * colorMap_e;
-
- if (!colorMap_garray) {
- init_colorMap();
- }
-
- colorMap_e = &g_array_index(colorMap_garray, colorMap_t, *color);
- colors[0] = colorMap_e->red/255.0;
- colors[1] = colorMap_e->green/255.0;
- colors[2] = colorMap_e->blue/255.0;
- colors[3] = 1.0; // Override to Fully opaque
- gtk_color_selection_set_color( GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->colorsel), colors );
- gtk_widget_show( colorSelectD );
- gtkDoModal( NULL, TRUE );
- if (colorSelectValid) {
- gtk_color_selection_get_color( GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(colorSelectD)->colorsel), colors );
- rgb = RGB( (int)(colors[0]*255), (int)(colors[1]*255), (int)(colors[2]*255) );
- * color = wDrawFindColor( rgb );
- return TRUE;
- }
- return FALSE;
-}
-
-
-/*
- *****************************************************************************
- *
- * Color Selection Button
- *
- *****************************************************************************
- */
-
-typedef struct {
- wDrawColor * valueP;
- wColorSelectButtonCallBack_p action;
- const char * labelStr;
- void * data;
- wDrawColor color;
- wButton_p button;
- } colorData_t;
-
-static void doColorButton(
- void * data )
-{
- colorData_t * cd = (colorData_t *)data;
- wDrawColor newColor;
-
- newColor = cd->color;
- if (wColorSelect( cd->labelStr, &newColor )) {
- cd->color = newColor;
- wColorSelectButtonSetColor( cd->button, newColor );
- if (cd->valueP)
- *(cd->valueP) = newColor;
- if (cd->action)
- cd->action( cd->data, newColor );
- }
-}
-
-
-void wColorSelectButtonSetColor(
- wButton_p bb,
- wDrawColor color )
-{
- wIcon_p bm;
- bm = wIconCreateBitMap( square10_width, square10_height, square10_bits, color );
- wButtonSetLabel( bb, (const char*)bm );
- ((colorData_t*)((wControl_p)bb)->data)->color = color;
-}
-
-
-wDrawColor wColorSelectButtonGetColor(
- wButton_p bb )
-{
- return ((colorData_t*)((wControl_p)bb)->data)->color;
-}
-
-/** Create the button showing the current paint color and starting the color selection dialog.
- * \param IN parent parent window
- * \param IN x x coordinate
- * \param IN Y y coordinate
- * \param IN helpStr balloon help string
- * \param IN labelStr Button label ???
- * \param IN option
- * \param IN width
- * \param IN valueP Current color ???
- * \param IN action Button callback procedure
- * \param IN data ???
- * \return bb handle for created button
- */
-
-wButton_p wColorSelectButtonCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- long option,
- wPos_t width,
- wDrawColor *valueP,
- wColorSelectButtonCallBack_p action,
- void * data )
-{
- wButton_p bb;
- wIcon_p bm;
- colorData_t * cd;
- bm = wIconCreateBitMap( square10_width, square10_height, square10_bits, (valueP?*valueP:0) );
- cd = malloc( sizeof( colorData_t ));
- cd->valueP = valueP;
- cd->action = action;
- cd->data = data;
- cd->labelStr = labelStr;
- cd->color = (valueP?*valueP:0);
- bb = wButtonCreate( parent, x, y, helpStr, (const char*)bm, option|BO_ICON, width, doColorButton, cd );
- cd->button = bb;
- if (labelStr)
- ((wControl_p)bb)->labelW = gtkAddLabel( (wControl_p)bb, labelStr );
- return bb;
-}
diff --git a/app/wlib/gtklib/gtkdraw-cairo.c b/app/wlib/gtklib/gtkdraw-cairo.c
index 9fc7eab..a19eb2b 100644
--- a/app/wlib/gtklib/gtkdraw-cairo.c
+++ b/app/wlib/gtklib/gtkdraw-cairo.c
@@ -1,5 +1,5 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkdraw-cairo.c,v 1.11 2009-10-03 17:34:37 dspagnol Exp $
+/** \file gtkdraw-cairo.c
+ * Basic drawing functions
*/
/* XTrkCad - Model Railroad CAD
@@ -29,9 +29,13 @@
#include <string.h>
#include <math.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
#include "gtkint.h"
#include "gdk/gdkkeysyms.h"
+#define gtkAddHelpString( a, b ) wlibAddHelpString( a, b )
#define CENTERMARK_LENGTH (6)
@@ -116,7 +120,7 @@ static GdkGC * selectGC(
{
if(bd->lastColor != color || !bd->lastColorInverted)
{
- gdk_gc_set_foreground( bd->gc, gtkGetColor(color,FALSE) );
+ gdk_gc_set_foreground( bd->gc, wlibGetColor(color,FALSE) );
bd->lastColor = color;
bd->lastColorInverted = TRUE;
}
@@ -127,7 +131,7 @@ static GdkGC * selectGC(
{
if(bd->lastColor != color || bd->lastColorInverted)
{
- gdk_gc_set_foreground( bd->gc, gtkGetColor(color,TRUE) );
+ gdk_gc_set_foreground( bd->gc, wlibGetColor(color,TRUE) );
bd->lastColor = color;
bd->lastColorInverted = FALSE;
}
@@ -182,7 +186,7 @@ static cairo_t* gtkDrawCreateCairoContext(
}
else
{
- GdkColor* const gcolor = gtkGetColor(color, TRUE);
+ GdkColor* const gcolor = wlibGetColor(color, TRUE);
cairo_set_source_rgb(cairo, gcolor->red / 65535.0, gcolor->green / 65535.0, gcolor->blue / 65535.0);
cairo_set_operator(cairo, CAIRO_OPERATOR_OVER);
@@ -195,7 +199,7 @@ static cairo_t* gtkDrawDestroyCairoContext(cairo_t *cairo) {
cairo_destroy(cairo);
}
-EXPORT void wDrawDelayUpdate(
+ void wDrawDelayUpdate(
wDraw_p bd,
wBool_t delay )
{
@@ -212,7 +216,7 @@ EXPORT void wDrawDelayUpdate(
}
-EXPORT void wDrawLine(
+ void wDrawLine(
wDraw_p bd,
wPos_t x0, wPos_t y0,
wPos_t x1, wPos_t y1,
@@ -275,7 +279,7 @@ EXPORT void wDrawLine(
*/
-EXPORT void wDrawArc(
+ void wDrawArc(
wDraw_p bd,
wPos_t x0, wPos_t y0,
wPos_t r,
@@ -344,7 +348,7 @@ EXPORT void wDrawArc(
}
-EXPORT void wDrawPoint(
+ void wDrawPoint(
wDraw_p bd,
wPos_t x0, wPos_t y0,
wDrawColor color,
@@ -380,7 +384,7 @@ EXPORT void wDrawPoint(
*
******************************************************************************/
-EXPORT void wDrawString(
+ void wDrawString(
wDraw_p bd,
wPos_t x, wPos_t y,
wAngle_t a,
@@ -413,19 +417,19 @@ EXPORT void wDrawString(
cairo_translate( cairo, x, y );
cairo_rotate( cairo, angle );
- layout = gtkFontCreatePangoLayout(bd->widget, cairo, fp, fs, s,
+ layout = wlibFontCreatePangoLayout(bd->widget, cairo, fp, fs, s,
(int *) &w, (int *) &h,
(int *) &ascent, (int *) &descent);
/* cairo does not support the old method of text removal by overwrite; force always write here and
refresh on cancel event */
- GdkColor* const gcolor = gtkGetColor(color, TRUE);
+ GdkColor* const gcolor = wlibGetColor(color, TRUE);
cairo_set_source_rgb(cairo, gcolor->red / 65535.0, gcolor->green / 65535.0, gcolor->blue / 65535.0);
cairo_move_to( cairo, 0, -ascent );
pango_cairo_show_layout(cairo, layout);
- gtkFontDestroyPangoLayout(layout);
+ wlibFontDestroyPangoLayout(layout);
cairo_restore( cairo );
gtkDrawDestroyCairoContext(cairo);
@@ -442,7 +446,7 @@ EXPORT void wDrawString(
gtk_widget_draw(bd->widget, &update_rect);
}
-EXPORT void wDrawGetTextSize(
+ void wDrawGetTextSize(
wPos_t *w,
wPos_t *h,
wPos_t *d,
@@ -459,8 +463,8 @@ EXPORT void wDrawGetTextSize(
*w = 0;
*h = 0;
- gtkFontDestroyPangoLayout(
- gtkFontCreatePangoLayout(bd->widget, NULL, fp, fs, s,
+ wlibFontDestroyPangoLayout(
+ wlibFontCreatePangoLayout(bd->widget, NULL, fp, fs, s,
&textWidth, (int *) &textHeight,
(int *) &ascent, (int *) &descent));
@@ -479,7 +483,7 @@ EXPORT void wDrawGetTextSize(
*
*******************************************************************************/
-EXPORT void wDrawFilledRectangle(
+ void wDrawFilledRectangle(
wDraw_p bd,
wPos_t x,
wPos_t y,
@@ -518,7 +522,7 @@ EXPORT void wDrawFilledRectangle(
gtk_widget_draw( bd->widget, &update_rect );
}
-EXPORT void wDrawFilledPolygon(
+ void wDrawFilledPolygon(
wDraw_p bd,
wPos_t p[][2],
int cnt,
@@ -584,7 +588,7 @@ EXPORT void wDrawFilledPolygon(
gtk_widget_draw( bd->widget, &update_rect );
}
-EXPORT void wDrawFilledCircle(
+ void wDrawFilledCircle(
wDraw_p bd,
wPos_t x0,
wPos_t y0,
@@ -623,7 +627,7 @@ EXPORT void wDrawFilledCircle(
}
-EXPORT void wDrawClear(
+ void wDrawClear(
wDraw_p bd )
{
GdkGC * gc;
@@ -648,7 +652,7 @@ EXPORT void wDrawClear(
gtk_widget_draw( bd->widget, &update_rect );
}
-EXPORT void * wDrawGetContext(
+ void * wDrawGetContext(
wDraw_p bd )
{
return bd->context;
@@ -661,7 +665,7 @@ EXPORT void * wDrawGetContext(
*******************************************************************************/
-EXPORT wDrawBitMap_p wDrawBitMapCreate(
+ wDrawBitMap_p wDrawBitMapCreate(
wDraw_p bd,
int w,
int h,
@@ -682,7 +686,7 @@ EXPORT wDrawBitMap_p wDrawBitMapCreate(
}
-EXPORT void wDrawBitMap(
+ void wDrawBitMap(
wDraw_p bd,
wDrawBitMap_p bm,
wPos_t x, wPos_t y,
@@ -713,7 +717,7 @@ EXPORT void wDrawBitMap(
} else if ( (opts&wDrawOptNoClip) != 0 ) {
xx += bd->realX;
yy += bd->realY;
- b = gtkGetControlFromPos( bd->parent, xx, yy );
+ b = wlibGetControlFromPos( bd->parent, xx, yy );
if ( b ) {
if ( b->type == B_DRAW )
gdk_window = ((wDraw_p)b)->pixmap;
@@ -762,7 +766,7 @@ EXPORT void wDrawBitMap(
-EXPORT void wDrawSaveImage(
+ void wDrawSaveImage(
wDraw_p bd )
{
if ( bd->pixmapBackup ) {
@@ -781,7 +785,7 @@ EXPORT void wDrawSaveImage(
}
-EXPORT void wDrawRestoreImage(
+ void wDrawRestoreImage(
wDraw_p bd )
{
GdkRectangle update_rect;
@@ -806,7 +810,7 @@ EXPORT void wDrawRestoreImage(
}
-EXPORT void wDrawSetSize(
+ void wDrawSetSize(
wDraw_p bd,
wPos_t w,
wPos_t h )
@@ -838,13 +842,13 @@ EXPORT void wDrawSetSize(
}
-EXPORT void wDrawGetSize(
+ void wDrawGetSize(
wDraw_p bd,
wPos_t *w,
wPos_t *h )
{
if (bd->widget)
- gtkControlGetSize( (wControl_p)bd );
+ wlibControlGetSize( (wControl_p)bd );
*w = bd->w-2;
*h = bd->h-2;
}
@@ -856,7 +860,7 @@ EXPORT void wDrawGetSize(
* \return the resolution in dpi
*/
-EXPORT double wDrawGetDPI(
+ double wDrawGetDPI(
wDraw_p d )
{
//if (d == &psPrint_d)
@@ -866,7 +870,7 @@ EXPORT double wDrawGetDPI(
}
-EXPORT double wDrawGetMaxRadius(
+ double wDrawGetMaxRadius(
wDraw_p d )
{
if (d == &psPrint_d)
@@ -876,7 +880,7 @@ EXPORT double wDrawGetMaxRadius(
}
-EXPORT void wDrawClip(
+ void wDrawClip(
wDraw_p d,
wPos_t x,
wPos_t y,
@@ -956,7 +960,7 @@ static gint draw_leave_event(
GtkWidget *widget,
GdkEvent * event )
{
- gtkHelpHideBalloon();
+ wlibHelpHideBalloon();
return FALSE;
}
@@ -1041,38 +1045,38 @@ static gint draw_char_event(
guint key = event->keyval;
wAccelKey_e extKey = wAccelKey_None;
switch (key) {
- case GDK_Escape: key = 0x1B; break;
- case GDK_Return: key = 0x0D; break;
- case GDK_Linefeed: key = 0x0A; break;
- case GDK_Tab: key = 0x09; break;
- case GDK_BackSpace: key = 0x08; break;
- case GDK_Delete: extKey = wAccelKey_Del; break;
- case GDK_Insert: extKey = wAccelKey_Ins; break;
- case GDK_Home: extKey = wAccelKey_Home; break;
- case GDK_End: extKey = wAccelKey_End; break;
- case GDK_Page_Up: extKey = wAccelKey_Pgup; break;
- case GDK_Page_Down: extKey = wAccelKey_Pgdn; break;
- case GDK_Up: extKey = wAccelKey_Up; break;
- case GDK_Down: extKey = wAccelKey_Down; break;
- case GDK_Right: extKey = wAccelKey_Right; break;
- case GDK_Left: extKey = wAccelKey_Left; break;
- case GDK_F1: extKey = wAccelKey_F1; break;
- case GDK_F2: extKey = wAccelKey_F2; break;
- case GDK_F3: extKey = wAccelKey_F3; break;
- case GDK_F4: extKey = wAccelKey_F4; break;
- case GDK_F5: extKey = wAccelKey_F5; break;
- case GDK_F6: extKey = wAccelKey_F6; break;
- case GDK_F7: extKey = wAccelKey_F7; break;
- case GDK_F8: extKey = wAccelKey_F8; break;
- case GDK_F9: extKey = wAccelKey_F9; break;
- case GDK_F10: extKey = wAccelKey_F10; break;
- case GDK_F11: extKey = wAccelKey_F11; break;
- case GDK_F12: extKey = wAccelKey_F12; break;
+ case GDK_KEY_Escape: key = 0x1B; break;
+ case GDK_KEY_Return: key = 0x0D; break;
+ case GDK_KEY_Linefeed: key = 0x0A; break;
+ case GDK_KEY_Tab: key = 0x09; break;
+ case GDK_KEY_BackSpace: key = 0x08; break;
+ case GDK_KEY_Delete: extKey = wAccelKey_Del; break;
+ case GDK_KEY_Insert: extKey = wAccelKey_Ins; break;
+ case GDK_KEY_Home: extKey = wAccelKey_Home; break;
+ case GDK_KEY_End: extKey = wAccelKey_End; break;
+ case GDK_KEY_Page_Up: extKey = wAccelKey_Pgup; break;
+ case GDK_KEY_Page_Down: extKey = wAccelKey_Pgdn; break;
+ case GDK_KEY_Up: extKey = wAccelKey_Up; break;
+ case GDK_KEY_Down: extKey = wAccelKey_Down; break;
+ case GDK_KEY_Right: extKey = wAccelKey_Right; break;
+ case GDK_KEY_Left: extKey = wAccelKey_Left; break;
+ case GDK_KEY_F1: extKey = wAccelKey_F1; break;
+ case GDK_KEY_F2: extKey = wAccelKey_F2; break;
+ case GDK_KEY_F3: extKey = wAccelKey_F3; break;
+ case GDK_KEY_F4: extKey = wAccelKey_F4; break;
+ case GDK_KEY_F5: extKey = wAccelKey_F5; break;
+ case GDK_KEY_F6: extKey = wAccelKey_F6; break;
+ case GDK_KEY_F7: extKey = wAccelKey_F7; break;
+ case GDK_KEY_F8: extKey = wAccelKey_F8; break;
+ case GDK_KEY_F9: extKey = wAccelKey_F9; break;
+ case GDK_KEY_F10: extKey = wAccelKey_F10; break;
+ case GDK_KEY_F11: extKey = wAccelKey_F11; break;
+ case GDK_KEY_F12: extKey = wAccelKey_F12; break;
default: ;
}
if (extKey != wAccelKey_None) {
- if ( gtkFindAccelKey( event ) == NULL ) {
+ if ( wlibFindAccelKey( event ) == NULL ) {
bd->action( bd, bd->context, wActionExtKey + ((int)extKey<<8), bd->lastX, bd->lastY );
}
return TRUE;
@@ -1097,7 +1101,7 @@ int XW = 0;
int XH = 0;
int xw, xh, cw, ch;
-EXPORT wDraw_p wDrawCreate(
+ wDraw_p wDrawCreate(
wWin_p parent,
wPos_t x,
wPos_t y,
@@ -1111,12 +1115,12 @@ EXPORT wDraw_p wDrawCreate(
{
wDraw_p bd;
- bd = (wDraw_p)gtkAlloc( parent, B_DRAW, x, y, NULL, sizeof *bd, NULL );
+ bd = (wDraw_p)wlibAlloc( parent, B_DRAW, x, y, NULL, sizeof *bd, NULL );
bd->option = option;
bd->context = context;
bd->redraw = redraw;
bd->action = action;
- gtkComputePos( (wControl_p)bd );
+ wlibComputePos( (wControl_p)bd );
bd->widget = gtk_drawing_area_new();
gtk_drawing_area_size( GTK_DRAWING_AREA(bd->widget), width, height );
@@ -1153,7 +1157,7 @@ EXPORT wDraw_p wDrawCreate(
bd->maxH = bd->h = height;
gtk_fixed_put( GTK_FIXED(parent->widget), bd->widget, bd->realX, bd->realY );
- gtkControlGetSize( (wControl_p)bd );
+ wlibControlGetSize( (wControl_p)bd );
gtk_widget_realize( bd->widget );
bd->pixmap = gdk_pixmap_new( bd->widget->window, width, height, -1 );
bd->gc = gdk_gc_new( parent->gtkwin->window );
@@ -1169,7 +1173,7 @@ EXPORT wDraw_p wDrawCreate(
bd->labelW = gtkAddLabel( (wControl_p)bd, labelStr );
#endif
gtk_widget_show( bd->widget );
- gtkAddButton( (wControl_p)bd );
+ wlibAddButton( (wControl_p)bd );
gtkAddHelpString( bd->widget, helpStr );
return bd;
@@ -1185,7 +1189,7 @@ wDraw_p wBitMapCreate( wPos_t w, wPos_t h, int arg )
{
wDraw_p bd;
- bd = (wDraw_p)gtkAlloc( gtkMainW, B_DRAW, 0, 0, NULL, sizeof *bd, NULL );
+ bd = (wDraw_p)wlibAlloc( gtkMainW, B_DRAW, 0, 0, NULL, sizeof *bd, NULL );
bd->lastColor = -1;
bd->dpi = 75;
diff --git a/app/wlib/gtklib/gtkfont.c b/app/wlib/gtklib/gtkfont.c
deleted file mode 100644
index 89937d7..0000000
--- a/app/wlib/gtklib/gtkfont.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/** \file gtkfont.c
- * Font selection and loading.
- */
-
-/* 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 <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#include <unistd.h>
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-
-#include "wlib.h"
-#include "gtkint.h"
-#include "i18n.h"
-
-#ifndef TRUE
-#define TRUE (1)
-#define FALSE (0)
-#endif
-
-/*
- * Macro for debug purposes. Possible debug macro values:
- *
- * 0 - no messages to console (use this value when building in release mode)
- * 1 - send errors
- * 2 - send details
- * 3 - send more details
- */
-#define WLIB_FONT_DEBUG 0
-
-static gchar sampleText[] = "AbCdE0129!@$&()[]{}";
-
-static GtkWidget *fontSelectionDialog;
-
-
-/*****************************************************************************
- * FONT HANDLERS
- */
-
-#define FW_MEDIUM (0)
-#define FW_BOLD (1)
-#define FS_REGULAR (0)
-#define FS_ITALIC (1)
-
-/* absoluteFontSize was introduced to keep the font size information synchron
- * between the Dt.size of ctext.c and it's drop list on the status bar and
- * the font size coming from the gtk font dialog which is located in this file */
-int absoluteFontSize = 18;
-
-struct wFont_t {
- PangoFontDescription *fontDescription;
- };
-
-static wFont_p standardFonts[F_HELV-F_TIMES+1][2][2];
-static wFont_p curFont = NULL;
-
-
-static void fontSelectionDialogCallback(GtkFontSelectionDialog *fontSelectionDialog, gint response, gpointer data)
-{
- gchar *fontName;
-
- switch (response)
- {
- case GTK_RESPONSE_APPLY: /* once the apply button is hidden, this should not be used */
- case GTK_RESPONSE_OK:
- fontName = gtk_font_selection_dialog_get_font_name(fontSelectionDialog);
- wPrefSetString( "font", "name", fontName );
- pango_font_description_free(curFont->fontDescription);
- curFont->fontDescription = pango_font_description_from_string(fontName);
- absoluteFontSize = (pango_font_description_get_size(curFont->fontDescription))/PANGO_SCALE;
-#if WLIB_FONT_DEBUG >= 2
- fprintf(stderr, "new font selection:\n");
- fprintf(stderr, " font name \"%s\"\n", fontName);
- fprintf(stderr, " font size is %d\n",pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE);
- fprintf(stderr, " font size is absolute %d\n", pango_font_description_get_size_is_absolute(curFont->fontDescription));
-#endif
- g_free(fontName);
- break;
- default:
- gtk_widget_hide(GTK_WIDGET(fontSelectionDialog));
- }
- if (response == GTK_RESPONSE_OK)
- gtk_widget_hide(GTK_WIDGET(fontSelectionDialog));
-}
-
-static wBool_t fontInitted = FALSE;
-
-static wBool_t fontInit()
-{
- const char *fontNames[] = {
- "times 18",
- "times italic 18",
- "times bold 18",
- "times bold italic 18",
- "helvetica 18",
- "helvetica oblique 18",
- "helvetica bold 18",
- "helvetica bold oblique 18",
- };
-
- int s = 0;
- int i, j, k;
-
- for (i = F_TIMES; i <= F_HELV; ++i) {
- for (j = FW_MEDIUM; j <= FW_BOLD; ++j) {
- for (k = FS_REGULAR; k <= FS_ITALIC; ++k) {
- PangoFontDescription *fontDescription = pango_font_description_from_string(fontNames[s++]);
- wFont_p standardFont = (wFont_p) malloc(sizeof(struct wFont_t));
- standardFont->fontDescription = fontDescription;
- standardFonts[i-F_TIMES][j][k] = standardFont;
- }
- }
- }
-
- if (curFont == NULL) {
- curFont = (wFont_p) malloc(sizeof(struct wFont_t));
- if (curFont == NULL)
- return FALSE;
- const char *fontName = wPrefGetString("font", "name");
- curFont->fontDescription = pango_font_description_from_string(fontName ? fontName : "helvetica 18");
- absoluteFontSize = (int) PANGO_PIXELS(pango_font_description_get_size(curFont->fontDescription));
- }
-
- fontInitted = TRUE;
- return TRUE;
-}
-
-
-static double fontFactor = 1.0;
-
-#define FONTSIZE_TO_PANGOSIZE(fs) ((gint) ((fs) * (fontFactor) + .5))
-
-/**
- * Create a Pango layout with a specified font and font size
- *
- * \param widget IN
- * \param cairo IN cairo context
- * \param fp IN font
- * \param fs IN size
- * \param s IN ???
- * \param width_p OUT width of layout
- * \param height_p OUT height of layout
- * \param ascent_p OUT ascent of layout
- * \param descent_p OUT descent of layout
- * \return the created Pango layout
- */
-
-PangoLayout *gtkFontCreatePangoLayout(GtkWidget *widget,
- void *cairo,
- wFont_p fp,
- wFontSize_t fs,
- const char *s,
- int *width_p,
- int *height_p,
- int *ascent_p,
- int *descent_p)
-{
- if (!fontInitted)
- fontInit();
-
- PangoLayout *layout = NULL;
-
- gchar *utf8 = gtkConvertInput(s);
-
-/* RPH -- pango_cairo_create_layout() is missing in CentOS 4.8.
- CentOS 4.8 only has GTK 2.4.13 and Pango 1.6.0 and does not have
- libpangocairo at all.
- pango_cairo_create_layout() was introduced with Pango 1.10. */
-
-#if PANGO_VERSION_MAJOR >= 1 && PANGO_VERSION_MINOR >= 10
- if (cairo != NULL) {
- layout = pango_cairo_create_layout((cairo_t *) cairo);
- pango_layout_set_text(layout, utf8, -1);
- }
- else
-#endif
- layout = gtk_widget_create_pango_layout(widget, utf8);
-
- PangoFontDescription *fontDescription = (fp ? fp : curFont)->fontDescription;
-
- PangoContext *context;
- PangoFontMetrics *metrics;
-
- /* set attributes */
- pango_font_description_set_size(fontDescription,
- FONTSIZE_TO_PANGOSIZE(fs) * PANGO_SCALE);
- pango_layout_set_font_description(layout, fontDescription);
-
- /* get layout measures */
- pango_layout_get_pixel_size(layout, width_p, height_p);
- context = gtk_widget_get_pango_context(widget);
- metrics = pango_context_get_metrics(context, fontDescription,
- pango_context_get_language(context));
- *ascent_p = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics));
- *descent_p = PANGO_PIXELS(pango_font_metrics_get_descent(metrics));
- pango_font_metrics_unref(metrics);
-
-#if WLIB_FONT_DEBUG >= 3
- fprintf(stderr, "font layout created:\n");
- fprintf(stderr, " widget: %p\n", widget);
- //fprintf(stderr, " font description:%p\n", fp);
- fprintf(stderr, " font size: %f\n", fs);
- fprintf(stderr, " layout text: \"%s\" (utf8)\n", utf8);
- fprintf(stderr, " layout width: %d\n", *width_p);
- fprintf(stderr, " layout height: %d\n", *height_p);
- fprintf(stderr, " layout ascent: %d (pixels)\n", *ascent_p);
- fprintf(stderr, " layout descent: %d (pixels)\n", *descent_p);
-#endif
-
- return layout;
-}
-
-void gtkFontDestroyPangoLayout(PangoLayout *layout)
-{
- g_object_unref(G_OBJECT(layout));
-}
-
-void wInitializeFonts()
-{
- if (!fontInitted)
- fontInit();
-}
-
-void wSelectFont(
- const char * title )
-{
- if (!fontInitted)
- fontInit();
-
- if (fontSelectionDialog == NULL) {
- fontSelectionDialog = gtk_font_selection_dialog_new(_("Font Select"));
- gtk_window_set_position(GTK_WINDOW(fontSelectionDialog), GTK_WIN_POS_MOUSE);
- gtk_window_set_modal(GTK_WINDOW(fontSelectionDialog), TRUE);
- gtk_font_selection_dialog_set_preview_text(GTK_FONT_SELECTION_DIALOG(fontSelectionDialog), sampleText);
- g_signal_connect(G_OBJECT(fontSelectionDialog), "response", G_CALLBACK(fontSelectionDialogCallback), NULL);
- gtk_signal_connect(GTK_OBJECT(fontSelectionDialog), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &fontSelectionDialog);
- }
- gtk_window_set_title(GTK_WINDOW(fontSelectionDialog), title);
-
- if (curFont != NULL) {
- /* the curFont description contains the latest font info
- * which is depended on the current scale
- * overwrite it with the absoluteFontSize */
- pango_font_description_set_size(curFont->fontDescription,FONTSIZE_TO_PANGOSIZE(absoluteFontSize) * PANGO_SCALE);
- gchar *fontName = pango_font_description_to_string(curFont->fontDescription);
- gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(fontSelectionDialog), fontName);
- g_free(fontName);
- }
-
- gtk_widget_show(fontSelectionDialog);
-}
-
-static wFont_p gtkSelectedFont( void )
-{
- if (!fontInitted)
- fontInit();
-
- return curFont;
-}
-
-wFontSize_t wSelectedFontSize( void )
-{
- if (!fontInitted)
- fontInit();
-
-#if WLIB_FONT_DEBUG >= 3
- fprintf(stderr, "the font size of current font description is: %d\n",pango_font_description_get_size(curFont->fontDescription)/PANGO_SCALE);
- fprintf(stderr, "the font size of absoluteFontSize is: %d\n",absoluteFontSize);
-#endif
-
- //return (wFontSize_t) PANGO_PIXELS(pango_font_description_get_size(curFont->fontDescription));
- return absoluteFontSize;
-}
-
-void wSetSelectedFontSize(int size){
- absoluteFontSize = (wFontSize_t)size;
-}
-
-/**
- * get the Pango font description as a string from a font definition.
- * If the font definition is NULL, a default font is return. This is
- * the current font if one is set. If not the first font from the font
- * list is returned.
- *
- * \param fp IN the font definition
- * \return the font description
- */
-
-const char *gtkFontTranslate( wFont_p fp )
-{
- static gchar *fontName = NULL;
-
- if (fontName != NULL)
- g_free(fontName);
-
- if (!fontInitted)
- fontInit();
-
- if (fp == NULL)
- fp = gtkSelectedFont();
-
- if (fp == NULL)
- fp = standardFonts[0][FW_MEDIUM][FS_REGULAR];
-
- fontName = pango_font_description_to_string(fp->fontDescription);
-
-#if WLIB_FONT_DEBUG >= 2
- fprintf(stderr, "font translation: ");
- fprintf(stderr, " \"%s\"\n", fontName);
-#endif
-
- return (const char *) fontName;
-}
-
-wFont_p wStandardFont( int face, wBool_t bold, wBool_t italic )
-{
- if (!fontInitted)
- fontInit();
-
- return standardFonts[face-F_TIMES][bold][italic];
-}
diff --git a/app/wlib/gtklib/gtkhelp.c b/app/wlib/gtklib/gtkhelp.c
deleted file mode 100644
index b02f555..0000000
--- a/app/wlib/gtklib/gtkhelp.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/** \file gtkhelp.c
- * Balloon help ( tooltips) and main help functions.
- *
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkhelp.c,v 1.12 2009-10-02 04:30:32 dspagnol Exp $
- */
-
-/* XTrkCad - Model Railroad CAD
- * Copyright (C) 2005 Dave Bullis and (C) 2007 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 <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>
-
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include <webkit/webkit.h>
-
-#include "gtkint.h"
-#include "i18n.h"
-
-void load_into_view (char *file, int requested_view); // Prototype to please clang.
-
-/* globals and defines related to the HTML help window */
-
-#define HTMLERRORTEXT "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=US-ASCII\">" \
- "<title>Help Error</title><body><h1>Error - help information can not be found.</h1><p>" \
- "The help information you requested cannot be found on this system.<br><pre>%s: %s</pre><p>" \
- "Usually this is an installation problem, Make sure that XTrackCAD and the included " \
- "HTML files are installed properly and can be found via the XTRKCADLIB environment " \
- "variable. Also make sure that the user has sufficient access rights to read these" \
- "files.</p></body></html>"
-
-
-#define SLIDERPOSDEFAULT 180 /**< default value for slider position */
-
-#define HTMLHELPSECTION "gtklib html help" /**< section name for html help window preferences */
-#define SLIDERPREFNAME "sliderpos" /**< name for the slider position preference */
-#define WINDOWPOSPREFNAME "position" /**< name for the window position preference */
-#define WINDOWSIZEPREFNAME "size" /**< name for the window size preference */
-
-#define BACKBUTTON "back"
-#define FORWARDBUTTON "forward"
-#define HOMEBUTTON "home"
-#define CONTENTBUTTON "contents"
-#define TOCDOC "tocDoc"
-#define CONTENTSDOC "contentsDoc"
-#define TOCVIEW "viewLeft"
-#define CONTENTSVIEW "viewRight"
-#define PANED "hpane"
-
-enum pane_views { MAIN_VIEW, CONTENTS_VIEW };
-
-#define MAXHISTORYSIZE 20
-
-/** \struct htmlHistory
- * for storing information about the browse history
- */
-struct htmlHistory {
- int curShownPage; /**< index of page that is shown currently */
- int newestPage; /**< index of newest page loaded */
- int oldestPage; /**< index of earliest page loaded */
- int bInUse; /**< does buffer have at least one entry */
- char *url[ MAXHISTORYSIZE ]; /**< array of pages in history */
-};
-
-static struct htmlHistory sHtmlHistory;
-
-#define INCBUFFERINDEX( x ) (((x) + 1 ) % MAXHISTORYSIZE )
-#define DECBUFFERINDEX( x ) ((x) == 0 ? MAXHISTORYSIZE - 1 : (x)-1)
-
-static char *directory; /**< base directory for HTML files */
-
-static GtkWidget *wHelpWindow; /**< handle for the help window */
-static GtkWidget *main_view; /** handle for the help main data pane */
-static GtkWidget *contents_view; /** handle for the help contents pane */
-
-#define GLADE_HOOKUP_OBJECT(component,widget,name) \
- g_object_set_data_full (G_OBJECT (component), name, \
- gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
-
-#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
- g_object_set_data (G_OBJECT (component), name, widget)
-
-static GtkWidget*
-lookup_widget(GtkWidget *widget, const gchar *widget_name)
-{
- GtkWidget *parent, *found_widget;
-
- for (;;)
- {
- if (GTK_IS_MENU (widget))
- parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
- else
- parent = widget->parent;
- if (!parent)
- parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey");
- if (parent == NULL)
- break;
- widget = parent;
- }
-
- found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
- widget_name);
- if (!found_widget)
- g_warning ("Widget not found: %s", widget_name);
- return found_widget;
-}
-
-
-
-/*
- ******************************************************************************
- *
- * Help
- *
- ******************************************************************************
- */
-
-wBool_t listHelpStrings = FALSE;
-wBool_t listMissingHelpStrings = FALSE;
-static char HelpDataKey[] = "HelpDataKey";
-
-static GtkWidget * balloonF;
-static GtkWidget * balloonPI;
-static wBalloonHelp_t * balloonHelpStrings;
-static int enableBalloonHelp = 1;
-static const char * balloonMsg;
-static wControl_p balloonB;
-static wPos_t balloonDx, balloonDy;
-static wBool_t balloonVisible = FALSE;
-static wControl_p balloonHelpB;
-static GtkTooltips * tooltips;
-
-
-void wSetBalloonHelp( wBalloonHelp_t * bh )
-{
- balloonHelpStrings = bh;
- if (!tooltips)
- tooltips = gtk_tooltips_new();
-}
-
-void wEnableBalloonHelp( int enable )
-{
- enableBalloonHelp = enable;
- if (tooltips) {
- if (enable)
- gtk_tooltips_enable( tooltips );
- else
- gtk_tooltips_disable( tooltips );
- }
-}
-
-
-void wControlSetBalloon( wControl_p b, wPos_t dx, wPos_t dy, const char * msg )
-{
- PangoLayout * layout;
- wPos_t x, y;
- wPos_t w, h;
- wPos_t xx, yy;
- const char * msgConverted;
- if (balloonVisible && balloonB == b &&
- balloonDx == dx && balloonDy == dy && balloonMsg == msg )
- return;
-
- if ( msg == NULL ) {
- if ( balloonF != NULL ) {
- gtk_widget_hide( balloonF );
- balloonVisible = FALSE;
- }
- balloonMsg = "";
- return;
- }
- msgConverted = gtkConvertInput(msg);
- if ( balloonF == NULL ) {
- balloonF = gtk_window_new( GTK_WINDOW_POPUP );
- gtk_window_set_policy( GTK_WINDOW (balloonF), FALSE, FALSE, TRUE );
- gtk_widget_realize( balloonF );
- balloonPI = gtk_label_new(msgConverted);
- gtk_container_add( GTK_CONTAINER(balloonF), balloonPI );
- gtk_container_border_width( GTK_CONTAINER(balloonF), 1 );
- gtk_widget_show( balloonPI );
- } else {
- gtk_label_set( GTK_LABEL(balloonPI), msgConverted );
- }
- balloonDx = dx;
- balloonDy = dy;
- balloonB = b;
- balloonMsg = msg;
- gtk_widget_hide( balloonF );
- layout = gtk_widget_create_pango_layout( balloonPI, msgConverted );
- pango_layout_get_pixel_size( layout, &w, &h );
- g_object_unref(G_OBJECT(layout));
- h = 16;
- gdk_window_get_position( GTK_WIDGET(b->parent->gtkwin)->window, &x, &y );
- gdk_window_get_origin( GTK_WIDGET(b->parent->gtkwin)->window, &x, &y );
- x += b->realX + dx;
- y += b->realY + b->h - dy;
- xx = gdk_screen_width();
- yy = gdk_screen_height();
- if ( x < 0 ) {
- x = 0;
- } else if ( x+w > xx ) {
- x = xx - w;
- }
- if ( y < 0 ) {
- y = 0;
- } else if ( y+h > yy ) {
- y = yy - h ;
- }
- gtk_widget_set_usize( balloonPI, w, h );
- gtk_widget_set_usize( balloonF, w+2, h+2 );
- gtk_widget_show( balloonF );
- gtk_widget_set_uposition( balloonF, x, y );
- /*gtk_widget_popup( balloonF, x, y );*/
- gdk_draw_rectangle( balloonF->window, balloonF->style->fg_gc[GTK_STATE_NORMAL], FALSE, 0, 0, w+1, h+1 );
- gtk_widget_queue_resize( GTK_WIDGET(balloonF) );
- /*gtk_widget_set_uposition( balloonF, x, y );*/
- balloonVisible = TRUE;
-}
-
-
-void wControlSetBalloonText(
- wControl_p b,
- const char * label )
-{
- const char * helpStr;
- if ( b->widget == NULL) abort();
- helpStr = (char*)gtk_object_get_data( GTK_OBJECT(b->widget), HelpDataKey );
- if ( helpStr == NULL ) helpStr = "NoHelp";
- if (tooltips)
- gtk_tooltips_set_tip( tooltips, b->widget, label, helpStr );
-}
-
-
-EXPORT void gtkHelpHideBalloon( void )
-{
- if (balloonF != NULL && balloonVisible) {
- gtk_widget_hide( balloonF );
- balloonVisible = FALSE;
- }
-}
-
-#ifdef XV_help
-static Notify_value showBalloonHelp( Notify_client client, int which )
-{
- wControlSetBalloon( balloonHelpB, 0, 0, balloonHelpString );
- return NOTIFY_DONE;
-}
-#endif
-
-static wWin_p balloonHelp_w;
-static wPos_t balloonHelp_x;
-static wPos_t balloonHelp_y;
-static void prepareBalloonHelp( wWin_p w, wPos_t x, wPos_t y )
-{
-#ifdef XV
- wControl_p b;
- char * hs;
- int appNameLen = strlen( wAppName ) + 1;
- if (w == NULL)
- return;
-#ifdef LATER
- if (!enableBalloonHelp)
- return;
-#endif
- if (!balloonHelpStrings)
- return;
-
- balloonHelp_w = w;
- balloonHelp_x = x;
- balloonHelp_y = y;
-
- for ( b=w->first; b; b=b->next ) {
- switch ( b->type ) {
- case B_BUTTON:
- case B_CANCEL:
- case B_TEXT:
- case B_INTEGER:
- case B_LIST:
- case B_DROPLIST:
- case B_COMBOLIST:
- case B_RADIO:
- case B_TOGGLE:
- case B_DRAW:
- case B_MULTITEXT:
- if (x >= b->realX && x < b->realX+b->w &&
- y >= b->realY && y < b->realY+b->h ) {
- hs = (char*)gtk_get( b->panel_item, XV_HELP_DATA );
- if ( hs ) {
- hs += appNameLen;
- for ( currBalloonHelp = balloonHelpStrings; currBalloonHelp->name && strcmp(currBalloonHelp->name,hs) != 0; currBalloonHelp++ );
- if (currBalloonHelp->name && balloonHelpB != b && currBalloonHelp->value ) {
- balloonHelpB = b;
- balloonHelpString = currBalloonHelp->value;
- if (enableBalloonHelp) {
- wControlSetBalloon( balloonHelpB, 0, 0, balloonHelpString );
- /*setTimer( balloonHelpTimeOut, showBalloonHelp );*/
- } else {
- /*resetBalloonHelp();*/
- }
- }
- return;
- }
- }
- default:
- ;
- }
- }
- cancelTimer( showBalloonHelp );
- resetBalloonHelp();
-#endif
-}
-
-
-void wBalloonHelpUpdate( void )
-{
- balloonHelpB = NULL;
- balloonMsg = NULL;
- prepareBalloonHelp( balloonHelp_w, balloonHelp_x, balloonHelp_y );
-}
-
-
-void gtkAddHelpString(
- GtkWidget * widget,
- const char * helpStr )
-{
- int rc;
- char *string;
- wBalloonHelp_t * bhp;
- rc = 0;
- if (helpStr==NULL || *helpStr==0)
- return;
- if ( balloonHelpStrings == NULL )
- return;
- for ( bhp = balloonHelpStrings; bhp->name && strcmp(bhp->name,helpStr) != 0; bhp++ );
- if (listMissingHelpStrings && !bhp->name) {
- printf( "Missing Help String: %s\n", helpStr );
- return;
- }
- string = malloc( strlen(wAppName) + 5 + strlen(helpStr) + 1 );
- sprintf( string, "%sHelp/%s", wAppName, helpStr );
- if (tooltips)
- gtk_tooltips_set_tip( tooltips, widget, _(bhp->value), string );
- gtk_object_set_data( GTK_OBJECT( widget ), HelpDataKey, string );
- if (listHelpStrings)
- printf( "HELPSTR - %s\n", string );
-}
-
-
-EXPORT const char * wControlGetHelp(
- wControl_p b ) /* Control */
-/*
-Returns the help topic string associated with <b>.
-*/
-{
- const char * helpStr;
- helpStr = (char*)gtk_object_get_data( GTK_OBJECT(b->widget), HelpDataKey );
- return helpStr;
-}
-
-
-EXPORT void wControlSetHelp(
- wControl_p b, /* Control */
- const char * help ) /* topic string */
-/*
-Set the help topic string for <b> to <help>.
-*/
-{
- const char * helpStr;
- if (b->widget == 0) abort();
- helpStr = wControlGetHelp(b);
- if (tooltips)
- gtk_tooltips_set_tip( tooltips, b->widget, help, helpStr );
-}
-
-
-/**
- * create a new horizontal pane and place it into container.
- * The separator position is read from the resource configuration and set accordingly.
- * Also a callback is specified that will be executed when the slider has been moved.
- *
- * \PARAM container IN the container into which the pane will be stuffed.
- * \PARAM property IN the name of the property for the slider position
- *
- * \return the HPaned handle
- */
-
-GtkWidget *
-CreateHPaned( GtkBox *container, char *property )
-{
- GtkWidget *hpaned;
- long posSlider;
-
- /* the horizontal slider */
- hpaned = gtk_hpaned_new ();
- gtk_container_set_border_width (GTK_CONTAINER (hpaned), 6);
-
- wPrefGetInteger( HTMLHELPSECTION, SLIDERPREFNAME, &posSlider, SLIDERPOSDEFAULT );
- gtk_paned_set_position (GTK_PANED (hpaned), (int)posSlider);
-
- /* pack the horizontal slider into the main window */
- gtk_box_pack_start( container, hpaned, TRUE, TRUE, 0 );
- gtk_widget_show( hpaned );
-
- return( hpaned );
-}
-
-/**
- * Handler for the delete-event issued on the help window.We are saving window
- * information (eg. position) and are hiding the window instead of closing it.
- *
- * \PARAM win IN the window to be destroyed
- * \PARAM event IN unused
- * \PARAM ptr IN unused
- *
- * \RETURN FALSE
- */
-
-static gboolean
-DestroyHelpWindow( GtkWidget *win, GdkEvent *event, void *ptr )
-{
- int i;
- GtkWidget *widget;
- char tmp[ 20 ];
-
- gint x, y;
-
- /* get the slider position and save it */
- widget = lookup_widget( win, PANED );
- i = gtk_paned_get_position( GTK_PANED( widget ));
- wPrefSetInteger( HTMLHELPSECTION, SLIDERPREFNAME, i );
-
- /* get the window position */
- gtk_window_get_position( (GtkWindow *)win, &x, &y );
- sprintf( tmp, "%d %d", x, y );
- wPrefSetString( HTMLHELPSECTION, WINDOWPOSPREFNAME, tmp );
-
- /* get the window size */
- gtk_window_get_size( (GtkWindow *)win , &x, &y );
- sprintf( tmp, "%d %d", x, y );
- wPrefSetString( HTMLHELPSECTION, WINDOWSIZEPREFNAME, tmp );
-
- gtk_widget_hide( win );
- return TRUE;
-}
-
-void back_button_clicked(GtkWidget *widget, gpointer data) {
- webkit_web_view_go_back(WEBKIT_WEB_VIEW(data));
-}
-
-void forward_button_clicked(GtkWidget *widget, gpointer data) {
- webkit_web_view_go_forward(WEBKIT_WEB_VIEW(data));
-}
-
-void home_button_clicked(GtkWidget *widget, gpointer data) {
- load_into_view("index.html", MAIN_VIEW);
-}
-
-/* Toggles the contents pane */
-void contents_button_clicked(GtkWidget *widget, gpointer data) {
- if (gtk_paned_get_position(GTK_PANED(data)) < 50) {
- gtk_paned_set_position(GTK_PANED(data), 370);
- }
- else {
- gtk_paned_set_position(GTK_PANED(data), 0);
- }
-}
-
-gboolean contents_click_handler(
- WebKitWebView *web_view,
- WebKitWebFrame *frame,
- WebKitNetworkRequest *request,
- WebKitWebNavigationAction *navigation_action,
- WebKitWebPolicyDecision *policy_decision,
- gpointer data) {
-
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(data), webkit_network_request_get_uri(request));
-
- return TRUE;
-}
-
-/**
- * Initialize the buttons for the help window
- */
-void initialize_buttons (GtkWidget *main_vbox, GtkWidget *content_hpane) {
- GtkWidget *buttons_hbuttonbox;
- GtkWidget *back_button;
- GtkWidget *forward_button;
- GtkWidget *home_button;
- GtkWidget *contents_button;
-
- // define and attach signals to buttons
- back_button = gtk_button_new_with_label(_("Back"));
- g_signal_connect(back_button, "clicked", G_CALLBACK(back_button_clicked), G_OBJECT(main_view));
-
- forward_button = gtk_button_new_with_label(_("Forward"));
- g_signal_connect(forward_button, "clicked", G_CALLBACK(forward_button_clicked), G_OBJECT(main_view));
-
- home_button = gtk_button_new_with_label(_("Home"));
- g_signal_connect(home_button, "clicked", G_CALLBACK(home_button_clicked), G_OBJECT(main_view));
-
- contents_button = gtk_button_new_with_label(_("Contents"));
- g_signal_connect(contents_button, "clicked", G_CALLBACK(contents_button_clicked), G_OBJECT(content_hpane));
-
- // button layout
- buttons_hbuttonbox = gtk_hbutton_box_new();
- gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), back_button);
- gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), forward_button);
- gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), home_button);
- gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), contents_button);
- gtk_box_pack_start(GTK_BOX(main_vbox), buttons_hbuttonbox, FALSE, TRUE, 0);
- gtk_box_set_spacing(GTK_BOX(buttons_hbuttonbox), 6);
- gtk_button_box_set_layout(GTK_BUTTON_BOX(buttons_hbuttonbox), GTK_BUTTONBOX_START);
-
- /* Store pointers to all widgets, for use by lookup_widget(). */
- GLADE_HOOKUP_OBJECT (main_view, back_button, BACKBUTTON);
- GLADE_HOOKUP_OBJECT (main_view, forward_button, FORWARDBUTTON);
- GLADE_HOOKUP_OBJECT (main_view, home_button, HOMEBUTTON);
- GLADE_HOOKUP_OBJECT (main_view, contents_button, CONTENTBUTTON);
-}
-
-/**
- * Create the help windows including all contained widgets and the needed HTML documents.
- *
- * \RETURN handle of the created window.
- */
-
-GtkWidget*
-CreateHelpWindow (void)
-{
- GtkWidget *main_vbox;
- GtkWidget *main_view_scroller;
- GtkWidget *contents_view_scroller;
- GtkWidget *content_hpane;
-
- int width;
- int height;
- int x, y;
- int w = 0, h = 0;
- const char *pref;
- char title[100];
-
- wHelpWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- width = gdk_screen_get_width( gtk_window_get_screen( (GtkWindow *)wHelpWindow ));
- height = gdk_screen_get_height( gtk_window_get_screen( (GtkWindow *)wHelpWindow ));
-
- pref = wPrefGetString( HTMLHELPSECTION, WINDOWSIZEPREFNAME );
- if( pref ) {
- sscanf( pref, "%d %d", &w, &h );
- if( w > width )
- w = width;
- if( h > height )
- h = height;
- }
- else {
- w = ( width * 2 )/ 5;
- h = height - 100;
- }
-
- pref = wPrefGetString( HTMLHELPSECTION, WINDOWPOSPREFNAME );
- if( pref ) {
- sscanf( pref, "%d %d", &x, &y );
- if( y > height - h )
- y = height - h;
-
- if( x > width - w )
- x = width - w;
- }
- else {
- x = ( width * 3 ) / 5 - 10;
- y = 70;
- }
-
- gtk_window_resize( (GtkWindow *)wHelpWindow, w, h );
- gtk_window_move( (GtkWindow *)wHelpWindow, x, y );
-
- gtk_window_set_title (GTK_WINDOW (wHelpWindow), "XTrkCad Help");
-
- g_signal_connect( G_OBJECT( wHelpWindow ), "delete-event", G_CALLBACK( DestroyHelpWindow ), NULL );
-
- main_view_scroller = gtk_scrolled_window_new(NULL, NULL);
- contents_view_scroller = gtk_scrolled_window_new(NULL, NULL);
- main_view = webkit_web_view_new();
- contents_view = webkit_web_view_new();
- // must be done here as it gets locked down later
- load_into_view ("contents.html", CONTENTS_VIEW);
- gtk_widget_set_size_request(GTK_WIDGET(wHelpWindow), x, y);
-
- main_vbox = gtk_vbox_new(FALSE, 5);
- gtk_container_add(GTK_CONTAINER(wHelpWindow), main_vbox);
-
- gtk_container_add(GTK_CONTAINER(main_view_scroller), main_view);
-
- gtk_container_add(GTK_CONTAINER(contents_view_scroller), contents_view);
-
- content_hpane = gtk_hpaned_new();
- initialize_buttons(main_vbox, content_hpane);
- gtk_container_add(GTK_CONTAINER(content_hpane), contents_view_scroller);
- gtk_container_add(GTK_CONTAINER(content_hpane), main_view_scroller);
- gtk_box_pack_start(GTK_BOX(main_vbox), content_hpane, TRUE, TRUE, 0);
-
- gtk_paned_set_position(GTK_PANED(content_hpane), 370);
-
- g_signal_connect(contents_view, "navigation-policy-decision-requested", G_CALLBACK(contents_click_handler), G_OBJECT(main_view));
-
- /* Store pointers to all widgets, for use by lookup_widget(). */
- GLADE_HOOKUP_OBJECT_NO_REF (wHelpWindow, wHelpWindow, "wHelpWindow");
- GLADE_HOOKUP_OBJECT (wHelpWindow, content_hpane, PANED );
- GLADE_HOOKUP_OBJECT (wHelpWindow, contents_view, TOCVIEW );
- GLADE_HOOKUP_OBJECT (wHelpWindow, main_view, CONTENTSVIEW );
-
- return wHelpWindow;
-}
-
-void load_into_view (char *file, int requested_view) {
- GtkWidget *view;
-
- switch (requested_view) {
- case MAIN_VIEW:
- view = main_view;
- break;
- case CONTENTS_VIEW:
- view = contents_view;
- break;
- default:
- printf("*** error, could not find view");
- break;
- }
-
- char fileToLoad[100] = "file://";
- strcat(fileToLoad,directory);
- strcat(fileToLoad,file);
-
- //debug printf("*** loading %s into pane %d.\n", fileToLoad, requested_view);
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(view), fileToLoad);
-}
-
-/**
- * Invoke the help system to display help for <topic>.
- *
- * \param topic IN topic string
- */
-
-EXPORT void wHelp( const char * topic )
-{
- char *htmlFile;
-
- if( !wHelpWindow )
- {
- directory = malloc( BUFSIZ );
- assert( directory != NULL );
-
- sprintf( directory, "%s/html/", wGetAppLibDir());
-
- wHelpWindow = CreateHelpWindow();
- /* load the default content */
- load_into_view ("index.html", MAIN_VIEW);
- }
-
- /* need space for the 'html' extension plus dot plus \0 */
- htmlFile = malloc( strlen( topic ) + 6 );
- assert( htmlFile != NULL );
-
- sprintf( htmlFile, "%s.html", topic );
-
- load_into_view (htmlFile, MAIN_VIEW);
- gtk_widget_show_all(wHelpWindow);
- gtk_window_present(GTK_WINDOW(wHelpWindow));
-}
-
-/**
- * Handle the commands issued from the Help drop-down. Currently, we only have a table
- * of contents, but search etc. might be added in the future.
- *
- * \PARAM data IN command value
- *
- */
-
-static void
-DoHelpMenu( void *data )
-{
- int func = (intptr_t)data;
-
- switch( func )
- {
- case 1:
- wHelp( "index" );
- break;
- default:
- break;
- }
-
- return;
-}
-
-/**
- * Add the entries for Help to the drop-down.
- *
- * \PARAM m IN handle of drop-down
- *
- */
-
-void wMenuAddHelp( wMenu_p m )
-{
- wMenuPushCreate( m, NULL, _("&Contents"), 0, DoHelpMenu, (void*)1 );
-}
diff --git a/app/wlib/gtklib/gtkint.h b/app/wlib/gtklib/gtkint.h
index c27c70b..da0d9ae 100644
--- a/app/wlib/gtklib/gtkint.h
+++ b/app/wlib/gtklib/gtkint.h
@@ -1,5 +1,5 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkint.h,v 1.8 2009-12-12 17:16:08 m_fischer Exp $
+/** \file gtkint.h
+ * Internal definitions for the gtk-library
*/
/* XTrkCad - Model Railroad CAD
@@ -27,7 +27,6 @@
#include "gdk/gdk.h"
#include "gtk/gtk.h"
-#define EXPORT
#ifdef WINDOWS
#define strcasecmp _stricmp
@@ -35,6 +34,10 @@
#include "dynarr.h"
+#define BORDERSIZE (4)
+#define LABEL_OFFSET (3)
+#define MENUH (24)
+
extern wWin_p gtkMainW;
typedef enum {
@@ -84,6 +87,37 @@ struct wWin_t {
struct wControl_t {
WOBJ_COMMON
};
+
+typedef struct wListItem_t * wListItem_p;
+
+struct wList_t {
+ WOBJ_COMMON
+// GtkWidget *list;
+ int count;
+ int number;
+ int colCnt;
+ wPos_t *colWidths;
+ wBool_t *colRightJust;
+ GtkListStore *listStore;
+ GtkWidget *treeView;
+ int last;
+ wPos_t listX;
+ long * valueP;
+ wListCallBack_p action;
+ int recursion;
+ int editted;
+ int editable;
+ };
+
+
+struct wListItem_t {
+ wBool_t active;
+ void * itemData;
+ const char * label;
+ GtkLabel * labelG;
+ wBool_t selected;
+ wList_p listP;
+ };
#define gtkIcon_bitmap (1)
#define gtkIcon_pixmap (2)
@@ -95,83 +129,118 @@ struct wIcon_t {
const void * bits;
};
-extern char wAppName[];
extern char wConfigName[];
extern wDrawColor wDrawColorWhite;
extern wDrawColor wDrawColorBlack;
-/* gtkmisc.c */
-void * gtkAlloc( wWin_p, wType_e, wPos_t, wPos_t, const char *, int, void * );
-void gtkComputePos( wControl_p );
-void gtkAddButton( wControl_p );
-int gtkAddLabel( wControl_p, const char * );
-void gtkControlGetSize( wControl_p );
-struct accelData_t;
-struct accelData_t * gtkFindAccelKey( GdkEventKey * event );
-wBool_t gtkHandleAccelKey( GdkEventKey * );
-wBool_t catch_shift_ctrl_alt_keys( GtkWidget *, GdkEventKey *, void * );
-void gtkSetReadonly( wControl_p, wBool_t );
-wControl_p gtkGetControlFromPos( wWin_p, wPos_t, wPos_t );
-void gtkSetTrigger( wControl_p, setTriggerCallback_p );
-GdkPixmap * gtkMakeIcon( GtkWidget *, wIcon_p, GdkBitmap ** );
-char * gtkConvertInput( const char * );
-char * gtkConvertOutput( const char * );
-
-/* gtkwindow.c */
-void gtkDoModal( wWin_p, wBool_t );
-
-/* gtkhelp.c */
-void load_into_view( char *, int );
-void gtkAddHelpString( GtkWidget *, const char * );
-void gtkHelpHideBalloon( void );
-
-/* gtksimple.c */
-void gtkDrawBox( wWin_p, wBoxType_e, wPos_t, wPos_t, wPos_t, wPos_t );
-void gtkLineShow( wLine_p, wBool_t );
-
-/* gktlist.c */
-void gtkListShow( wList_p, wBool_t );
-void gtkListSetPos( wList_p );
-void gtkListActive( wList_p, wBool_t );
-void gtkDropListPos( wList_p );
-
-/* gtktext.c */
-void gtkTextFreeze( wText_p );
-void gtkTextThaw( wText_p );
-
-/* gtkfont.c */
-const char * gtkFontTranslate( wFont_p );
-PangoLayout *gtkFontCreatePangoLayout( GtkWidget *, void *cairo,
- wFont_p, wFontSize_t, const char *,
- int *, int *, int *, int * );
-
-/* gtkbutton.c */
-void gtkButtonDoAction( wButton_p );
-void gtkSetLabel( GtkWidget*, long, const char *, GtkLabel**, GtkWidget** );
-
-/* gtkcolor.c */
-void gtkGetColorMap( void );
-GdkColor * gtkGetColor( wDrawColor, wBool_t );
-int gtkGetColorChar( wDrawColor );
-void gtkPrintColorMap( FILE *, int, int );
-int gtkMapPixel( long );
-
-/* psprint.c */
-
-void WlibApplySettings( GtkPrintOperation *op );
-void WlibSaveSettings( GtkPrintOperation *op );
-
-void psPrintLine( wPos_t, wPos_t, wPos_t, wPos_t,
- wDrawWidth, wDrawLineType_e, wDrawColor, wDrawOpts );
-void psPrintArc( wPos_t, wPos_t, wPos_t, double, double, int,
- wDrawWidth, wDrawLineType_e, wDrawColor, wDrawOpts );
-void psPrintString( wPos_t x, wPos_t y, double a, char * s,
- wFont_p fp, double fs, wDrawColor color, wDrawOpts opts );
-
-void psPrintFillRectangle( wPos_t, wPos_t, wPos_t, wPos_t, wDrawColor, wDrawOpts );
-void psPrintFillPolygon( wPos_t [][2], int, wDrawColor, wDrawOpts );
-void psPrintFillCircle( wPos_t, wPos_t, wPos_t, wDrawColor, wDrawOpts );
+
+/* boxes.c */
+void wlibDrawBox(wWin_p win, wBoxType_e style, wPos_t x, wPos_t y, wPos_t w, wPos_t h);
+
+/* button.c */
+void wlibSetLabel(GtkWidget *widget, long option, const char *labelStr, GtkLabel **labelG, GtkWidget **imageG);
+void wlibButtonDoAction(wButton_p bb);
+
+struct wButton_t {
+ WOBJ_COMMON
+ GtkLabel * labelG;
+ GtkWidget * imageG;
+ wButtonCallBack_p action;
+ int busy;
+ int recursion;
+};
+
+/* color.c */
+typedef struct {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ GdkColor normalColor;
+ GdkColor invertColor;
+ long rgb;
+ int colorChar;
+} colorMap_t;
+
+GdkColor *wlibGetColor(wDrawColor color, wBool_t normal);
+
+/* control.c */
+
+/* droplist.c */
+enum columns {
+ LISTCOL_DATA, /**< user data not for display */
+ LISTCOL_BITMAP, /**< bitmap column */
+ LISTCOL_TEXT, /**< starting point for text columns */
+};
+GtkWidget *wlibNewDropList(GtkListStore *ls, int editable);
+
+wIndex_t wDropListGetCount(wList_p b);
+void wDropListClear(wList_p b);
+void *wDropListGetItemContext(wList_p b, wIndex_t inx);
+void wDropListAddValue(wList_p b, char *text, wListItem_p data);
+void wDropListSetIndex(wList_p b, int val);
+wBool_t wDropListSetValues(wList_p b, wIndex_t row, const char *labelStr, wIcon_p bm, void *itemData);
+wList_p wDropListCreate(wWin_p parent, wPos_t x, wPos_t y, const char *helpStr, const char *labelStr, long option, long number, wPos_t width, long *valueP, wListCallBack_p action, void *data);
+
+/* filesel.c */
+
+/* font.c */
+PangoLayout *wlibFontCreatePangoLayout(GtkWidget *widget, void *cairo, wFont_p fp, wFontSize_t fs, const char *s, int *width_p, int *height_p, int *ascent_p, int *descent_p);
+void wlibFontDestroyPangoLayout(PangoLayout *layout);
+const char *wlibFontTranslate(wFont_p fp);
+
+/* help.c */
+
+/* lines.c */
+void wlibLineShow(wLine_p bl, wBool_t visible);
+
+/* list.c */
+int CompareListData(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
+
+/* liststore.c */
+wListItem_p wlibListItemGet(GtkListStore *ls, wIndex_t inx, GList **childR);
+void *wlibListStoreGetContext(GtkListStore *ls, int inx);
+void wlibListStoreClear(GtkListStore *listStore);
+GtkListStore *wlibNewListStore(int colCnt);
+void wlibListStoreSetPixbuf(GtkListStore *ls, GtkTreeIter *iter, GdkPixbuf *pixbuf);
+int wlibListStoreAddData(GtkListStore *ls, GdkPixbuf *pixbuf, int cols, wListItem_p id);
+int wlibListStoreUpdateValues(GtkListStore *ls, int row, int cols, char *labels, wIcon_p bm);
+
+/* main.c */
+char *wlibGetAppName(void);
+
+/* menu.c */
+int getMlistOrigin(wMenuList_p ml, GList **pChildren);
+
+/* misc.c */
+typedef struct accelData_t {
+ wAccelKey_e key;
+ int modifier;
+ wAccelKeyCallBack_p action;
+ void * data;
+} accelData_t;
+
+
+GdkPixbuf* wlibPixbufFromXBM(wIcon_p ip);
+int wlibAddLabel(wControl_p b, const char *labelStr);
+void *wlibAlloc(wWin_p parent, wType_e type, wPos_t origX, wPos_t origY, const char *labelStr, int size, void *data);
+void wlibComputePos(wControl_p b);
+void wlibControlGetSize(wControl_p b);
+void wlibAddButton(wControl_p b);
+wControl_p wlibGetControlFromPos(wWin_p win, wPos_t x, wPos_t y);
+char *wlibConvertInput(const char *inString);
+char *wlibConvertOutput(const char *inString);
+struct accelData_t *wlibFindAccelKey(GdkEventKey *event);
+wBool_t wlibHandleAccelKey(GdkEventKey *event);
+
+/* notice.c */
+
+/* pixbuf.c */
+GdkPixbuf *wlibMakePixbuf(wIcon_p ip);
+
+/* png.c */
+
+/* print.c */
struct wDraw_t {
WOBJ_COMMON
void * context;
@@ -199,4 +268,48 @@ struct wDraw_t {
cairo_t *printContext;
cairo_surface_t *curPrintSurface;
};
+
+void WlibApplySettings(GtkPrintOperation *op);
+void WlibSaveSettings(GtkPrintOperation *op);
+void psPrintLine(wPos_t x0, wPos_t y0, wPos_t x1, wPos_t y1, wDrawWidth width, wDrawLineType_e lineType, wDrawColor color, wDrawOpts opts);
+void psPrintArc(wPos_t x0, wPos_t y0, wPos_t r, double angle0, double angle1, wBool_t drawCenter, wDrawWidth width, wDrawLineType_e lineType, wDrawColor color, wDrawOpts opts);
+void psPrintFillRectangle(wPos_t x0, wPos_t y0, wPos_t x1, wPos_t y1, wDrawColor color, wDrawOpts opts);
+void psPrintFillPolygon(wPos_t p[][2], int cnt, wDrawColor color, wDrawOpts opts);
+void psPrintFillCircle(wPos_t x0, wPos_t y0, wPos_t r, wDrawColor color, wDrawOpts opts);
+void psPrintString(wPos_t x, wPos_t y, double a, char *s, wFont_p fp, double fs, wDrawColor color, wDrawOpts opts);
+static void WlibGetPaperSize(void);
+
+/* single.c */
+
+/* splash.c */
+
+/* text.c */
+
+/* timer.c */
+void wlibSetTrigger(wControl_p b, setTriggerCallback_p trigger);
+
+/* tooltip.c */
+#define HELPDATAKEY "HelpDataKey"
+void wlibAddHelpString(GtkWidget *widget, const char *helpStr);
+void wlibHelpHideBalloon();
+
+/* treeview.c */
+void wlibTreeViewSetSelected(wList_p b, int index);
+GtkWidget *wlibNewTreeView(GtkListStore *ls, int showTitles, int multiSelection);
+int wlibTreeViewAddColumns(GtkWidget *tv, int count);
+int wlibAddColumnTitles(GtkWidget *tv, const char **titles);
+int wlibTreeViewAddData(GtkWidget *tv, int cols, char *label, GdkPixbuf *pixbuf, wListItem_p userData);
+void wlibTreeViewAddRow(wList_p b, char *label, wIcon_p bm, wListItem_p id_p);
+gboolean changeSelection(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data);
+
+int wTreeViewGetCount(wList_p b);
+void wTreeViewClear(wList_p b);
+void *wTreeViewGetItemContext(wList_p b, int row);
+
+/* window.c */
+void wlibDoModal(wWin_p win0, wBool_t modal);
+wBool_t catch_shift_ctrl_alt_keys(GtkWidget *widget, GdkEventKey *event, void *data);
+
+/* wpref.c */
+
#endif
diff --git a/app/wlib/gtklib/gtklist.c b/app/wlib/gtklib/gtklist.c
deleted file mode 100644
index fb8afaa..0000000
--- a/app/wlib/gtklib/gtklist.c
+++ /dev/null
@@ -1,1131 +0,0 @@
-/** \file gtklist.c
- * Listboxes, dropdown boxes, combo boxes
- */
-/* 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 <stdlib.h>
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include "gtkint.h"
-#include "i18n.h"
-
-#define ROW_HEIGHT (15)
-#define PIX_TEXT_SEP (5)
-static char ListItemDataKey[] = "ListItemDataKey";
-
-/*
- *****************************************************************************
- *
- * List Boxes
- *
- *****************************************************************************
- */
-
-typedef struct wListItem_t * wListItem_p;
-
-struct wList_t {
- WOBJ_COMMON
- GtkWidget *list;
- int count;
- int number;
- int colCnt;
- wPos_t *colWidths;
- wBool_t *colRightJust;
- int last;
- wPos_t listX;
- long * valueP;
- wListCallBack_p action;
- int recursion;
- int editted;
- int editable;
- };
-
-
-struct wListItem_t {
- wBool_t active;
- void * itemData;
- const char * label;
- GtkLabel * labelG;
- wBool_t selected;
- wList_p listP;
- };
-
-
-static wListItem_p getListItem(
- wList_p b,
- wIndex_t inx,
- GList ** childR )
-{
- GList * child;
- GtkObject * listItem;
- wListItem_p id_p;
- if (childR)
- *childR = NULL;
- if (b->list == 0) abort();
- if (inx < 0)
- return NULL;
- if ( b->type == B_LIST )
- return (wListItem_p)gtk_clist_get_row_data( GTK_CLIST(b->list), inx );
-
- for ( child=GTK_LIST(b->list)->children; inx>0&&child; child=child->next,inx-- );
- if (child==NULL) {
- fprintf( stderr, "wListGetValues - End Of List\n" );
- return NULL;
- }
- listItem = GTK_OBJECT(child->data);
- id_p = (wListItem_p)gtk_object_get_data(listItem, ListItemDataKey );
- if (id_p==NULL) {
- fprintf( stderr, "wListGetValues - id_p == NULL\n" );
- return NULL;
- }
- if (childR)
- *childR = child;
- return id_p;
-}
-
-
-EXPORT void wListClear(
- wList_p b ) /* List */
-/*
-Remove all entries from the list <b>.
-*/
-{
- if (b->list == 0) abort();
- b->recursion++;
- if ( b->type == B_DROPLIST )
- gtk_list_clear_items( GTK_LIST(b->list), 0, b->count );
- else
- gtk_clist_clear( GTK_CLIST(b->list) );
- b->recursion--;
- b->last = -1;
- b->count = 0;
-}
-
-
-EXPORT void wListSetIndex(
- wList_p b, /* List */
- int val ) /* Index */
-/*
-Makes the <val>th entry (0-origin) the current selection.
-If <val> if '-1' then no entry is selected.
-*/
-{
- int cur;
- wListItem_p id_p;
-
- if (b->widget == 0) abort();
- b->recursion++;
- cur = b->last;
- if ( b->type == B_DROPLIST ) {
- if ((b->option&BL_NONE)!=0 && val < 0) {
- if (cur != -1) {
- gtk_list_unselect_item( GTK_LIST(b->list), cur );
- }
- } else {
- if (cur != -1)
- gtk_list_unselect_item( GTK_LIST(b->list), cur );
- if (val != -1)
- gtk_list_select_item( GTK_LIST(b->list), val );
- }
- } else {
- if (cur != -1) {
- gtk_clist_unselect_row( GTK_CLIST(b->list), cur, -1 );
- id_p = getListItem( b, cur, NULL );
- if ( id_p )
- id_p->selected = FALSE;
- }
- if (val != -1) {
- gtk_clist_select_row( GTK_CLIST(b->list), val, -1 );
- id_p = getListItem( b, val, NULL );
- if ( id_p )
- id_p->selected = TRUE;
- }
- }
- b->last = val;
- b->recursion--;
-}
-
-
-static void parseLabelStr(
- const char * labelStr,
- int count,
- char * * * texts )
-{
- static char * labelBuffer;
- static int labelBufferLen = 0;
- static char * * textBuffer;
- static int textBufferCount = 0;
- char * cp;
- int col;
- int len;
-
- labelStr = gtkConvertInput( labelStr );
- len = strlen(labelStr)+1;
- if ( len > labelBufferLen ) {
- if ( labelBuffer )
- labelBuffer = realloc( labelBuffer, len );
- else
- labelBuffer = (char*)malloc( len );
- labelBufferLen = len;
- }
- if ( count > textBufferCount ) {
- if ( textBuffer )
- textBuffer = (char**)malloc( count * sizeof *textBuffer );
- else
- textBuffer = (char**)realloc( textBuffer, count * sizeof *textBuffer );
- textBufferCount = count;
- }
-
- strcpy( labelBuffer, labelStr );
- cp = labelBuffer;
- for ( col=0; cp && col<count; col++ ) {
- textBuffer[col] = cp;
- cp = strchr( cp, '\t' );
- if ( cp != NULL )
- *cp++ = '\0';
- }
- for ( ; col<count; col++ )
- textBuffer[col] = "";
- *texts = textBuffer;
-}
-
-
-EXPORT void wListSetValue(
- wList_p bl,
- const char * val )
-{
- if (bl->list==NULL) abort();
- bl->recursion++;
- if (bl->type == B_DROPLIST) {
- bl->editted = TRUE;
- gtk_entry_set_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry), val );
- if (bl->action) {
- bl->action( -1, val, 0, bl->data, NULL );
- }
- }
- bl->recursion--;
-}
-
-
-EXPORT wIndex_t wListFindValue(
- wList_p b,
- const char * val )
-{
- GList * child;
- GtkObject * listItem;
- wListItem_p id_p;
- wIndex_t inx;
-
- if (b->list==NULL) abort();
- if (b->type == B_DROPLIST) {
- for ( child=GTK_LIST(b->list)->children,inx=0; child; child=child->next,inx++ ) {
- listItem = GTK_OBJECT(child->data);
- id_p = (wListItem_p)gtk_object_get_data(listItem, ListItemDataKey );
- if ( id_p && id_p->label && strcmp( id_p->label, val ) == 0 ) {
- return inx;
- }
- }
- } else {
- for ( inx=0; inx<b->count; inx++ ) {
- id_p = (wListItem_p)gtk_clist_get_row_data( GTK_CLIST(b->list), inx );
- if ( id_p && id_p->label && strcmp( id_p->label, val ) == 0 )
- return inx;
- }
- }
- return -1;
-}
-
-EXPORT wIndex_t wListGetIndex(
- wList_p b ) /* List */
-/*
-Returns the current selected list entry.
-If <val> if '-1' then no entry is selected.
-*/
-{
- if (b->list == 0) abort();
- return b->last;
-}
-
-EXPORT wIndex_t wListGetValues(
- wList_p bl,
- char * labelStr,
- int labelSize,
- void * * listDataRet,
- void * * itemDataRet )
-
-{
- wListItem_p id_p;
- wIndex_t inx = bl->last;
- const char * entry_value = "";
- void * item_data = NULL;
-
- if ( bl->list == 0 ) abort();
- if ( bl->type == B_DROPLIST && bl->editted ) {
- entry_value = gtk_entry_get_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry) );
- inx = bl->last = -1;
- } else {
- inx = bl->last;
- if (inx >= 0) {
- id_p = getListItem( bl, inx, NULL );
- if (id_p==NULL) {
- fprintf( stderr, "wListGetValues - id_p == NULL\n" );
- inx = -1;
- } else {
- entry_value = id_p->label;
- item_data = id_p->itemData;
- }
- }
- }
- if ( labelStr ) {
- strncpy( labelStr, entry_value, labelSize );
- }
- if ( listDataRet )
- *listDataRet = bl->data;
- if ( itemDataRet )
- *itemDataRet = item_data;
- return bl->last;
-}
-
-
-EXPORT wIndex_t wListGetCount(
- wList_p b )
-{
- return b->count;
-}
-
-
-EXPORT void * wListGetItemContext(
- wList_p b,
- wIndex_t inx )
-{
- wListItem_p id_p;
- if ( inx < 0 )
- return NULL;
- id_p = getListItem( b, inx, NULL );
- if ( id_p )
- return id_p->itemData;
- else
- return NULL;
-}
-
-
-EXPORT wBool_t wListGetItemSelected(
- wList_p b,
- wIndex_t inx )
-{
- wListItem_p id_p;
- if ( inx < 0 )
- return FALSE;
- id_p = getListItem( b, inx, NULL );
- if ( id_p )
- return id_p->selected;
- else
- return FALSE;
-}
-
-
-EXPORT wIndex_t wListGetSelectedCount(
- wList_p b )
-{
- wIndex_t selcnt, inx;
- for ( selcnt=inx=0; inx<b->count; inx++ )
- if ( wListGetItemSelected( b, inx ) )
- selcnt++;
- return selcnt;
-}
-
-/**
- * Select all items in list.
- *
- * \param bl IN list handle
- * \return
- */
-
-void wListSelectAll( wList_p bl )
-{
- wIndex_t inx;
- wListItem_p ldp;
-
- // mark all items selected
- gtk_clist_select_all(GTK_CLIST(bl->list));
-
- // and synchronize the internal data structures
- wListGetCount(bl);
- for ( inx=0; inx<bl->count; inx++ ) {
- ldp = getListItem( bl, inx, NULL );
-
- ldp->selected = TRUE;
- }
-}
-
-EXPORT wBool_t wListSetValues(
- wList_p b,
- wIndex_t row,
- const char * labelStr,
- wIcon_p bm,
- void *itemData )
-
-{
- wListItem_p id_p;
- GList * child;
- GdkPixmap *pixmap;
- GdkBitmap *bitmap = NULL;
- char ** texts;
- int col;
-
- if (b->list == 0) abort();
- b->recursion++;
- id_p = getListItem( b, row, &child );
- if (id_p != NULL) {
- if ( b->type == B_DROPLIST ) {
- gtk_label_set( id_p->labelG, labelStr?gtkConvertInput(labelStr):"" );
- id_p->label = strdup( labelStr?labelStr:"" );
- } else {
- parseLabelStr( labelStr, b->colCnt, &texts );
- for ( col=0; col<b->colCnt; col++ )
- gtk_clist_set_text( GTK_CLIST(b->list), row, col, texts[col] );
- if ( bm ) {
- pixmap = gtkMakeIcon( b->widget, bm, &bitmap );
- gtk_clist_set_pixtext( GTK_CLIST(b->list), row, 0, texts[0], 5, pixmap, bitmap );
- gdk_pixmap_unref( pixmap );
- gdk_bitmap_unref( bitmap );
- }
- }
- id_p->itemData = itemData;
- }
- b->recursion--;
- return TRUE;
-}
-
-
-EXPORT void wListDelete(
- wList_p b,
- wIndex_t inx )
-
-{
- wListItem_p id_p;
- GList * child;
-
- if (b->list == 0) abort();
- b->recursion++;
- if ( b->type == B_DROPLIST ) {
- id_p = getListItem( b, inx, &child );
- if (id_p != NULL) {
- gtk_container_remove( GTK_CONTAINER(b->list), child->data );
- b->count--;
- }
- } else {
- gtk_clist_remove( GTK_CLIST(b->list), inx );
- b->count--;
- }
- b->recursion--;
- return;
-}
-
-
-int wListGetColumnWidths(
- wList_p bl,
- int colCnt,
- wPos_t * colWidths )
-{
- int inx;
-
- if ( bl->type != B_LIST )
- return 0;
- if ( bl->colWidths == NULL )
- return 0;
- for ( inx=0; inx<colCnt; inx++ ) {
- if ( inx < bl->colCnt ) {
- colWidths[inx] = bl->colWidths[inx];
- } else {
- colWidths[inx] = 0;
- }
- }
- return bl->colCnt;
-}
-
-
-static void gtkDropListAddValue(
- wList_p b,
- wListItem_p id_p )
-{
- GtkWidget * listItem;
-
- if ( id_p == NULL )
- return;
- id_p->labelG = (GtkLabel*)gtk_label_new( gtkConvertInput(id_p->label) );
- /*gtk_misc_set_alignment( GTK_MISC(id_p->labelG), 0.0, 0.5 );*/
- gtk_widget_show( GTK_WIDGET(id_p->labelG) );
-
- listItem = gtk_list_item_new();
- gtk_object_set_data( GTK_OBJECT(listItem), ListItemDataKey, id_p );
- gtk_container_add( GTK_CONTAINER(listItem), GTK_WIDGET(id_p->labelG) );
- gtk_misc_set_alignment( GTK_MISC(id_p->labelG), 0.0, 0.5 );
- gtk_container_add( GTK_CONTAINER(b->list), listItem );
- gtk_widget_show( listItem );
-}
-
-
-EXPORT wIndex_t wListAddValue(
- wList_p b, /* List */
- const char * labelStr, /* Entry name */
- wIcon_p bm, /* Entry bitmap */
- void * itemData ) /* User context */
-/*
-Adds a entry to the list <b> with name <name>.
-If list is created with 'BL_
-*/
-{
- wListItem_p id_p;
- GdkPixmap * pixmap = NULL;
- GdkBitmap * bitmap;
- static char ** texts;
- GtkAdjustment *adj;
-
- if (b->list == 0) abort();
- b->recursion++;
- id_p = (wListItem_p)malloc( sizeof *id_p );
- memset( id_p, 0, sizeof *id_p );
- id_p->itemData = itemData;
- id_p->active = TRUE;
- if ( labelStr == NULL )
- labelStr = "";
- id_p->label = strdup( labelStr );
- id_p->listP = b;
- if ( b->type == B_DROPLIST ) {
- gtkDropListAddValue( b, id_p );
- } else {
- parseLabelStr( labelStr, b->colCnt, &texts );
- gtk_clist_append( GTK_CLIST(b->list), texts );
-
- /*
- * this has taken forever to find out: the adjustment has to be notified
- * about the list change by the program. So we need to get the current alignment.
- * increment the upper value and then inform the scrolled window about the update.
- * The upper value is increased only if the current value is smaller than the size
- * of the list box.
- */
-
- adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(b->widget));
-
- if( adj->upper < adj->step_increment * (b->count+1)) {
- adj->upper += adj->step_increment;
- gtk_adjustment_changed( adj );
- }
- if ( bm ) {
- pixmap = gtkMakeIcon( b->widget, bm, &bitmap );
- gtk_clist_set_pixtext( GTK_CLIST(b->list), b->count, 0, texts[0], 5, pixmap, bitmap );
- gdk_pixmap_unref( pixmap );
- gdk_bitmap_unref( bitmap );
- }
- gtk_clist_set_row_data( GTK_CLIST(b->list), b->count, id_p );
- }
-
- b->count++;
- b->recursion--;
- if ( b->count == 1 ) {
- b->last = 0;
- }
- return b->count-1;
-}
-
-
-void wListSetSize( wList_p bl, wPos_t w, wPos_t h )
-{
- /*gtk_widget_set_usize( bl->list, w, h );*/
- if (bl->type == B_DROPLIST) {
- /*gtk_widget_set_usize( GTK_COMBO(bl->widget)->entry, w, -1 );
- gtk_widget_set_usize( GTK_COMBO(bl->widget)->list, w, -1 );*/
-#ifndef GTK1
- gtk_widget_set_size_request( bl->widget, w, -1 );
-#else
- gtk_widget_set_usize( bl->widget, w, -1 );
-#endif
- } else {
-#ifndef GTK1
- gtk_widget_set_size_request( bl->widget, w, h );
-#else
- gtk_widget_set_usize( bl->widget, w, h );
-#endif
- }
- bl->w = w;
- bl->h = h;
-}
-
-
-
-
-EXPORT void wListSetActive(
- wList_p b, /* List */
- int inx, /* Index */
- wBool_t active ) /* Command */
-/*
-*/
-{
- wListItem_p id_p;
- GList * child;
-
- if (b->list == 0) abort();
- id_p = getListItem( b, inx, &child );
- if (id_p == NULL)
- return;
- gtk_widget_set_sensitive( GTK_WIDGET(child->data), active );
-}
-
-
-EXPORT void wListSetEditable(
- wList_p b,
- wBool_t editable )
-{
- b->editable = editable;
- if ( b->type == B_DROPLIST )
- gtk_widget_set_sensitive( GTK_WIDGET(GTK_COMBO(b->widget)->entry), b->editable );
-}
-
-
-static int selectCList(
- GtkWidget * clist,
- int row,
- int col,
- GdkEventButton* event,
- gpointer data )
-{
- wList_p bl = (wList_p)data;
- wListItem_p id_p;
-
- if (gdk_pointer_is_grabbed()) {
- gdk_pointer_ungrab(0);
- }
- wFlush();
- if (bl->recursion)
- return 0;
- id_p = gtk_clist_get_row_data( GTK_CLIST(clist), row );
- if ( id_p == NULL ) return 1;
- bl->editted = FALSE;
- if ( (bl->option&BL_MANY)==0 && bl->last == row )
- return 1;
- bl->last = row;
- id_p->selected = TRUE;
- if (bl->valueP)
- *bl->valueP = row;
- if (bl->action)
- bl->action( row, id_p->label, 1, bl->data, id_p->itemData );
- return 1;
-}
-
-
-static int unselectCList(
- GtkWidget * clist,
- int row,
- int col,
- GdkEventButton* event,
- gpointer data )
-{
- wList_p bl = (wList_p)data;
- wListItem_p id_p;
-
- if (gdk_pointer_is_grabbed()) {
- gdk_pointer_ungrab(0);
- }
- wFlush();
- if (bl->recursion)
- return 0;
- id_p = gtk_clist_get_row_data( GTK_CLIST(clist), row );
- if ( id_p == NULL ) return 1;
- id_p->selected = FALSE;
- if (bl->action)
- bl->action( row, id_p->label, 2, bl->data, id_p->itemData );
- return 1;
-}
-
-
-static int resizeColumnCList(
- GtkWidget * clist,
- int col,
- int width,
- gpointer data )
-{
- wList_p bl = (wList_p)data;
-
- if (gdk_pointer_is_grabbed()) {
- gdk_pointer_ungrab(0);
- }
- wFlush();
- if (bl->recursion)
- return 0;
- if ( col >= 0 && col < bl->colCnt )
- bl->colWidths[col] = width;
- return 0;
-}
-
-
-
-static int DropListSelectChild(
- GtkWidget * list,
- GtkWidget * listItem,
- gpointer data )
-{
- wList_p bl = (wList_p)data;
- wListItem_p id_p=NULL;
- wIndex_t inx;
- GList * child;
-
- if (gdk_pointer_is_grabbed()) {
- gdk_pointer_ungrab(0);
- }
-#ifdef LATER
- printf( "DropListSelectChild %p %p %p\n", list, listItem, data );
- printf( " b: recurs=%d widget=%p\n", bl->recursion, bl->list );
-#endif
- if (bl->recursion)
- return 0;
- wFlush();
- id_p = gtk_object_get_data(GTK_OBJECT(listItem), ListItemDataKey );
- if ( id_p == NULL ) {
- fprintf( stderr, " id_p = NULL\n");
- return 0;
- }
-#ifdef LATER
- printf( " id_p = %s %lx, %d %d\n", id_p->label, (long)id_p->itemData, id_p->active, id_p->selected );
-#endif
- if ( bl->type == B_DROPLIST && bl->editable ) {
- if ( bl->editted == FALSE )
- return 0;
- gtkSetTrigger( NULL, NULL );
- }
- bl->editted = FALSE;
- for ( inx=0,child=GTK_LIST(bl->list)->children,inx=0; child&&child->data!=listItem; child=child->next ) inx++;
- if ( bl->last == inx )
- return 1;
- bl->last = inx;
- if (bl->valueP)
- *bl->valueP = inx;
- if (id_p && bl->action)
- bl->action( (wIndex_t)inx, id_p->label, 1, bl->data, id_p->itemData );
- gtkSetTrigger( NULL, NULL );
- return 1;
-}
-
-
-#ifdef LATER
-static int DropListSelectionChanged(
- GtkWidget * list,
- gpointer data )
-{
- wList_p bl = (wList_p)data;
- wListItem_p id_p=NULL;
- GList * child;
- GList * dlist;
- wIndex_t inx;
- GtkObject * listItem;
- if (gdk_pointer_is_grabbed()) {
- gdk_pointer_ungrab(0);
- }
- if (bl->recursion)
- return 0;
- wFlush();
- if ( bl->type == B_DROPLIST && bl->editable ) {
- if ( bl->editted == FALSE )
- return 0;
- gtkSetTrigger( NULL, NULL );
- }
-
- dlist = GTK_LIST(bl->list)->selection;
- if (dlist == NULL) {
- return 0;
- }
- inx = 0;
- for ( child=GTK_LIST(bl->list)->children,inx=0; child&&child->data!=dlist->data; child=child->next ) inx++;
- while (dlist) {
- listItem = GTK_OBJECT(dlist->data);
- id_p = gtk_object_get_data(listItem, ListItemDataKey );
- printf( "DropListSelectionChanged: id_p = %s %lx\n", id_p->label, (long)id_p->itemData );
- dlist = dlist->next;
- }
- return 0;
-#ifdef LATER
- bl->editted = FALSE;
- if ( bl->last == inx )
- return 1;
- bl->last = inx;
- if (bl->valueP)
- *bl->valueP = inx;
- if (id_p && bl->action)
- bl->action( inx, id_p->label, 1, bl->data, id_p->itemData );
- gtkSetTrigger( NULL, NULL );
- return 1;
-#endif
-}
-
-#endif
-
-
-static void triggerDListEntry(
- wControl_p b )
-{
- wList_p bl = (wList_p)b;
- const char * entry_value;
-
- if (bl == 0)
- return;
- if (bl->widget == 0) abort();
- entry_value = gtk_entry_get_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry) );
- if (entry_value == NULL) return;
- if (debugWindow >= 2) printf("triggerListEntry: %s text = %s\n", bl->labelStr?bl->labelStr:"No label", entry_value );
- if (bl->action) {
- bl->recursion++;
- bl->action( -1, entry_value, 0, bl->data, NULL );
- bl->recursion--;
- }
- gtkSetTrigger( NULL, NULL );
- return;
-}
-
-
-static void updateDListEntry(
- GtkEntry * widget,
- wList_p bl )
-{
- const char *entry_value;
- if (bl == 0)
- return;
- if (bl->recursion)
- return;
- if (!bl->editable)
- return;
- entry_value = gtk_entry_get_text( GTK_ENTRY(GTK_COMBO(bl->widget)->entry) );
- bl->editted = TRUE;
- if (bl->valueP != NULL)
- *bl->valueP = -1;
- bl->last = -1;
- if (bl->action)
- gtkSetTrigger( (wControl_p)bl, triggerDListEntry );
- return;
-}
-
-
-
-#ifdef LATER
-EXPORT wList_p wListCreate(
- wWin_p parent, /* Parent window */
- wPos_t x, /* X-position */
- wPos_t y, /* Y-position */
- const char * helpStr, /* Help string */
- const char * labelStr, /* Label */
- long option, /* Options */
- long number, /* Number of displayed entries */
- wPos_t width, /* Width of list */
- long *valueP, /* Selected index */
- wListCallBack_p action, /* Callback */
- void *data ) /* Context */
-/*
-*/
-{
- wList_p b;
-
- b = (wList_p)gtkAlloc( parent, B_LIST, x, y, labelStr, sizeof *b, data );
- b->option = option;
- b->number = number;
- b->count = 0;
- b->last = -1;
- b->valueP = valueP;
- b->action = action;
- b->listX = b->realX;
- b->colCnt = 0;
- b->colWidths = NULL;
- b->colRightJust = NULL;
- gtkComputePos( (wControl_p)b );
-
- b->list = (GtkWidget*)gtk_clist_new(1);
- if (b->list == 0) abort();
- b->widget = gtk_scrolled_window_new( NULL, NULL );
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (b->widget),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
- /*gtk_container_add( GTK_CONTAINER(b->widget), b->list );*/
- gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(b->widget), b->list );
- if (width == 0)
- width = 100;
- gtk_clist_set_column_width( GTK_CLIST(b->list), 0, width );
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, width, (number+1)*ROW_HEIGHT );
-#else
- gtk_widget_set_usize( b->widget, width, (number+1)*ROW_HEIGHT );
-#endif
- gtk_signal_connect( GTK_OBJECT(b->list), "select_row", GTK_SIGNAL_FUNC(selectCList), b );
- gtk_signal_connect( GTK_OBJECT(b->list), "unselect_row", GTK_SIGNAL_FUNC(unselectCList), b );
- gtk_list_set_selection_mode( GTK_LIST(b->list), (option&BL_MANY)?GTK_SELECTION_MULTIPLE:GTK_SELECTION_BROWSE );
-/* gtk_container_set_focus_vadjustment (GTK_CONTAINER (b->list),
- gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (b->widget))); */
- gtk_widget_show( b->list );
-
-#ifndef GTK1
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
- gtk_widget_set_uposition( b->widget, b->realX, b->realY );
-#endif
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- gtkAddHelpString( b->widget, helpStr );
- return b;
-}
-#endif
-
-/** Create a drop down list. The drop down is created and intialized with the supplied values.
- *
- * \param IN parent Parent window
- * \param IN x, X-position
- * \param IN y Y-position
- * \param IN helpStr Help string
- * \param IN labelStr Label
- * \param IN option Options
- * \param IN number Number of displayed entries
- * \param IN width Width
- * \param IN valueP Selected index
- * \param IN action Callback
- * \param IN data Context
- */
-
-EXPORT wList_p wDropListCreate(
- wWin_p parent, /* Parent window */
- wPos_t x, /* X-position */
- wPos_t y, /* Y-position */
- const char * helpStr, /* Help string */
- const char * labelStr, /* Label */
- long option, /* Options */
- long number, /* Number of displayed entries */
- wPos_t width, /* Width */
- long *valueP, /* Selected index */
- wListCallBack_p action, /* Callback */
- void *data ) /* Context */
-/*
-*/
-{
- wList_p b;
- b = (wList_p)gtkAlloc( parent, B_DROPLIST, x, y, labelStr, sizeof *b, data );
- b->option = option;
- b->number = number;
- b->count = 0;
- b->last = -1;
- b->valueP = valueP;
- b->action = action;
- b->listX = b->realX;
- b->colCnt = 0;
- b->colWidths = NULL;
- b->colRightJust = NULL;
- gtkComputePos( (wControl_p)b );
-
- b->widget = (GtkWidget*)gtk_combo_new();
- if (b->widget == 0) abort();
- b->list = GTK_COMBO(b->widget)->list;
-#ifdef LATER
- gtk_signal_connect( GTK_OBJECT(b->list), "selection_changed", GTK_SIGNAL_FUNC(DropListSelectionChanged), b );
-#endif
- gtk_signal_connect( GTK_OBJECT(b->list), "select_child", GTK_SIGNAL_FUNC(DropListSelectChild), b );
- if (width == 0)
- width = 100;
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, width, -1 );
- gtk_widget_set_size_request( GTK_COMBO(b->widget)->entry, width, -1 );
-#else
- gtk_widget_set_usize( b->widget, width, -1 );
- gtk_widget_set_usize( GTK_COMBO(b->widget)->entry, width, -1 );
-#endif
-
- gtk_signal_connect( GTK_OBJECT(GTK_COMBO(b->widget)->entry), "changed", GTK_SIGNAL_FUNC(updateDListEntry), b );
- if ( (option&BL_EDITABLE) == 0 )
- gtk_widget_set_sensitive( GTK_WIDGET(GTK_COMBO(b->widget)->entry), FALSE );
- else {
- b->editable = TRUE;
- }
-
-#ifndef GTK1
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
- gtk_widget_set_uposition( b->widget, b->realX, b->realY );
-#endif
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- gtkAddHelpString( b->widget, helpStr );
- return b;
-
-}
-
-
-EXPORT wList_p wComboListCreate(
- wWin_p parent, /* Parent window */
- wPos_t x, /* X-position */
- wPos_t y, /* Y-position */
- const char * helpStr, /* Help string */
- const char * labelStr, /* Label */
- long option, /* Options */
- long number, /* Number of displayed list entries */
- wPos_t width, /* Width */
- long *valueP, /* Selected index */
- wListCallBack_p action, /* Callback */
- void *data ) /* Context */
-/*
-*/
-{
- return wListCreate( parent, x, y, helpStr, labelStr, option, number, width, 0, NULL, NULL, NULL, valueP, action, data );
-#ifdef LATER
- wList_p b;
-
- b = (wList_p)gtkAlloc( parent, B_LIST, x, y, labelStr, sizeof *b, data );
- b->option = option;
- b->number = number;
- b->count = 0;
- b->last = -1;
- b->valueP = valueP;
- b->action = action;
- b->listX = b->realX;
- gtkComputePos( (wControl_p)b );
-
- b->widget = (GtkWidget*)gtk_combo_new();
- if (b->widget == 0) abort();
- if (width == 0)
- width = 100;
- /*gtk_clist_set_column_width( GTK_CLIST(b->widget), 0, width );*/
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, width, -1 );
-#else
- gtk_widget_set_usize( b->widget, width, -1 );
-#endif
-
-#ifndef GTK1
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
- gtk_widget_set_uposition( b->widget, b->realX, b->realY );
-#endif
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- gtkAddHelpString( b->widget, helpStr );
- return b;
-#endif
-}
-
-
-
-EXPORT wList_p wListCreate(
- wWin_p parent, /* Parent window */
- wPos_t x, /* X-position */
- wPos_t y, /* Y-position */
- const char * helpStr, /* Help string */
- const char * labelStr, /* Label */
- long option, /* Options */
- long number, /* Number of displayed entries */
- wPos_t width, /* Width of list */
- int colCnt, /* Number of columns */
- wPos_t * colWidths, /* Width of columns */
- wBool_t * colRightJust, /* justification of columns */
- const char ** colTitles, /* Title of columns */
- long *valueP, /* Selected index */
- wListCallBack_p action, /* Callback */
- void *data ) /* Context */
-/*
-*/
-{
- wList_p bl;
- long col;
- static wPos_t zeroPos = 0;
-
- bl = (wList_p)gtkAlloc( parent, B_LIST, x, y, labelStr, sizeof *bl, data );
- bl->option = option;
- bl->number = number;
- bl->count = 0;
- bl->last = -1;
- bl->valueP = valueP;
- bl->action = action;
- bl->listX = bl->realX;
-
- if ( colCnt <= 0 ) {
- colCnt = 1;
- colWidths = &zeroPos;
- }
- bl->colCnt = colCnt;
- bl->colWidths = (wPos_t*)malloc( colCnt * sizeof *(wPos_t*)0 );
- memcpy( bl->colWidths, colWidths, colCnt * sizeof *(wPos_t*)0 );
-
- gtkComputePos( (wControl_p)bl );
-
- bl->list = (GtkWidget*)gtk_clist_new( bl->colCnt );
- if (bl->list == 0) abort();
- if (colTitles)
- {
- for (col = 0; col < colCnt; col++)
- gtk_clist_set_column_title(GTK_CLIST(bl->list), col, _(((char*)colTitles[col])));
- gtk_clist_column_titles_show(GTK_CLIST(bl->list));
- }
-
- bl->widget = gtk_scrolled_window_new( NULL, NULL );
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bl->widget),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
- /* gtk_container_add( GTK_CONTAINER(bl->widget), bl->list ); */
- gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(bl->widget), bl->list );
- if (width == 0)
- width = 100;
- for ( col=0; col<colCnt; col++ ) {
- gtk_clist_set_column_auto_resize( GTK_CLIST(bl->list), col, TRUE );
- gtk_clist_set_column_resizeable( GTK_CLIST(bl->list), col, TRUE );
- gtk_clist_set_column_justification( GTK_CLIST(bl->list), col,
- (colRightJust==NULL||colRightJust[col]==FALSE)?GTK_JUSTIFY_LEFT:GTK_JUSTIFY_RIGHT );
- gtk_clist_set_column_width( GTK_CLIST(bl->list), col, bl->colWidths[col] );
- }
-#ifndef GTK1
- gtk_widget_set_size_request( bl->widget, width, (number+1)*ROW_HEIGHT );
-#else
- gtk_widget_set_usize( bl->widget, width, (number+1)*ROW_HEIGHT );
-#endif
- gtk_signal_connect( GTK_OBJECT(bl->list), "select_row", GTK_SIGNAL_FUNC(selectCList), bl );
- gtk_signal_connect( GTK_OBJECT(bl->list), "unselect_row", GTK_SIGNAL_FUNC(unselectCList), bl );
- gtk_signal_connect( GTK_OBJECT(bl->list), "resize_column", GTK_SIGNAL_FUNC(resizeColumnCList), bl );
- gtk_clist_set_selection_mode( GTK_CLIST(bl->list), (option&BL_MANY)?GTK_SELECTION_MULTIPLE:GTK_SELECTION_BROWSE );
- gtk_container_set_focus_vadjustment (GTK_CONTAINER (bl->list),
- gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (bl->widget)));
-
- gtk_widget_show( bl->list );
-
-#ifndef GTK1
- gtk_fixed_put( GTK_FIXED(parent->widget), bl->widget, bl->realX, bl->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), bl->widget );
- gtk_widget_set_uposition( bl->widget, bl->realX, bl->realY );
-#endif
- gtkControlGetSize( (wControl_p)bl );
- if (labelStr)
- bl->labelW = gtkAddLabel( (wControl_p)bl, labelStr );
- gtk_widget_show( bl->widget );
- gtkAddButton( (wControl_p)bl );
- gtkAddHelpString( bl->widget, helpStr );
- return bl;
-}
diff --git a/app/wlib/gtklib/gtkmenu.c b/app/wlib/gtklib/gtkmenu.c
deleted file mode 100644
index d3258c4..0000000
--- a/app/wlib/gtklib/gtkmenu.c
+++ /dev/null
@@ -1,873 +0,0 @@
-/** \file gtkmenu.c
- * Menu creation and handling stuff.
- *
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkmenu.c,v 1.5 2009-10-03 04:49:01 dspagnol Exp $
- */
-
-/* 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 <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <ctype.h>
-
-#include "gtkint.h"
-
-int testMenuPopup = 1;
-
-static char MenuItemDataKey[] = "MenuItemDataKey";
-
-extern char gtkAccelChar;
-
-/*
- *****************************************************************************
- *
- * Menus
- *
- *****************************************************************************
- */
-
-typedef enum { M_MENU, M_SEPARATOR, M_PUSH, M_LIST, M_LISTITEM, M_TOGGLE, M_RADIO } mtype_e;
-typedef enum { MM_BUTT, MM_MENU, MM_BAR, MM_POPUP } mmtype_e;
-
-
-#define MOBJ_COMMON \
- WOBJ_COMMON \
- mtype_e mtype; \
- GtkWidget * menu_item; \
- wMenu_p parentMenu; \
- int recursion;
-
-struct wMenuItem_t {
- MOBJ_COMMON
- };
-typedef struct wMenuItem_t * wMenuItem_p;
-
-struct wMenu_t {
- MOBJ_COMMON
- mmtype_e mmtype;
- wMenuItem_p first, last;
- GSList *radioGroup; /* in case menu holds a radio button group */
- GtkWidget * menu;
- wMenuTraceCallBack_p traceFunc;
- void * traceData;
- GtkLabel * labelG;
- GtkWidget * imageG;
- };
-
-struct wMenuPush_t {
- MOBJ_COMMON
- wMenuCallBack_p action;
- wBool_t enabled;
- };
-
-struct wMenuRadio_t {
- MOBJ_COMMON
- wMenuCallBack_p action;
- wBool_t enabled;
- };
-
-
-typedef struct wMenuListItem_t * wMenuListItem_p;
-
-struct wMenuList_t {
- MOBJ_COMMON
- int max;
- int count;
- wMenuListCallBack_p action;
- };
-
-struct wMenuListItem_t {
- MOBJ_COMMON
- wMenuList_p mlist;
- };
-
-struct wMenuToggle_t {
- MOBJ_COMMON
- wMenuToggleCallBack_p action;
- wBool_t enabled;
- wBool_t set;
- };
-
-
-/*-----------------------------------------------------------------*/
-
-static void pushMenuItem(
- GtkWidget * widget,
- gpointer value )
-{
- wMenuItem_p m = (wMenuItem_p)value;
- wMenuToggle_p mt;
- if (gdk_pointer_is_grabbed()) {
- gdk_pointer_ungrab(0);
- }
-/* wFlush(); */
- if (m->recursion)
- return;
- switch (m->mtype) {
- case M_PUSH:
- if ( ((wMenuPush_p)m)->enabled == FALSE )
- wBeep();
- else
- ((wMenuPush_p)m)->action( ((wMenuPush_p)m)->data );
- break;
- case M_TOGGLE:
- mt = (wMenuToggle_p)m;
- if ( mt->enabled == FALSE ) {
- wBeep();
- } else {
- wMenuToggleSet( mt, !mt->set );
- mt->action( mt->set, mt->data );
- }
- break;
- case M_RADIO:
- /* NOTE: action is only called when radio button is activated, not when deactivated */
- if ( ((wMenuRadio_p)m)->enabled == FALSE )
- wBeep();
- else
- if( ((GtkCheckMenuItem *)widget)->active == TRUE )
- ((wMenuRadio_p)m)->action( ((wMenuRadio_p)m)->data );
- break;
- case M_MENU:
- return;
- default:
- /*fprintf(stderr," Oops menu\n");*/
- return;
- }
- if ( (m->parentMenu)->traceFunc ) {
- (m->parentMenu)->traceFunc( m->parentMenu, m->labelStr, ((wMenu_p)m->parentMenu)->traceData );
- }
-}
-
-static wMenuItem_p createMenuItem(
- wMenu_p m,
- mtype_e mtype,
- const char * helpStr,
- const char * labelStr,
- int size )
-{
- wMenuItem_p mi;
- mi = (wMenuItem_p)gtkAlloc( NULL, B_MENUITEM, 0, 0, labelStr, size, NULL );
- mi->mtype = mtype;
- switch ( mtype ) {
- case M_LIST:
- m->menu_item = NULL;
- break;
- case M_SEPARATOR:
- mi->menu_item = gtk_separator_menu_item_new();
- break;
- case M_TOGGLE:
- mi->menu_item = gtk_check_menu_item_new_with_mnemonic(gtkConvertInput(mi->labelStr));
- break;
- case M_RADIO:
- mi->menu_item = gtk_radio_menu_item_new_with_mnemonic(m->radioGroup, gtkConvertInput(mi->labelStr));
- m->radioGroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (mi->menu_item));
- break;
- default:
- mi->menu_item = gtk_menu_item_new_with_mnemonic(gtkConvertInput(mi->labelStr));
- break;
- }
- if (mi->menu_item) {
- if (m)
- gtk_menu_append( GTK_MENU(m->menu), mi->menu_item );
-
- gtk_signal_connect( GTK_OBJECT(mi->menu_item), "activate",
- GTK_SIGNAL_FUNC(pushMenuItem), mi );
- gtk_widget_show(mi->menu_item);
- }
- if (m) {
- if (m->first == NULL) {
- m->first = mi;
- } else {
- m->last->next = (wControl_p)mi;
- }
- m->last = mi;
- }
- mi->next = NULL;
- if (helpStr != NULL) {
- gtkAddHelpString( mi->menu_item, helpStr );
- }
- mi->parentMenu = m;
- return mi;
-}
-
-
-static void setAcclKey( wWin_p w, GtkWidget * menu, GtkWidget * menu_item, int acclKey )
-{
- char acclStr[40];
- int len;
- int mask;
- static GtkAccelGroup * accel_alpha_group = NULL;
- static GtkAccelGroup * accel_nonalpha_group = NULL;
- guint oldmods;
-
-
- if (accel_alpha_group == NULL) {
- accel_alpha_group = gtk_accel_group_new();
- /*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/
- gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_alpha_group );
- }
- if (accel_nonalpha_group == NULL) {
- oldmods = gtk_accelerator_get_default_mod_mask();
- gtk_accelerator_set_default_mod_mask( GDK_CONTROL_MASK | GDK_MOD1_MASK );
- accel_nonalpha_group = gtk_accel_group_new();
- /*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/
- gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_nonalpha_group );
- gtk_accelerator_set_default_mod_mask( oldmods );
- }
-
- mask = 0;
- if (acclKey) {
-#ifdef LATER
- switch ( (acclKey&0xFF) ) {
- case '+': acclKey = (acclKey&0xFF00) | WSHIFT | '='; break;
- case '?': acclKey = (acclKey&0xFF00) | WSHIFT | '/'; break;
- }
-#endif
- len = 0;
- if (acclKey&WALT) {
- mask |= GDK_MOD1_MASK;
- strcpy( acclStr+len, "Meta+" );
- len += 5;
- }
- if (acclKey&WSHIFT) {
- mask |= GDK_SHIFT_MASK;
- strcpy( acclStr+len, "Shift+" );
- len += 6;
- switch ( (acclKey&0xFF) ) {
- case '0': acclKey += ')'-'0'; break;
- case '1': acclKey += '!'-'1'; break;
- case '2': acclKey += '@'-'2'; break;
- case '3': acclKey += '#'-'3'; break;
- case '4': acclKey += '$'-'4'; break;
- case '5': acclKey += '%'-'5'; break;
- case '6': acclKey += '^'-'6'; break;
- case '7': acclKey += '&'-'7'; break;
- case '8': acclKey += '*'-'8'; break;
- case '9': acclKey += '('-'9'; break;
- case '`': acclKey += '~'-'`'; break;
- case '-': acclKey += '_'-'-'; break;
- case '=': acclKey += '+'-'='; break;
- case '\\': acclKey += '|'-'\\'; break;
- case '[': acclKey += '{'-'['; break;
- case ']': acclKey += '}'-']'; break;
- case ';': acclKey += ':'-';'; break;
- case '\'': acclKey += '"'-'\''; break;
- case ',': acclKey += '<'-','; break;
- case '.': acclKey += '>'-'.'; break;
- case '/': acclKey += '?'-'/'; break;
- default: break;
- }
- }
- if (acclKey&WCTL) {
- mask |= GDK_CONTROL_MASK;
- strcpy( acclStr+len, "Ctrl+" );
- len += 5;
- }
- acclStr[len++] = (acclKey & 0xFF);
- acclStr[len++] = '\0';
- gtk_widget_add_accelerator( menu_item, "activate",
- (isalpha(acclKey&0xFF)?accel_alpha_group:accel_nonalpha_group),
- toupper(acclKey&0xFF), mask, GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED );
- }
-}
-
-/*-----------------------------------------------------------------*/
-
-wMenuRadio_p wMenuRadioCreate(
- wMenu_p m,
- const char * helpStr,
- const char * labelStr,
- long acclKey,
- wMenuCallBack_p action,
- void *data )
-{
- wMenuRadio_p mi;
-
- mi = (wMenuRadio_p)createMenuItem( m, M_RADIO, helpStr, labelStr, sizeof *mi );
- if (m->mmtype == MM_POPUP && !testMenuPopup)
- return mi;
- setAcclKey( m->parent, m->menu, mi->menu_item, acclKey );
- mi->action = action;
- mi->data = data;
- mi->enabled = TRUE;
- return mi;
-}
-
-void wMenuRadioSetActive(
- wMenuRadio_p mi )
-{
- gtk_check_menu_item_set_active( (GtkCheckMenuItem *)mi->menu_item, TRUE );
-}
-
-/*-----------------------------------------------------------------*/
-
-wMenuPush_p wMenuPushCreate(
- wMenu_p m,
- const char * helpStr,
- const char * labelStr,
- long acclKey,
- wMenuCallBack_p action,
- void *data )
-{
- wMenuPush_p mi;
-
- mi = (wMenuPush_p)createMenuItem( m, M_PUSH, helpStr, labelStr, sizeof *mi );
- if (m->mmtype == MM_POPUP && !testMenuPopup)
- return mi;
- setAcclKey( m->parent, m->menu, mi->menu_item, acclKey );
- mi->action = action;
- mi->data = data;
- mi->enabled = TRUE;
- return mi;
-}
-
-
-void wMenuPushEnable(
- wMenuPush_p mi,
- wBool_t enable )
-{
- mi->enabled = enable;
- gtk_widget_set_sensitive( GTK_WIDGET(mi->menu_item), enable );
-}
-
-
-/*-----------------------------------------------------------------*/
-
-wMenu_p wMenuMenuCreate(
- wMenu_p m,
- const char * helpStr,
- const char * labelStr )
-{
- wMenu_p mi;
- mi = (wMenu_p)createMenuItem( m, M_MENU, helpStr, labelStr, sizeof *mi );
- mi->mmtype = MM_MENU;
- mi->menu = gtk_menu_new();
- /*gtk_widget_set_sensitive( GTK_WIDGET(mi->menu_item), FALSE );*/
- gtk_menu_item_set_submenu( GTK_MENU_ITEM(mi->menu_item), mi->menu );
- return mi;
-}
-
-
-/*-----------------------------------------------------------------*/
-
-void wMenuSeparatorCreate(
- wMenu_p m )
-{
- wMenuItem_p mi;
- mi = createMenuItem( m, M_SEPARATOR, NULL, "", sizeof *mi );
-}
-
-
-/*-----------------------------------------------------------------*/
-
-int getMlistOrigin( wMenu_p m, wMenuList_p ml )
-{
- wMenuItem_p mi;
- int count;
- count = 0; /* Menu counts as one */
- for ( mi = m->first; mi != NULL; mi = (wMenuItem_p)mi->next ) {
- switch( mi->mtype ) {
- case M_SEPARATOR:
- case M_PUSH:
- case M_MENU:
- count++;
- break;
- case M_LIST:
- if (mi == (wMenuItem_p)ml)
- return count;
- count += ((wMenuList_p)mi)->count;
- break;
- default:
- /*fprintf(stderr, "Oops: getMlistOrigin\n");*/
- break;
- }
- }
- return count;
-}
-
-wMenuList_p wMenuListCreate(
- wMenu_p m,
- const char * helpStr,
- int max,
- wMenuListCallBack_p action )
-{
- wMenuList_p mi;
- mi = (wMenuList_p)createMenuItem( m, M_LIST, NULL, NULL, sizeof *mi );
- mi->next = NULL;
- mi->count = 0;
- mi->max = max;
- mi->parentMenu = m;
- mi->action = action;
- return (wMenuList_p)mi;
-}
-
-
-static void pushMenuList(
- GtkWidget * widget,
- gpointer value )
-{
- wMenuListItem_p ml = (wMenuListItem_p)value;
- int i;
- int origin;
- GtkWidget * item;
- char * itemLabel;
- GList * children;
- GList * child;
- GtkWidget *label;
-
- if (gdk_pointer_is_grabbed()) {
- gdk_pointer_ungrab(0);
- }
- wFlush();
-
- if (ml->recursion)
- return;
- if (ml->mlist->count <= 0) {
- fprintf( stderr, "pushMenuItem: empty list\n" );
- return;
- }
- if (ml->mlist->action) {
- origin = getMlistOrigin(ml->mlist->parentMenu, ml->mlist);
- children = gtk_container_children( GTK_CONTAINER(ml->mlist->parentMenu->menu) );
- if (children == NULL) abort();
- child = g_list_nth( children, origin );
- for (i=origin; i<origin+ml->mlist->count; i++, child=g_list_next(child) ) {
- if (child == NULL) abort();
- item = (GtkWidget*)child->data;
- if (item == NULL) abort();
- if (item == widget) {
- children = gtk_container_children(GTK_CONTAINER(item));
- label = (GtkWidget*)children->data;
- gtk_label_get( GTK_LABEL(label), &itemLabel );
- ml->mlist->action( i-origin, itemLabel, ml->data );
- return;
- }
- }
- }
- fprintf( stderr, "pushMenuItem: item (%lx) not found\n", (long)widget );
-}
-
-
-void wMenuListAdd(
- wMenuList_p ml,
- int index,
- const char * labelStr,
- const void * data )
-{
- int i;
- int origin;
- GtkWidget * item;
- char * itemLabel;
- GList * children;
- GList * child;
- GList * itemList;
- GtkWidget * label;
- wMenuListItem_p mi;
- char * labelStrConverted;
-
- origin = getMlistOrigin(ml->parentMenu, ml);
- if (ml->count > 0) {
- children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) );
- if (children == NULL) abort();
- child = g_list_nth( children, origin );
- labelStrConverted = gtkConvertInput(labelStr);
- for (i=origin; i<origin+ml->count; i++, child=g_list_next(child) ) {
- if (child == NULL) abort();
- item = (GtkWidget*)child->data;
- if (item == NULL) abort();
- itemList = gtk_container_children(GTK_CONTAINER(item));
- label = (GtkWidget*)itemList->data;
- gtk_label_get( GTK_LABEL(label), &itemLabel );
- if (strcmp( labelStrConverted, itemLabel ) == 0) {
- if (i != ml->count+index) {
- gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item );
- ml->count--;
- break;
- }
- return;
- }
- }
- if (ml->max >= 0 && ml->count >= ml->max) {
- child = g_list_nth( children, origin+ml->count-1 );
- if (child == NULL) abort();
- item = (GtkWidget*)child->data;
- if (item == NULL) abort();
- gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item );
- ml->count--;
- }
- }
- mi = (wMenuListItem_p)gtkAlloc( NULL, B_MENUITEM, 0, 0, labelStr, sizeof *mi, NULL );
- mi->mtype = M_LISTITEM;
- mi->menu_item = gtk_menu_item_new_with_label(gtkConvertInput(mi->labelStr));
- mi->data = (void *)data;
- mi->mlist = ml;
- if (index < 0 || index > ml->count)
- index = ml->count;
- gtk_menu_insert( GTK_MENU(ml->parentMenu->menu), mi->menu_item, origin+index );
- gtk_signal_connect( GTK_OBJECT(mi->menu_item), "activate",
- GTK_SIGNAL_FUNC(pushMenuList), mi );
- gtk_object_set_data( GTK_OBJECT(mi->menu_item), MenuItemDataKey, mi );
- gtk_widget_show(mi->menu_item);
-
- ml->count++;
-}
-
-
-void wMenuListDelete(
- wMenuList_p ml,
- const char * labelStr )
-{
- int i;
- int origin;
- GtkWidget * item;
- char * itemLabel;
- GList * children;
- GList * child;
- GtkWidget * label;
- char * labelStrConverted;
-
- if (ml->count < 0) abort();
- origin = getMlistOrigin(ml->parentMenu, ml);
- children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) );
- if (children == NULL) abort();
- child = g_list_nth( children, origin );
- labelStrConverted = gtkConvertInput( labelStr );
- for (i=origin; i<origin+ml->count; i++, child=g_list_next(child) ) {
- if (child == NULL) abort();
- item = (GtkWidget*)child->data;
- if (item == NULL) abort();
- children = gtk_container_children(GTK_CONTAINER(item));
- label = (GtkWidget*)children->data;
- gtk_label_get( GTK_LABEL(label), &itemLabel );
- if (strcmp( labelStrConverted, itemLabel ) == 0) {
- gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item );
- gtk_widget_queue_resize( GTK_WIDGET(ml->parentMenu->menu) );
- ml->count--;
- return;
- }
- }
-}
-
-
-const char * wMenuListGet( wMenuList_p ml, int index, void ** data )
-{
- int origin;
- GtkWidget * item;
- GList * children;
- GList * child;
- GtkWidget * label;
- char * itemLabel;
- wMenuListItem_p mi;
-
- if (ml->count <= 0)
- return NULL;
-
- if (index >= ml->count) {
- if (data)
- *data = NULL;
- return NULL;
- }
- origin = getMlistOrigin(ml->parentMenu, ml);
- children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) );
- if (children == NULL) abort();
- child = g_list_nth( children, origin+index );
- if (child == NULL) abort();
- item = (GtkWidget*)child->data;
- if (item == NULL) abort();
- children = gtk_container_children(GTK_CONTAINER(item));
- label = (GtkWidget*)children->data;
- gtk_label_get( GTK_LABEL(label), &itemLabel );
- if (data) {
- mi = (wMenuListItem_p)gtk_object_get_data( GTK_OBJECT(item), MenuItemDataKey );
- if (mi)
- *data = mi->data;
- }
- return itemLabel;
-}
-
-
-void wMenuListClear(
- wMenuList_p ml )
-{
- int i;
- int origin;
- GtkWidget * item;
- GList * children;
- GList * child;
-
- if (ml->count == 0)
- return;
- origin = getMlistOrigin(ml->parentMenu, ml);
- children = gtk_container_children( GTK_CONTAINER(ml->parentMenu->menu) );
- if (children == NULL) abort();
- child = g_list_nth( children, origin );
- for (i=origin; i<origin+ml->count; i++, child=g_list_next(child) ) {
- if (child == NULL) abort();
- item = (GtkWidget*)child->data;
- if (item == NULL) abort();
- gtk_container_remove( GTK_CONTAINER(ml->parentMenu->menu), item );
- }
- ml->count = 0;
- gtk_widget_queue_resize( GTK_WIDGET(ml->parentMenu->menu) );
-}
-/*-----------------------------------------------------------------*/
-
-wMenuToggle_p wMenuToggleCreate(
- wMenu_p m,
- const char * helpStr,
- const char * labelStr,
- long acclKey,
- wBool_t set,
- wMenuToggleCallBack_p action,
- void * data )
-{
- wMenuToggle_p mt;
-
- mt = (wMenuToggle_p)createMenuItem( m, M_TOGGLE, helpStr, labelStr, sizeof *mt );
- setAcclKey( m->parent, m->menu, mt->menu_item, acclKey );
- mt->action = action;
- mt->data = data;
- mt->enabled = TRUE;
- mt->parentMenu = m;
- wMenuToggleSet( mt, set );
-
- return mt;
-}
-
-
-wBool_t wMenuToggleGet(
- wMenuToggle_p mt )
-{
- return mt->set;
-}
-
-
-wBool_t wMenuToggleSet(
- wMenuToggle_p mt,
- wBool_t set )
-{
- wBool_t rc;
- if (mt==NULL) return 0;
- mt->recursion++;
- gtk_check_menu_item_set_state( GTK_CHECK_MENU_ITEM(mt->menu_item), set );
- mt->recursion--;
- rc = mt->set;
- mt->set = set;
- return rc;
-}
-
-
-void wMenuToggleEnable(
- wMenuToggle_p mt,
- wBool_t enable )
-{
- mt->enabled = enable;
-}
-
-
-/*-----------------------------------------------------------------*/
-
-void wMenuSetLabel( wMenu_p m, const char * labelStr) {
- gtkSetLabel( m->widget, m->option, labelStr, &m->labelG, &m->imageG );
-}
-
-
-static gint pushMenu(
- GtkWidget * widget,
- wMenu_p m )
-{
- gtk_menu_popup( GTK_MENU(m->menu), NULL, NULL, NULL, NULL, 0, 0 );
- /* Tell calling code that we have handled this event; the buck
- * stops here. */
- return TRUE;
-}
-
-
-wMenu_p wMenuCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- long option )
-{
- wMenu_p m;
- m = gtkAlloc( parent, B_MENU, x, y, labelStr, sizeof *m, NULL );
- m->mmtype = MM_BUTT;
- m->option = option;
- m->traceFunc = NULL;
- m->traceData = NULL;
- gtkComputePos( (wControl_p)m );
-
- m->widget = gtk_button_new();
- gtk_signal_connect (GTK_OBJECT(m->widget), "clicked",
- GTK_SIGNAL_FUNC(pushMenu), m );
-
- m->menu = gtk_menu_new();
-
- wMenuSetLabel( m, labelStr );
-#ifdef MENUOPTION
- gtk_option_menu_set_menu( GTK_OPTION_MENU(m->widget), m->menu );
- ((GtkOptionMenu*)m->widget)->width = 25;
- ((GtkOptionMenu*)m->widget)->height = 16;
-#endif
-
- gtk_fixed_put( GTK_FIXED(parent->widget), m->widget, m->realX, m->realY );
- gtkControlGetSize( (wControl_p)m );
- if ( m->w < 80 && (m->option&BO_ICON)==0) {
- m->w = 80;
- gtk_widget_set_usize( m->widget, m->w, m->h );
- }
- gtk_widget_show( m->widget );
- gtkAddButton( (wControl_p)m );
- gtkAddHelpString( m->widget, helpStr );
- return m;
-}
-
-/**
- * Add a drop-down menu to the menu bar.
- *
- * \param[IN] w main window handle
- * \param[IN] helpStr unused (should be help topic )
- * \param[IN] labelStr label for the drop-down menu
- * \return pointer to the created drop-down menu
- */
-
-
-wMenu_p wMenuBarAdd(
- wWin_p w,
- const char * helpStr,
- const char * labelStr )
-{
- wMenu_p m;
- GtkWidget * menuItem;
- static GtkAccelGroup * accel_group = NULL;
-
- m = gtkAlloc( w, B_MENU, 0, 0, labelStr, sizeof *m, NULL );
- m->mmtype = MM_BAR;
- m->realX = 0;
- m->realY = 0;
-
- menuItem = gtk_menu_item_new_with_label( gtkConvertInput(m->labelStr) );
- m->menu = gtk_menu_new();
- gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), m->menu );
- gtk_menu_bar_append( GTK_MENU_BAR(w->menubar), menuItem );
- gtk_widget_show( menuItem );
-
- m->w = 0;
- m->h = 0;
-
- /* TODO: why is help not supported here? */
- /*gtkAddHelpString( m->panel_item, helpStr );*/
-
- if ( gtkAccelChar ) {
- if ( accel_group == NULL ) {
- accel_group = gtk_accel_group_new();
- gtk_window_add_accel_group( GTK_WINDOW(w->gtkwin), accel_group );
- }
- gtk_widget_add_accelerator( menuItem, "activate", accel_group, tolower(gtkAccelChar), GDK_MOD1_MASK, GTK_ACCEL_LOCKED );
- }
- return m;
-}
-
-
-/*-----------------------------------------------------------------*/
-
-
-wMenu_p wMenuPopupCreate(
- wWin_p w,
- const char * labelStr )
-{
- wMenu_p b;
- b = gtkAlloc( w, B_MENU, 0, 0, labelStr, sizeof *b, NULL );
- b->mmtype = MM_POPUP;
- b->option = 0;
-
- b->menu = gtk_menu_new();
- b->w = 0;
- b->h = 0;
- gtk_signal_connect( GTK_OBJECT (b->menu), "key_press_event",
- GTK_SIGNAL_FUNC (catch_shift_ctrl_alt_keys), b);
- gtk_signal_connect( GTK_OBJECT (b->menu), "key_release_event",
- GTK_SIGNAL_FUNC (catch_shift_ctrl_alt_keys), b);
- gtk_widget_set_events ( GTK_WIDGET(b->menu), GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK );
- return b;
-}
-
-
-void wMenuPopupShow( wMenu_p mp )
-{
- gtk_menu_popup( GTK_MENU(mp->menu), NULL, NULL, NULL, NULL, 0, 0 );
-}
-
-
-/*-----------------------------------------------------------------*/
-
-void wMenuSetTraceCallBack(
- wMenu_p m,
- wMenuTraceCallBack_p func,
- void * data )
-{
- m->traceFunc = func;
- m->traceData = data;
-}
-
-wBool_t wMenuAction(
- wMenu_p m,
- const char * label )
-{
- wMenuItem_p mi;
- wMenuToggle_p mt;
- for ( mi = m->first; mi != NULL; mi = (wMenuItem_p)mi->next ) {
- if ( strcmp( mi->labelStr, label ) == 0 ) {
- switch( mi->mtype ) {
- case M_SEPARATOR:
- break;
- case M_PUSH:
- if ( ((wMenuPush_p)mi)->enabled == FALSE )
- wBeep();
- else
- ((wMenuPush_p)mi)->action( ((wMenuPush_p)mi)->data );
- break;
- case M_TOGGLE:
- mt = (wMenuToggle_p)mi;
- if ( mt->enabled == FALSE ) {
- wBeep();
- } else {
- wMenuToggleSet( mt, !mt->set );
- mt->action( mt->set, mt->data );
- }
- break;
- case M_MENU:
- break;
- case M_LIST:
- break;
- default:
- /*fprintf(stderr, "Oops: wMenuAction\n");*/
- break;
- }
- return TRUE;
- }
- }
- return FALSE;
-}
diff --git a/app/wlib/gtklib/gtkmisc.c b/app/wlib/gtklib/gtkmisc.c
deleted file mode 100644
index acc123a..0000000
--- a/app/wlib/gtklib/gtkmisc.c
+++ /dev/null
@@ -1,1210 +0,0 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkmisc.c,v 1.15 2009-10-03 04:49:01 dspagnol Exp $
- */
-
-/* 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 <stdlib.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <locale.h>
-
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-
-#include "gtkint.h"
-#include "i18n.h"
-
-wWin_p gtkMainW;
-
-long debugWindow = 0;
-
-char wAppName[256];
-char wConfigName[ 256 ];
-
-#define FOUR (4)
-#ifndef GTK1
-#define MENUH (24)
-#else
-#define MENUH (24)
-#endif
-#define LABEL_OFFSET (3)
-
-const char * wNames[] = {
- "MAIN",
- "POPUP",
- "BUTT",
- "CANCEL",
- "POPUP",
- "TEXT",
- "INTEGER",
- "FLOAT",
- "LIST",
- "DROPLIST",
- "COMBOLIST",
- "RADIO",
- "TOGGLE",
- "DRAW",
- "MENU"
- "MULTITEXT",
- "MESSAGE",
- "LINES",
- "MENUITEM",
- "BOX"
- };
-
-static struct timeval startTime;
-
-static wBool_t reverseIcon =
-#if defined(linux)
- FALSE;
-#else
- TRUE;
-#endif
-
-char gtkAccelChar;
-
-
-/*
- *****************************************************************************
- *
- * Internal Utility functions
- *
- *****************************************************************************
- */
-
-unsigned char gtkBitrotate(
- char v )
-{
- unsigned char r = 0;
- int i;
- static unsigned char bits[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
- for (i=0;i<8;i++)
- if (v & bits[i])
- r |= bits[7-i];
- return r;
-}
-
-GdkPixmap* gtkMakeIcon(
- GtkWidget * widget,
- wIcon_p ip,
- GdkBitmap ** mask )
-{
- GdkPixmap * pixmap;
- char ** pixmapData;
- char * oldline1;
- static char newline1[] = " \tc None s None";
- char line0[40];
- char line2[40];
- int row,col,wb;
- long rgb;
- const char * bits;
- GdkColor *transparent;
-
- transparent = &gtk_widget_get_style( gtkMainW->gtkwin )->bg[GTK_WIDGET_STATE( gtkMainW->gtkwin )];
-
- if ( ip->gtkIconType == gtkIcon_pixmap ) {
- pixmap = gdk_pixmap_create_from_xpm_d( gtkMainW->gtkwin->window, mask, transparent, (char**)ip->bits );
- }
- else {
- wb = (ip->w+7)/8;
- pixmapData = (char**)malloc( (3+ip->h) * sizeof *pixmapData );
- pixmapData[0] = line0;
- rgb = wDrawGetRGB(ip->color);
- sprintf( line0, " %d %d 2 1", ip->w, ip->h );
- sprintf( line2, "# c #%2.2lx%2.2lx%2.2lx", (rgb>>16)&0xFF, (rgb>>8)&0xFF, rgb&0xFF );
- pixmapData[1] = ". c None s None";
- pixmapData[2] = line2;
- bits = ip->bits;
- for (row = 0; row<ip->h; row++ ) {
- pixmapData[row+3] = (char*)malloc( (ip->w+1) * sizeof **pixmapData );
- for (col = 0; col<ip->w; col++ ) {
- if ( bits[ row*wb+(col>>3) ] & (1<<(col&07)) ) {
- pixmapData[row+3][col] = '#';
- } else {
- pixmapData[row+3][col] = '.';
- }
- }
- pixmapData[row+3][ip->w] = 0;
- }
- pixmap = gdk_pixmap_create_from_xpm_d( gtkMainW->gtkwin->window, mask, transparent, pixmapData );
- for (row = 0; row<ip->h; row++ ) {
- free( pixmapData[row+3] );
- }
- }
- return pixmap;
-}
-
-
-int gtkAddLabel( wControl_p b, const char * labelStr )
-{
- GtkRequisition requisition;
- if (labelStr == NULL)
- return 0;
- b->label = gtk_label_new(gtkConvertInput(labelStr));
- gtk_widget_size_request( b->label, &requisition );
- gtk_container_add( GTK_CONTAINER(b->parent->widget), b->label );
-#ifndef GTK1
- gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-requisition.width-8, b->realY+LABEL_OFFSET );
-#else
- gtk_widget_set_uposition( b->label, b->realX-requisition.width-8, b->realY+LABEL_OFFSET );
-#endif
- gtk_widget_show( b->label );
- return requisition.width+8;
-}
-
-
-void * gtkAlloc(
- wWin_p parent,
- wType_e type,
- wPos_t origX,
- wPos_t origY,
- const char * labelStr,
- int size,
- void * data )
-{
- wControl_p w = (wControl_p)malloc( size );
- char * cp;
- memset( w, 0, size );
- if (w == NULL)
- abort();
- w->type = type;
- w->parent = parent;
- w->origX = origX;
- w->origY = origY;
- gtkAccelChar = 0;
- if (labelStr) {
- cp = (char*)malloc(strlen(labelStr)+1);
- w->labelStr = cp;
- for ( ; *labelStr; labelStr++ )
- if ( *labelStr != '&' )
- *cp++ = *labelStr;
- else {
-/* *cp++ = '_';
- gtkAccelChar = labelStr[1]; */
- }
- *cp = 0;
- }
- w->doneProc = NULL;
- w->data = data;
- return w;
-}
-
-
-void gtkComputePos(
- wControl_p b )
-{
- wWin_p w = b->parent;
-
- if (b->origX >= 0)
- b->realX = b->origX;
- else
- b->realX = w->lastX + (-b->origX) - 1;
- if (b->origY >= 0)
- b->realY = b->origY + FOUR + ((w->option&F_MENUBAR)?MENUH:0);
- else
- b->realY = w->lastY + (-b->origY) - 1;
-}
-
-
-void gtkControlGetSize(
- wControl_p b )
-{
- GtkRequisition requisition;
- gtk_widget_size_request( b->widget, &requisition );
- b->w = requisition.width;
- b->h = requisition.height;
-}
-
-
-void gtkAddButton(
- wControl_p b )
-{
- wWin_p win = b->parent;
- wBool_t resize = FALSE;
- if (win->first == NULL) {
- win->first = b;
- } else {
- win->last->next = b;
- }
- win->last = b;
- b->next = NULL;
- b->parent = win;
- win->lastX = b->realX + b->w;
- win->lastY = b->realY + b->h;
- if (win->option&F_AUTOSIZE) {
- if (win->lastX > win->realX) {
- win->realX = win->lastX;
- if (win->w != (win->realX + win->origX)) {
- resize = TRUE;
- win->w = (win->realX + win->origX);
- }
- }
- if (win->lastY > win->realY) {
- win->realY = win->lastY;
- if (win->h != (win->realY + win->origY)) {
- resize = TRUE;
- win->h = (win->realY + win->origY);
- }
- }
- if (win->shown) {
- if ( resize ) {
-#ifndef GTK1
- gtk_widget_set_size_request( win->gtkwin, win->w, win->h );
- gtk_widget_set_size_request( win->widget, win->w, win->h );
-#else
- gtk_widget_set_usize( win->gtkwin, win->w, win->h );
- gtk_widget_set_usize( win->widget, win->w, win->h );
-#endif
- }
- }
- }
-}
-
-
-void gtkSetReadonly( wControl_p b, wBool_t ro )
-{
- if (ro)
- b->option |= BO_READONLY;
- else
- b->option &= ~BO_READONLY;
-}
-
-
-wControl_p gtkGetControlFromPos(
- wWin_p win,
- wPos_t x,
- wPos_t y )
-{
- wControl_p b;
- wPos_t xx, yy;
- for (b=win->first; b != NULL; b = b->next) {
- if ( b->widget && GTK_WIDGET_VISIBLE(b->widget) ) {
- xx = b->realX;
- yy = b->realY;
- if ( xx <= x && x < xx+b->w &&
- yy <= y && y < yy+b->h ) {
- return b;
- }
- }
- }
- return NULL;
-}
-
-/* \brief Convert label string from Windows mnemonic to GTK
- *
- * The first occurence of '&' in the passed string is changed to '_'
- *
- * \param label the string to convert
- * \return pointer to modified string, has to be free'd after usage
- *
- */
-static
-char * gtkChgMnemonic( char *label )
-{
- char *ptr;
- char *cp;
-
- cp = strdup( label );
-
- ptr = strchr( cp, '&' );
- if( ptr )
- *ptr = '_';
-
- return( cp );
-}
-
-
-/*
- *****************************************************************************
- *
- * Exported Utility Functions
- *
- *****************************************************************************
- */
-
-EXPORT void wBeep(
- void )
-/*
-Beep!
-*/
-{
- gdk_display_beep(gdk_display_get_default());
-}
-
-typedef struct {
- GtkWidget * win;
- GtkWidget * label;
- GtkWidget * butt[3];
- } notice_win;
-static notice_win noticeW;
-static long noticeValue;
-
-static void doNotice(
- GtkWidget * widget,
- long value )
-{
- noticeValue = value;
- gtk_widget_destroy( noticeW.win );
- gtkDoModal( NULL, FALSE );
-}
-
-/**
- * Show a notification window with a yes/no reply and an icon.
- *
- * \param type IN type of message: Information, Warning, Error
- * \param msg IN message to display
- * \param yes IN text for accept button
- * \param no IN text for cancel button
- * \return True when accept was selected, false otherwise
- */
-
-int wNoticeEx( int type,
- const char * msg,
- const char * yes,
- const char * no )
-{
-
- int res;
- unsigned flag;
- char *headline;
- GtkWidget *dialog;
- GtkWindow *parent = GTK_WINDOW_TOPLEVEL;
-
- switch( type ) {
- case NT_INFORMATION:
- flag = GTK_MESSAGE_INFO;
- headline = _("Information");
- break;
- case NT_WARNING:
- flag = GTK_MESSAGE_WARNING;
- headline = _("Warning");
- break;
- case NT_ERROR:
- flag = GTK_MESSAGE_ERROR;
- headline = _("Error");
- break;
- }
-
- if( gtkMainW )
- parent = GTK_WINDOW( gtkMainW->gtkwin);
-
- dialog = gtk_message_dialog_new( parent,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- flag,
- ((no==NULL)?GTK_BUTTONS_OK:GTK_BUTTONS_YES_NO),
- "%s", msg );
- gtk_window_set_title( GTK_WINDOW(dialog), headline );
-
- res = gtk_dialog_run( GTK_DIALOG(dialog));
- gtk_widget_destroy( dialog );
-
- return res == GTK_RESPONSE_OK || res == GTK_RESPONSE_YES;
-}
-
-
-EXPORT int wNotice(
- const char * msg, /* Message */
- const char * yes, /* First button label */
- const char * no ) /* Second label (or 'NULL') */
-/*
-Popup up a notice box with one or two buttons.
-When this notice box is displayed the application is paused and
-will not response to other actions.
-
-Pushing the first button returns 'TRUE'.
-Pushing the second button (if present) returns 'FALSE'.
-*/
-{
- return wNotice3( msg, yes, no, NULL );
-}
-
-/** \brief Popup a notice box with three buttons.
- *
- * Popup up a notice box with three buttons.
- * When this notice box is displayed the application is paused and
- * will not response to other actions.
- *
- * Pushing the first button returns 1
- * Pushing the second button returns 0
- * Pushing the third button returns -1
- *
- * \param msg Text to display in message box
- * \param yes First button label
- * \param no Second label (or 'NULL')
- * \param cancel Third button label (or 'NULL')
- *
- * \returns 1, 0 or -1
- */
-
-EXPORT int wNotice3(
- const char * msg, /* Message */
- const char * affirmative, /* First button label */
- const char * cancel, /* Second label (or 'NULL') */
- const char * alternate )
-{
- notice_win *nw;
- GtkWidget * vbox;
- GtkWidget * hbox;
- GtkWidget * hbox1;
- GtkWidget * image;
- nw = &noticeW;
-
- char *aff = NULL;
- char *can = NULL;
- char *alt = NULL;
-
-#ifndef GTK1
- nw->win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
- /*gtk_window_set_decorated( GTK_WINDOW(nw->win), FALSE );*/
-#else
- nw->win = gtk_window_new( GTK_WINDOW_DIALOG );
-#endif
- gtk_window_position( GTK_WINDOW(nw->win), GTK_WIN_POS_CENTER );
- gtk_container_set_border_width (GTK_CONTAINER (nw->win), 0);
- gtk_window_set_resizable (GTK_WINDOW (nw->win), FALSE);
- gtk_window_set_modal (GTK_WINDOW (nw->win), TRUE);
- gtk_window_set_type_hint (GTK_WINDOW (nw->win), GDK_WINDOW_TYPE_HINT_DIALOG);
-
- vbox = gtk_vbox_new( FALSE, 12 );
- gtk_widget_show( vbox );
- gtk_container_add( GTK_CONTAINER(nw->win), vbox );
- gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
-
- hbox = gtk_hbox_new( FALSE, 12 );
- gtk_box_pack_start( GTK_BOX(vbox), hbox, TRUE, TRUE, 0 );
- gtk_widget_show(hbox);
-
- image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
- gtk_widget_show (image);
- gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0);
- gtk_misc_set_alignment (GTK_MISC (image), 0, 0);
-
- /* create the text label, allow GTK to wrap and allow for markup (for future enhancements) */
- nw->label = gtk_label_new(msg);
- gtk_widget_show( nw->label );
- gtk_box_pack_end (GTK_BOX (hbox), nw->label, TRUE, TRUE, 0);
- gtk_label_set_use_markup (GTK_LABEL (nw->label), FALSE);
- gtk_label_set_line_wrap (GTK_LABEL (nw->label), TRUE);
- gtk_misc_set_alignment (GTK_MISC (nw->label), 0, 0);
-
- /* this hbox will include the button bar */
- hbox1 = gtk_hbox_new (TRUE, 0);
- gtk_widget_show (hbox1);
- gtk_box_pack_start (GTK_BOX (vbox), hbox1, FALSE, TRUE, 0);
-
- /* add the respective buttons */
- aff = gtkChgMnemonic( (char *) affirmative);
- nw->butt[ 0 ] = gtk_button_new_with_mnemonic (aff);
- gtk_widget_show (nw->butt[ 0 ]);
- gtk_box_pack_end (GTK_BOX (hbox1), nw->butt[ 0 ], TRUE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 0 ]), 3);
- gtk_signal_connect( GTK_OBJECT(nw->butt[0]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)1 );
- GTK_WIDGET_SET_FLAGS (nw->butt[ 0 ], GTK_CAN_DEFAULT);
-
- if( cancel ) {
- can = gtkChgMnemonic( (char *) cancel);
- nw->butt[ 1 ] = gtk_button_new_with_mnemonic (can);
- gtk_widget_show (nw->butt[ 1 ]);
- gtk_box_pack_end (GTK_BOX (hbox1), nw->butt[ 1 ], TRUE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 1 ]), 3);
- gtk_signal_connect( GTK_OBJECT(nw->butt[1]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)0 );
- GTK_WIDGET_SET_FLAGS (nw->butt[ 1 ], GTK_CAN_DEFAULT);
-
- if( alternate ) {
- alt = gtkChgMnemonic( (char *) alternate);
- nw->butt[ 2 ] = gtk_button_new_with_mnemonic (alt);
- gtk_widget_show (nw->butt[ 2 ]);
- gtk_box_pack_start (GTK_BOX (hbox1), nw->butt[ 2 ], TRUE, TRUE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (nw->butt[ 2 ]), 3);
- gtk_signal_connect( GTK_OBJECT(nw->butt[2]), "clicked", GTK_SIGNAL_FUNC(doNotice), (void*)-1 );
- GTK_WIDGET_SET_FLAGS (nw->butt[ 2 ], GTK_CAN_DEFAULT);
- }
- }
-
- gtk_widget_grab_default (nw->butt[ 0 ]);
- gtk_widget_grab_focus (nw->butt[ 0 ]);
-
- gtk_widget_show( nw->win );
-
- if ( gtkMainW ) {
- gtk_window_set_transient_for( GTK_WINDOW(nw->win), GTK_WINDOW( gtkMainW->gtkwin) );
-/* gdk_window_set_group( nw->win->window, gtkMainW->gtkwin->window ); */
- }
- gtkDoModal( NULL, TRUE );
-
- if( aff )
- free( aff );
-
- if( can )
- free( can );
-
- if( alt )
- free( alt );
-
- return noticeValue;
-}
-
-
-EXPORT void wFlush(
- void )
-/*
-Flushs all commands to the Window.
-*/
-{
- while ( gtk_events_pending() )
- gtk_main_iteration();
-
- gdk_display_sync(gdk_display_get_default());
-}
-
-
-void wWinTop( wWin_p win )
-{
-}
-
-
-void wSetCursor( wCursor_t cursor )
-{
-}
-
-
-const char * wMemStats( void )
-{
-#ifdef LATER
- static char msg[80];
- struct mstats stats;
- stats = mstats();
- sprintf( msg, "Total %d, used %d(%d), free %d(%d)",
- stats.bytes_total,
- stats.bytes_used, stats.chunks_used,
- stats.bytes_free, stats.chunks_free );
- return msg;
-#else
- return "No stats available";
-#endif
-}
-
-
-wBool_t wCheckExecutable( void )
-{
- return TRUE;
-}
-
-
-void wGetDisplaySize( wPos_t * w, wPos_t * h )
-{
-
- *w = gdk_screen_width();
- *h = gdk_screen_height();
-}
-
-
-wIcon_p wIconCreateBitMap( wPos_t w, wPos_t h, const char * bits, wDrawColor color )
-{
- wIcon_p ip;
- ip = (wIcon_p)malloc( sizeof *ip );
- ip->gtkIconType = gtkIcon_bitmap;
- ip->w = w;
- ip->h = h;
- ip->color = color;
- ip->bits = bits;
- return ip;
-}
-
-wIcon_p wIconCreatePixMap( char *pm[] )
-{
- wIcon_p ip;
- ip = (wIcon_p)malloc( sizeof *ip );
- ip->gtkIconType = gtkIcon_pixmap;
- ip->w = 0;
- ip->h = 0;
- ip->color = 0;
- ip->bits = pm;
- return ip;
-}
-
-
-void wIconSetColor( wIcon_p ip, wDrawColor color )
-{
- ip->color = color;
-}
-
-void wConvertToCharSet( char * buffPtr, int buffMax )
-{
-}
-
-
-void wConvertFromCharSet( char * buffPtr, int buffMax )
-{
-}
-
-static dynArr_t conversionBuffer_da;
-#define convesionBuffer(N) DYNARR_N( char, conversionBuffer_da, N )
-
-char * gtkConvertInput( const char * inString )
-{
-#ifndef GTK1
- const char * cp;
- char * cq;
- int extCharCnt, inCharCnt;
-
- /* Already UTF-8 encoded? */
- if (g_utf8_validate(inString, -1, NULL))
- /* Yes, do not double-convert */
- return (char*)inString;
-#ifdef VERBOSE
- fprintf(stderr, "gtkConvertInput(%s): Invalid UTF-8, converting...\n", inString);
-#endif
-
- for ( cp=inString, extCharCnt=0; *cp; cp++ ) {
- if ( ((*cp)&0x80) != 0 )
- extCharCnt++;
- }
- inCharCnt = cp-inString;
- if ( extCharCnt == 0 )
- return (char*)inString;
- DYNARR_SET( char, conversionBuffer_da, inCharCnt+extCharCnt+1 );
- for ( cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++ ) {
- if ( ((*cp)&0x80) != 0 ) {
- *cq++ = 0xC0+(((*cp)&0xC0)>>6);
- *cq++ = 0x80+((*cp)&0x3F);
- } else {
- *cq++ = *cp;
- }
- }
- *cq = 0;
- return (char*)conversionBuffer_da.ptr;
-#else
- return (char*)inString;
-#endif
-}
-
-
-char * gtkConvertOutput( const char * inString )
-{
-#ifndef GTK1
- const char * cp;
- char * cq;
- int extCharCnt, inCharCnt;
- for ( cp=inString, extCharCnt=0; *cp; cp++ ) {
- if ( ((*cp)&0xC0) == 0x80 )
- extCharCnt++;
- }
- inCharCnt = cp-inString;
- if ( extCharCnt == 0 )
- return (char*)inString;
- DYNARR_SET( char, conversionBuffer_da, inCharCnt+1 );
- for ( cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++ ) {
- if ( ((*cp)&0x80) != 0 ) {
- *cq++ = 0xC0+(((*cp)&0xC0)>>6);
- *cq++ = 0x80+((*cp)&0x3F);
- } else {
- *cq++ = *cp;
- }
- }
- *cq = 0;
- return (char*)conversionBuffer_da.ptr;
-#else
- return (char*)inString;
-#endif
-}
-
-/*-----------------------------------------------------------------*/
-
-typedef struct accelData_t {
- wAccelKey_e key;
- int modifier;
- wAccelKeyCallBack_p action;
- void * data;
- } accelData_t;
-static dynArr_t accelData_da;
-#define accelData(N) DYNARR_N( accelData_t, accelData_da, N )
-
-
-static guint accelKeyMap[] = {
- 0, /* wAccelKey_None, */
- GDK_Delete, /* wAccelKey_Del, */
- GDK_Insert, /* wAccelKey_Ins, */
- GDK_Home, /* wAccelKey_Home, */
- GDK_End, /* wAccelKey_End, */
- GDK_Page_Up, /* wAccelKey_Pgup, */
- GDK_Page_Down, /* wAccelKey_Pgdn, */
- GDK_Up, /* wAccelKey_Up, */
- GDK_Down, /* wAccelKey_Down, */
- GDK_Right, /* wAccelKey_Right, */
- GDK_Left, /* wAccelKey_Left, */
- GDK_BackSpace, /* wAccelKey_Back, */
- GDK_F1, /* wAccelKey_F1, */
- GDK_F2, /* wAccelKey_F2, */
- GDK_F3, /* wAccelKey_F3, */
- GDK_F4, /* wAccelKey_F4, */
- GDK_F5, /* wAccelKey_F5, */
- GDK_F6, /* wAccelKey_F6, */
- GDK_F7, /* wAccelKey_F7, */
- GDK_F8, /* wAccelKey_F8, */
- GDK_F9, /* wAccelKey_F9, */
- GDK_F10, /* wAccelKey_F10, */
- GDK_F11, /* wAccelKey_F11, */
- GDK_F12 /* wAccelKey_F12, */
- };
-
-
-EXPORT void wAttachAccelKey(
- wAccelKey_e key,
- int modifier,
- wAccelKeyCallBack_p action,
- void * data )
-{
- accelData_t * ad;
- if ( key < 1 || key > wAccelKey_F12 ) {
- fprintf( stderr, "wAttachAccelKey(%d) out of range\n", (int)key );
- return;
- }
- DYNARR_APPEND( accelData_t, accelData_da, 10 );
- ad = &accelData(accelData_da.cnt-1);
- ad->key = key;
- ad->modifier = modifier;
- ad->action = action;
- ad->data = data;
-}
-
-
-EXPORT struct accelData_t * gtkFindAccelKey(
- GdkEventKey * event )
-{
- accelData_t * ad;
- int modifier = 0;
- if ( ( event->state & GDK_SHIFT_MASK ) )
- modifier |= WKEY_SHIFT;
- if ( ( event->state & GDK_CONTROL_MASK ) )
- modifier |= WKEY_CTRL;
- if ( ( event->state & GDK_MOD1_MASK ) )
- modifier |= WKEY_ALT;
- for ( ad=&accelData(0); ad<&accelData(accelData_da.cnt); ad++ )
- if ( event->keyval == accelKeyMap[ad->key] &&
- modifier == ad->modifier )
- return ad;
- return NULL;
-}
-
-
-EXPORT wBool_t gtkHandleAccelKey(
- GdkEventKey *event )
-{
- accelData_t * ad = gtkFindAccelKey( event );
- if ( ad ) {
- ad->action( ad->key, ad->data );
- return TRUE;
- }
- return FALSE;
-}
-
-/*
- *****************************************************************************
- *
- * Timer Functions
- *
- *****************************************************************************
- */
-
-static wBool_t gtkPaused = FALSE;
-static int alarmTimer = 0;
-
-static gint doAlarm(
- gpointer data )
-{
- wAlarmCallBack_p func = (wAlarmCallBack_p)data;
- if (alarmTimer)
- gtk_timeout_remove( alarmTimer );
- func();
- alarmTimer = 0;
- return 0;
-}
-
-
-EXPORT void wAlarm(
- long count,
- wAlarmCallBack_p func ) /* milliseconds */
-/*
-Alarm for <count> milliseconds.
-*/
-{
- gtkPaused = TRUE;
- if (alarmTimer)
- gtk_timeout_remove( alarmTimer );
- alarmTimer = gtk_timeout_add( count, doAlarm, (void *) (GtkFunction)func );
-}
-
-
-static wControl_p triggerControl = NULL;
-static setTriggerCallback_p triggerFunc = NULL;
-
-static void doTrigger( void )
-{
- if (triggerControl && triggerFunc) {
- triggerFunc( triggerControl );
- triggerFunc = NULL;
- triggerControl = NULL;
- }
-}
-
-void gtkSetTrigger(
- wControl_p b,
- setTriggerCallback_p trigger )
-{
- triggerControl = b;
- triggerFunc = trigger;
- wAlarm( 500, doTrigger );
-}
-
-
-EXPORT void wPause(
- long count ) /* milliseconds */
-/*
-Pause for <count> milliseconds.
-*/
-{
- struct timeval timeout;
- sigset_t signal_mask;
- sigset_t oldsignal_mask;
-
- gdk_display_sync(gdk_display_get_default());
-
- timeout.tv_sec = count/1000;
- timeout.tv_usec = (count%1000)*1000;
-
- sigemptyset( &signal_mask );
- sigaddset( &signal_mask, SIGIO );
- sigaddset( &signal_mask, SIGALRM );
- sigprocmask( SIG_BLOCK, &signal_mask, &oldsignal_mask );
-
- if (select( 0, NULL, NULL, NULL, &timeout ) == -1) {
- perror("wPause:select");
- }
- sigprocmask( SIG_BLOCK, &oldsignal_mask, NULL );
-}
-
-
-unsigned long wGetTimer( void )
-{
- struct timeval tv;
- struct timezone tz;
- int rc;
- rc = gettimeofday( &tv, &tz );
- return (tv.tv_sec-startTime.tv_sec+1) * 1000 + tv.tv_usec /1000;
-}
-
-
-
-/**
- * Add control to circular list of synonymous controls. Synonymous controls are kept in sync by
- * calling wControlLinkedActive for one member of the list
- *
- * \param b1 IN first control
- * \param b2 IN second control
- * \return none
- */
-
-EXPORT void wControlLinkedSet( wControl_p b1, wControl_p b2 )
-{
-
- b2->synonym = b1->synonym;
- if( b2->synonym == NULL )
- b2->synonym = b1;
-
- b1->synonym = b2;
-}
-
-/**
- * Activate/deactivate a group of synonymous controls.
- *
- * \param b IN control
- * \param active IN state
- * \return none
- */
-
-
-EXPORT void wControlLinkedActive( wControl_p b, int active )
-{
- wControl_p savePtr = b;
-
- if( savePtr->type == B_MENUITEM )
- wMenuPushEnable( (wMenuPush_p)savePtr, active );
- else
- wControlActive( savePtr, active );
-
- savePtr = savePtr->synonym;
-
- while( savePtr && savePtr != b ) {
-
- if( savePtr->type == B_MENUITEM )
- wMenuPushEnable( (wMenuPush_p)savePtr, active );
- else
- wControlActive( savePtr, active );
-
- savePtr = savePtr->synonym;
- }
-}
-
-/*
- *****************************************************************************
- *
- * Control Utilities
- *
- *****************************************************************************
- */
-
-EXPORT void wControlShow(
- wControl_p b, /* Control */
- wBool_t show ) /* Command */
-/*
-Cause the control <b> to be displayed or hidden.
-Used to hide control (such as a list) while it is being updated.
-*/
-{
- if ( b->type == B_LINES ) {
- gtkLineShow( (wLine_p)b, show );
- return;
- }
- if (b->widget == 0) abort();
- if (show) {
- gtk_widget_show( b->widget );
- if (b->label)
- gtk_widget_show( b->label );
- } else {
- gtk_widget_hide( b->widget );
- if (b->label)
- gtk_widget_hide( b->label );
- }
-}
-
-EXPORT void wControlActive(
- wControl_p b, /* Control */
- int active ) /* Command */
-/*
-Cause the control <b> to be marked active or inactive.
-Inactive controls donot respond to actions.
-*/
-{
- if (b->widget == 0) abort();
- gtk_widget_set_sensitive( GTK_WIDGET(b->widget), active );
-}
-
-
-EXPORT wPos_t wLabelWidth(
- const char * label ) /* Label */
-/*
-Returns the width of <label>.
-This is used for computing window layout.
-Typically the width to the longest label is computed and used as
-the X-position for <controls>.
-*/
-{
- GtkWidget * widget;
- GtkRequisition requisition;
- widget = gtk_label_new( gtkConvertInput(label) );
- gtk_widget_size_request( widget, &requisition );
- gtk_widget_destroy( widget );
- return requisition.width+8;
-}
-
-
-EXPORT wPos_t wControlGetWidth(
- wControl_p b) /* Control */
-{
- return b->w;
-}
-
-
-EXPORT wPos_t wControlGetHeight(
- wControl_p b) /* Control */
-{
- return b->h;
-}
-
-
-EXPORT wPos_t wControlGetPosX(
- wControl_p b) /* Control */
-{
- return b->realX;
-}
-
-
-EXPORT wPos_t wControlGetPosY(
- wControl_p b) /* Control */
-{
- return b->realY - FOUR - ((b->parent->option&F_MENUBAR)?MENUH:0);
-}
-
-
-EXPORT void wControlSetPos(
- wControl_p b, /* Control */
- wPos_t x, /* X-position */
- wPos_t y ) /* Y-position */
-{
- b->realX = x;
- b->realY = y + FOUR + ((b->parent->option&F_MENUBAR)?MENUH:0);
-#ifndef GTK1
- if (b->widget)
- gtk_fixed_move( GTK_FIXED(b->parent->widget), b->widget, b->realX, b->realY );
- if (b->label)
- gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET );
-#else
- if (b->widget)
- gtk_widget_set_uposition( b->widget, b->realX, b->realY );
- if (b->label)
- gtk_widget_set_uposition( b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET );
-#endif
-}
-
-
-EXPORT void wControlSetLabel(
- wControl_p b,
- const char * labelStr )
-{
- GtkRequisition requisition;
- if (b->label) {
- gtk_label_set( GTK_LABEL(b->label), gtkConvertInput(labelStr) );
- gtk_widget_size_request( b->label, &requisition );
- b->labelW = requisition.width+8;
-#ifndef GTK1
- gtk_fixed_move( GTK_FIXED(b->parent->widget), b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET );
-#else
- gtk_widget_set_uposition( b->label, b->realX-b->labelW, b->realY+LABEL_OFFSET );
-#endif
- } else {
- b->labelW = gtkAddLabel( b, labelStr );
- }
-}
-
-EXPORT void wControlSetContext(
- wControl_p b,
- void * context )
-{
- b->data = context;
-}
-
-
-EXPORT void wControlSetFocus(
- wControl_p b )
-{
-}
-
-
-static int gtkControlHiliteWidth = 3;
-EXPORT void wControlHilite(
- wControl_p b,
- wBool_t hilite )
-{
- int off = gtkControlHiliteWidth/2+1;
- if ( b->parent->gc == NULL ) {
- b->parent->gc = gdk_gc_new( b->parent->gtkwin->window );
- gdk_gc_copy( b->parent->gc, b->parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] );
- b->parent->gc_linewidth = 0;
- gdk_gc_set_line_attributes( b->parent->gc, b->parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- }
- if ( b->widget == NULL )
- return;
- if ( ! GTK_WIDGET_VISIBLE( b->widget ) )
- return;
- if ( ! GTK_WIDGET_VISIBLE( b->parent->widget ) )
- return;
- gdk_gc_set_foreground( b->parent->gc, gtkGetColor( wDrawColorBlack, FALSE ) );
- gdk_gc_set_function( b->parent->gc, GDK_XOR );
- gdk_gc_set_line_attributes( b->parent->gc, gtkControlHiliteWidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- gdk_draw_line( b->parent->widget->window, b->parent->gc,
- b->realX - gtkControlHiliteWidth,
- b->realY - off,
- b->realX + b->w + gtkControlHiliteWidth,
- b->realY - off );
- gdk_draw_line( b->parent->widget->window, b->parent->gc,
- b->realX - gtkControlHiliteWidth,
- b->realY + b->h + off - 1,
- b->realX + b->w + gtkControlHiliteWidth,
- b->realY + b->h + off - 1 );
- gdk_draw_line( b->parent->widget->window, b->parent->gc,
- b->realX - off,
- b->realY,
- b->realX - off,
- b->realY + b->h );
- gdk_draw_line( b->parent->widget->window, b->parent->gc,
- b->realX + b->w + off - 1,
- b->realY,
- b->realX + b->w + off - 1,
- b->realY + b->h );
-}
-
-/*
- *******************************************************************************
- *
- * Main
- *
- *******************************************************************************
- */
-
-#ifdef GTK
-static wBool_t wAbortOnErrors = FALSE;
-#endif
-
-int do_rgb_init = 1;
-
-int main( int argc, char *argv[] )
-{
- wWin_p win;
- wControl_p b;
- const char *ld, *hp;
- static char buff[BUFSIZ];
-
- if ( getenv( "GTKLIB_NOLOCALE" ) == 0 )
- setlocale( LC_ALL, "en_US" );
- gtk_init( &argc, &argv );
- gettimeofday( &startTime, NULL );
-
- if ( getenv( "XVLIB_REVERSEICON" ) != 0 )
- reverseIcon = !reverseIcon;
-
- if ( do_rgb_init )
- gdk_rgb_init(); /* before we try to draw */
-
- if ((win=wMain( argc, argv )) == (wWin_p)0)
- exit(1);
-
- ld = wGetAppLibDir();
- if (ld != NULL) {
- sprintf( buff, "HELPPATH=/usr/lib/help:%s:", ld );
- if ( (hp = getenv("HELPPATH")) != NULL )
- strcat( buff, hp );
- putenv( buff );
- }
-
- if (!win->shown)
- wWinShow( win, TRUE );
- for (b=win->first; b != NULL; b = b->next) {
- if (b->repaintProc)
- b->repaintProc( b );
- }
- gtk_main();
- exit(0);
-}
diff --git a/app/wlib/gtklib/gtksimple.c b/app/wlib/gtklib/gtksimple.c
deleted file mode 100644
index 244c0a3..0000000
--- a/app/wlib/gtklib/gtksimple.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtksimple.c,v 1.6 2009-09-25 05:38:15 dspagnol Exp $
- */
-
-/* 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 <stdlib.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "gtkint.h"
-
-static int windowxxx = 0;
-/*
- *****************************************************************************
- *
- * Message Boxes
- *
- *****************************************************************************
- */
-
-struct wMessage_t {
- WOBJ_COMMON
- GtkWidget * labelWidget;
- const char * message;
- wPos_t labelWidth;
- };
-
-EXPORT void wMessageSetValue(
- wMessage_p b,
- const char * arg )
-{
- if (b->widget == 0) abort();
- gtk_label_set( GTK_LABEL( b->labelWidget ), gtkConvertInput(arg) );
-}
-
-
-EXPORT void wMessageSetWidth(
- wMessage_p b,
- wPos_t width )
-{
- b->labelWidth = width;
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, width, -1 );
-#else
- gtk_widget_set_usize( b->widget, width, -1 );
-#endif
-}
-
-
-EXPORT wPos_t wMessageGetHeight(
- long flags )
-{
- return 14;
-}
-
-/**
- * Create a window for a simple text.
- *
- * \param IN parent Handle of parent window
- * \param IN x position in x direction
- * \param IN y position in y direction
- * \param IN labelStr ???
- * \param IN width horizontal size of window
- * \param IN message message to display ( null terminated )
- * \param IN flags display options
- * \return handle for created window
- */
-
-EXPORT wMessage_p wMessageCreateEx(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * labelStr,
- wPos_t width,
- const char *message,
- long flags )
-{
- wMessage_p b;
- GtkRequisition requisition;
- PangoFontDescription *fontDesc;
- int fontSize;
-
- b = (wMessage_p)gtkAlloc( parent, B_MESSAGE, x, y, NULL, sizeof *b, NULL );
- gtkComputePos( (wControl_p)b );
- b->message = message;
- b->labelWidth = width;
-
- b->labelWidget = gtk_label_new( message?gtkConvertInput(message):"" );
-
- /* do we need to set a special font? */
- if( wMessageSetFont( flags )) {
- /* get the current font descriptor */
- fontDesc = (b->labelWidget)->style->font_desc;
-
- /* get the current font size */
- fontSize = PANGO_PIXELS(pango_font_description_get_size( fontDesc ));
-
- /* calculate the new font size */
- if( flags & BM_LARGE ) {
- pango_font_description_set_size( fontDesc, fontSize * 1.4 * PANGO_SCALE );
- } else {
- pango_font_description_set_size( fontDesc, fontSize * 0.7 * PANGO_SCALE );
- }
-
- /* set the new font size */
- gtk_widget_modify_font( (GtkWidget *)b->labelWidget, fontDesc );
- }
-
- b->widget = gtk_fixed_new();
- gtk_widget_size_request( GTK_WIDGET(b->labelWidget), &requisition );
- gtk_container_add( GTK_CONTAINER(b->widget), b->labelWidget );
-
- gtk_widget_set_size_request( b->widget, width?width:requisition.width, requisition.height );
- gtkControlGetSize( (wControl_p)b );
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
-
- gtk_widget_show( b->widget );
- gtk_widget_show( b->labelWidget );
- gtkAddButton( (wControl_p)b );
-
- /* Reset font size to normal */
- if( wMessageSetFont( flags )) {
- if( flags & BM_LARGE ) {
- pango_font_description_set_size(fontDesc, fontSize * PANGO_SCALE);
- } else {
- pango_font_description_set_size(fontDesc, fontSize * PANGO_SCALE);
- }
- }
- return b;
-}
-
-/*
- *****************************************************************************
- *
- * Lines
- *
- *****************************************************************************
- */
-
-struct wLine_t {
- WOBJ_COMMON
- wBool_t visible;
- int count;
- wLines_t * lines;
- };
-
-static void linesRepaint( wControl_p b )
-{
- wLine_p bl = (wLine_p)(b);
- int i;
- wWin_p win = (wWin_p)(bl->parent);
- GdkDrawable * window;
- GdkColor *black;
-
- if (!bl->visible)
- return;
-if (windowxxx)
- window = win->gtkwin->window;
-else
- window = win->widget->window;
-
- /* get the GC attached to the panel in main() */
- black = gtkGetColor( wDrawColorBlack, TRUE );
- gdk_gc_set_foreground( win->gc, black );
- gdk_gc_set_function( win->gc, GDK_COPY );
- for (i=0; i<bl->count; i++) {
- if (win->gc_linewidth != bl->lines[i].width) {
- win->gc_linewidth = bl->lines[i].width;
- gdk_gc_set_line_attributes( win->gc, win->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- }
- gdk_draw_line( window, win->gc,
- bl->lines[i].x0, bl->lines[i].y0,
- bl->lines[i].x1, bl->lines[i].y1 );
- }
-}
-
-
-void gtkLineShow(
- wLine_p bl,
- wBool_t visible )
-{
- bl->visible = visible;
-}
-
-
-wLine_p wLineCreate(
- wWin_p parent,
- const char * labelStr,
- int count,
- wLines_t * lines )
-{
- wLine_p b;
- int i;
- b = (wLine_p)gtkAlloc( parent, B_LINES, 0, 0, labelStr, sizeof *b, NULL );
- if (parent->gc == NULL) {
- parent->gc = gdk_gc_new( parent->gtkwin->window );
- gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] );
- parent->gc_linewidth = 0;
- gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- }
- b->visible = TRUE;
- b->count = count;
- b->lines = lines;
-
- b->w = b->h = 0;
- for ( i=0; i<count; i++ ) {
- if (lines[i].x0 > b->w)
- b->w = lines[i].x0;
- if (lines[i].y0 > b->h)
- b->h = lines[i].y0;
- if (lines[i].x1 > b->w)
- b->w = lines[i].x1;
- if (lines[i].y1 > b->h)
- b->h = lines[i].y1;
- }
- b->repaintProc = linesRepaint;
- gtkAddButton( (wControl_p)b );
- b->widget = 0;
- return b;
-}
-
-
-/*
- *****************************************************************************
- *
- * Boxes
- *
- *****************************************************************************
- */
-
-struct wBox_t {
- WOBJ_COMMON
- wBoxType_e boxTyp;
- };
-
-#define B (1)
-#define W (2)
-#define SETCOLOR( S, N ) \
- if ( lastColor != colors[style][S][N] ) { \
- lastColor = colors[style][S][N]; \
- gdk_gc_set_foreground( win->gc, (lastColor==B)?black:white ); \
- }
-
-EXPORT void wBoxSetSize(
- wBox_p b, /* */
- wPos_t w, /* */
- wPos_t h ) /* */
-{
- b->w = w;
- b->h = h;
-}
-
-
-EXPORT void gtkDrawBox(
- wWin_p win,
- wBoxType_e style,
- wPos_t x,
- wPos_t y,
- wPos_t w,
- wPos_t h )
-{
- wPos_t x0, y0, x1, y1;
- char lastColor;
- GdkColor *white;
- GdkColor *black;
- GdkDrawable * window;
- static char colors[8][4][2] = {
- { /* ThinB */ {B,0}, {B,0}, {B,0}, {B,0} },
- { /* ThinW */ {W,0}, {W,0}, {W,0}, {W,0} },
- { /* AboveW */ {W,0}, {W,0}, {B,0}, {B,0} },
- { /* BelowW */ {B,0}, {B,0}, {W,0}, {W,0} },
- { /* ThickB */ {B,B}, {B,B}, {B,B}, {B,B} },
- { /* ThickW */ {W,W}, {W,W}, {W,W}, {W,W} },
- { /* RidgeW */ {W,B}, {W,B}, {B,W}, {B,W} },
- { /* TroughW*/ {B,W}, {B,W}, {W,B}, {W,B} } };
-
-if (windowxxx)
- window = win->gtkwin->window;
-else
- window = win->widget->window;
- white = gtkGetColor( wDrawColorWhite, TRUE );
- black = gtkGetColor( wDrawColorBlack, TRUE );
- win->gc_linewidth = 0;
- gdk_gc_set_line_attributes( win->gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- gdk_gc_set_function( win->gc, GDK_COPY );
- x0 = x;
- x1 = x+w;
- y0 = y;
- y1 = y+h;
- lastColor = colors[style][0][0];
- gdk_gc_set_foreground( win->gc, (lastColor==B)?black:white );
- gdk_draw_line( window, win->gc, x0, y0, x0, y1 );
- SETCOLOR( 1, 0 );
- gdk_draw_line( window, win->gc, x0+1, y0, x1, y0 );
- SETCOLOR( 2, 0 );
- gdk_draw_line( window, win->gc, x1, y1, x0+1, y1 );
- SETCOLOR( 3, 0 );
- gdk_draw_line( window, win->gc, x1, y1-1, x1, y0+1 );
- if (style < wBoxThickB)
- return;
- x0++; y0++; x1--; y1--;
- SETCOLOR( 0, 1 );
- gdk_draw_line( window, win->gc, x0, y0, x0, y1 );
- SETCOLOR( 1, 1 );
- gdk_draw_line( window, win->gc, x0+1, y0, x1, y0 );
- SETCOLOR( 2, 1 );
- gdk_draw_line( window, win->gc, x1, y1, x0+1, y1 );
- SETCOLOR( 3, 1 );
- gdk_draw_line( window, win->gc, x1, y1-1, x1, y0+1 );
- gdk_gc_set_foreground( win->gc, black );
-}
-
-
-static void boxRepaint( wControl_p b )
-{
- wBox_p bb = (wBox_p)(b);
- wWin_p win = bb->parent;
-
- gtkDrawBox( win, bb->boxTyp, bb->realX, bb->realY, bb->w, bb->h );
-}
-
-
-wBox_p wBoxCreate(
- wWin_p parent,
- wPos_t bx,
- wPos_t by,
- const char * labelStr,
- wBoxType_e boxTyp,
- wPos_t bw,
- wPos_t bh )
-{
- wBox_p b;
- b = (wBox_p)gtkAlloc( parent, B_BOX, bx, by, labelStr, sizeof *b, NULL );
- gtkComputePos( (wControl_p)b );
- b->boxTyp = boxTyp;
- b->w = bw;
- b->h = bh;
- if (parent->gc == NULL) {
- parent->gc = gdk_gc_new( parent->gtkwin->window );
- gdk_gc_copy( parent->gc, parent->gtkwin->style->base_gc[GTK_STATE_NORMAL] );
- parent->gc_linewidth = 0;
- gdk_gc_set_line_attributes( parent->gc, parent->gc_linewidth, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER );
- }
- b->repaintProc = boxRepaint;
- gtkAddButton( (wControl_p)b );
- return b;
-}
-
diff --git a/app/wlib/gtklib/gtksingle.c b/app/wlib/gtklib/gtksingle.c
deleted file mode 100644
index d106e17..0000000
--- a/app/wlib/gtklib/gtksingle.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtksingle.c,v 1.2 2009-05-15 18:54:20 m_fischer Exp $
- */
-
-/* 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 <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <gtk/gtk.h>
-
-#include "gtkint.h"
-
-/*
- *****************************************************************************
- *
- * Text Boxes
- *
- *****************************************************************************
- */
-
-struct wString_t {
- WOBJ_COMMON
- char * valueP;
- wIndex_t valueL;
- wStringCallBack_p action;
- wBool_t busy;
- };
-
-void wStringSetValue(
- wString_p b,
- const char * arg )
-{
- wBool_t busy;
- if (b->widget == 0) abort();
- busy = b->busy;
- b->busy = TRUE;
- gtk_entry_set_text( GTK_ENTRY(b->widget), arg );
- b->busy = busy;
-}
-
-
-void wStringSetWidth(
- wString_p b,
- wPos_t w )
-{
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, w, -1 );
-#else
- gtk_widget_set_usize( b->widget, w, -1 );
-#endif
- b->w = w;
-}
-
-
-const char * wStringGetValue(
- wString_p b )
-{
- if (b->widget == 0) abort();
- return gtk_entry_get_text( GTK_ENTRY(b->widget) );
-}
-
-
-static void triggerString(
- wControl_p b )
-{
- wString_p bs = (wString_p)b;
- const char * s;
-
- if (b == 0)
- return;
- if (bs->widget == 0) abort();
- s = gtk_entry_get_text( GTK_ENTRY(bs->widget) );
- if (debugWindow >= 2) printf("%s text = %s\n", bs->labelStr?bs->labelStr:"No label", s );
- if (s == NULL)
- return;
- if (debugWindow >= 2) printf("triggerString( %s )\n", s );
- if (bs->action) {
- bs->busy = TRUE;
- bs->action( s, bs->data );
- bs->busy = FALSE;
- }
- gtkSetTrigger( NULL, NULL );
- return;
-}
-
-
-static void stringActivated(
- GtkEntry * widget,
- wString_p b )
-{
- const char * s;
- if (b == 0)
- return;
- s = wStringGetValue(b);
-
- if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
- if (b->valueP)
- strcpy( b->valueP, s );
- if (b->action) {
- b->busy = TRUE;
- b->action( s, b->data );
- b->busy = FALSE;
- }
-}
-
-static void stringChanged(
- GtkEntry * widget,
- wString_p b )
-{
- const char *new_value;
- if (b == 0)
- return;
- if (b->busy)
- return;
- new_value = wStringGetValue(b);
- if (b->valueP != NULL)
- strcpy( b->valueP, new_value );
- if (b->action)
- gtkSetTrigger( (wControl_p)b, triggerString );
- return;
-}
-
-wString_p wStringCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- long option,
- wPos_t width,
- char *valueP,
- wIndex_t valueL,
- wStringCallBack_p action,
- void *data )
-{
- wString_p b;
-
- b = (wString_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data );
- b->valueP = valueP;
- b->action = action;
- b->option = option;
- b->valueL = valueL;
- gtkComputePos( (wControl_p)b );
-
- if (valueL) {
- b->widget = (GtkWidget*)gtk_entry_new_with_max_length( valueL );
- } else {
- b->widget = (GtkWidget*)gtk_entry_new();
- }
- if (b->widget == 0) abort();
-
-#ifndef GTK1
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
- gtk_widget_set_uposition( b->widget, b->realX, b->realY );
-#endif
- if ( width )
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, width, -1 );
-#else
- gtk_widget_set_usize( b->widget, width, -1 );
-#endif
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- /*b->w += 4;*/
- /*b->h += 4;*/
- if (b->valueP)
- wStringSetValue( b, b->valueP );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- gtkAddHelpString( b->widget, helpStr );
- gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(stringChanged), b );
- gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(stringActivated), b );
- if (option & BO_READONLY)
- gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE );
- return b;
-}
-
-/*
- *****************************************************************************
- *
- * Floating Point Value Boxes
- *
- *****************************************************************************
- */
-
-
-struct wFloat_t {
- WOBJ_COMMON
- double low, high;
- double oldValue;
- double * valueP;
- wFloatCallBack_p action;
- wBool_t busy;
- };
-
-
-void wFloatSetValue(
- wFloat_p b,
- double arg )
-{
- char message[80];
- if (b->widget == 0) abort();
- sprintf( message, "%0.3f", arg );
- if (!b->busy) {
- b->busy = TRUE;
- gtk_entry_set_text( GTK_ENTRY(b->widget), message );
- b->busy = FALSE;
- }
- if (b->valueP)
- *b->valueP = arg;
-}
-
-
-double wFloatGetValue(
- wFloat_p b )
-{
- double ret;
- const char * cp;
- if (b->widget == 0) abort();
- cp = gtk_entry_get_text( GTK_ENTRY(b->widget) );
- ret = atof( cp );
- return ret;
-}
-
-
-static void triggerFloat(
- wControl_p b )
-{
- wFloat_p bf = (wFloat_p)b;
- const char * s;
- char * cp;
- double v;
-
- if (b == 0)
- return;
- if (bf->widget == 0) abort();
- s = gtk_entry_get_text( GTK_ENTRY(bf->widget) );
- if (debugWindow >= 2) printf("%s text = %s\n", bf->labelStr?bf->labelStr:"No label", s );
- if (s == NULL)
- return;
- v = strtod( s, &cp );
- if (*cp!=0 || v < bf->low || v > bf->high)
- return;
- /*if (bf->oldValue == v)
- return;*/
- if (debugWindow >= 2) printf("triggerFloat( %0.3f )\n", v );
- bf->oldValue = v;
- if (bf->valueP)
- *bf->valueP = v;
- if (bf->action) {
- bf->busy = TRUE;
- bf->action( v, bf->data );
- bf->busy = FALSE;
- }
- gtkSetTrigger( NULL, NULL );
- return;
-}
-
-
-static void floatActivated(
- GtkEntry *widget,
- wFloat_p b )
-{
- const char * s;
- char * cp;
- double v;
- char val_s[80];
-
- if (b == 0)
- return;
- if (b->widget == 0) abort();
- s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
- if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
- if (s != NULL) {
- v = strtod( s, &cp );
- if (*cp != '\n' && *cp != '\0') {
- wNoticeEx( NT_ERROR, "The value you have entered is not a valid number\nPlease try again", "Ok", NULL );
- } else if (v < b->low || v > b->high) {
- sprintf( val_s, "Please enter a value between %0.3f and %0.3f", b->low, b->high );
- wNoticeEx( NT_ERROR, val_s, "Ok", NULL );
- } else {
- if (debugWindow >= 2) printf("floatActivated( %0.3f )\n", v );
- b->oldValue = v;
- if (b->valueP)
- *b->valueP = v;
- if (b->action) {
- gtkSetTrigger( NULL, NULL );
- b->busy = TRUE;
- b->action( v, b->data );
- b->busy = FALSE;
- }
- return;
- }
- sprintf( val_s, "%0.3f", b->oldValue);
- b->busy = TRUE;
- gtk_entry_set_text( GTK_ENTRY(b->widget), val_s );
- b->busy = FALSE;
- }
- return;
-}
-
-static void floatChanged(
- GtkEntry *widget,
- wFloat_p b )
-{
- const char * s;
- char * cp;
- double v;
-
- if (b == 0)
- return;
- if (b->widget == 0) abort();
- if (b->busy)
- return;
- s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
- if (s == NULL)
- return;
- if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
- if ( s[0] == '\0' ||
- strcmp( s, "-" ) == 0 ||
- strcmp( s, "." ) == 0 ) {
- v = 0;
- } else {
- v = strtod( s, &cp );
- if (*cp != '\0'
-#ifdef LATER
- || v < b->low || v > b->high
-#endif
- ) {
- wBeep();
- wFloatSetValue( b, b->oldValue );
- return;
- }
- }
- b->oldValue = v;
- if (b->valueP != NULL) {
- *b->valueP = v;
- }
- if (b->action)
- gtkSetTrigger( (wControl_p)b, triggerFloat );
- return;
-}
-
-wFloat_p wFloatCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- long option,
- wPos_t width,
- double low,
- double high,
- double *valueP,
- wFloatCallBack_p action,
- void *data )
-{
- wFloat_p b;
-
- b = (wFloat_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data );
- b->valueP = valueP;
- b->action = action;
- b->option = option;
- b->low = low;
- b->high = high;
- gtkComputePos( (wControl_p)b );
-
- b->widget = (GtkWidget*)gtk_entry_new_with_max_length( 20 );
- if (b->widget == 0) abort();
-
-#ifndef GTK1
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
- gtk_widget_set_uposition( b->widget, b->realX, b->realY );
-#endif
- if ( width )
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, width, -1 );
-#else
- gtk_widget_set_usize( b->widget, width, -1 );
-#endif
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- /*b->w += 4;*/
- /*b->h += 4;*/
- if (b->valueP)
- wFloatSetValue( b, *b->valueP );
- else
- wFloatSetValue( b, b->low>0?b->low:0.0 );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- gtkAddHelpString( b->widget, helpStr );
- gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(floatChanged), b );
- gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(floatActivated), b );
- if (option & BO_READONLY)
- gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE );
- return b;
-}
-
-/*
- *****************************************************************************
- *
- * Integer Value Boxes
- *
- *****************************************************************************
- */
-
-
-struct wInteger_t {
- WOBJ_COMMON
- long low, high;
- long oldValue;
- long * valueP;
- wIntegerCallBack_p action;
- wBool_t busy;
- };
-
-
-void wIntegerSetValue(
- wInteger_p b,
- long arg )
-{
- char message[80];
- if (b->widget == 0) abort();
- sprintf( message, "%ld", arg );
- if (!b->busy) {
- b->busy = TRUE;
- gtk_entry_set_text( GTK_ENTRY(b->widget), message );
- b->busy = FALSE;
- }
- if (b->valueP)
- *b->valueP = arg;
-}
-
-
-long wIntegerGetValue(
- wInteger_p b )
-{
- long ret;
- const char * cp;
- if (b->widget == 0) abort();
- cp = gtk_entry_get_text( GTK_ENTRY(b->widget) );
- ret = atol( cp );
- return ret;
-}
-
-
-static void triggerInteger(
- wControl_p b )
-{
- wInteger_p bi = (wInteger_p)b;
- const char * s;
- char * cp;
- long v;
-
- if (b == 0)
- return;
- if (bi->widget == 0) abort();
- s = gtk_entry_get_text( GTK_ENTRY(bi->widget) );
- if (debugWindow >= 2) printf("%s text = %s\n", bi->labelStr?bi->labelStr:"No label", s );
- if (s == NULL)
- return;
- v = strtol( s, &cp, 10 );
- if (*cp!=0 || v < bi->low || v > bi->high)
- return;
- /*if (bi->oldValue == v)
- return;*/
- if (debugWindow >= 2) printf("triggerInteger( %ld )\n", v );
- bi->oldValue = v;
- if (bi->valueP)
- *bi->valueP = v;
- if (bi->action) {
- bi->busy = TRUE;
- bi->action( v, bi->data );
- bi->busy = FALSE;
- }
- gtkSetTrigger( NULL, NULL );
- return;
-}
-
-
-
-static void integerActivated(
- GtkEntry *widget,
- wInteger_p b )
-{
- const char * s;
- char * cp;
- long v;
- char val_s[80];
-
- if (b == 0)
- return;
- if (b->widget == 0) abort();
- s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
- if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
- if (s != NULL) {
- v = strtod( s, &cp );
- if (*cp != '\n' && *cp != '\0') {
- wNoticeEx( NT_ERROR, "The value you have entered is not a valid number\nPlease try again", "Ok", NULL );
- } else if (v < b->low || v > b->high) {
- sprintf( val_s, "Please enter a value between %ld and %ld", b->low, b->high );
- wNoticeEx( NT_ERROR, val_s, "Ok", NULL );
- } else {
- if (debugWindow >= 2) printf("integerActivated( %ld )\n", v );
- b->oldValue = v;
- if (b->valueP)
- *b->valueP = v;
- if (b->action) {
- gtkSetTrigger( NULL, NULL );
- b->busy = TRUE;
- b->action( v, b->data );
- b->busy = FALSE;
- }
- return;
- }
- sprintf( val_s, "%ld", b->oldValue);
- b->busy = TRUE;
- gtk_entry_set_text( GTK_ENTRY(b->widget), val_s );
- b->busy = FALSE;
- }
- return;
-}
-
-static void integerChanged(
- GtkEntry *widget,
- wInteger_p b )
-{
- const char * s;
- char * cp;
- long v;
-
- if (b == 0)
- return;
- if (b->widget == 0) abort();
- if (b->busy)
- return;
- s = gtk_entry_get_text( GTK_ENTRY(b->widget) );
- if (s == NULL)
- return;
- if (debugWindow >= 2) printf("%s text = %s\n", b->labelStr?b->labelStr:"No label", s );
- if ( s[0] == '\0' ||
- strcmp( s, "-" ) == 0 ) {
- v = 0;
- } else {
- v = strtol( s, &cp, 10 );
- if (*cp != '\0'
-#ifdef LATER
- || v < b->low || v > b->high
-#endif
- ) {
- wBeep();
- wIntegerSetValue( b, b->oldValue );
- return;
- }
- }
- b->oldValue = v;
- if (b->valueP != NULL) {
- *b->valueP = v;
- }
- if (b->action)
- gtkSetTrigger( (wControl_p)b, triggerInteger );
- return;
-}
-
-wInteger_p wIntegerCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- long option,
- wPos_t width,
- long low,
- long high,
- long *valueP,
- wIntegerCallBack_p action,
- void *data )
-{
- wInteger_p b;
-
- b = (wInteger_p)gtkAlloc( parent, B_TEXT, x, y, labelStr, sizeof *b, data );
- b->valueP = valueP;
- b->action = action;
- b->option = option;
- b->low = low;
- b->high = high;
- gtkComputePos( (wControl_p)b );
-
- b->widget = (GtkWidget*)gtk_entry_new_with_max_length( 20 );
- if (b->widget == 0) abort();
-
-#ifndef GTK1
- gtk_fixed_put( GTK_FIXED(parent->widget), b->widget, b->realX, b->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), b->widget );
- gtk_widget_set_uposition( b->widget, b->realX, b->realY );
-#endif
- if ( width )
-#ifndef GTK1
- gtk_widget_set_size_request( b->widget, width, -1 );
-#else
- gtk_widget_set_usize( b->widget, width, -1 );
-#endif
- gtkControlGetSize( (wControl_p)b );
- if (labelStr)
- b->labelW = gtkAddLabel( (wControl_p)b, labelStr );
- /*b->w += 4;*/
- /*b->h += 4;*/
- if (b->valueP)
- wIntegerSetValue( b, *b->valueP );
- else
- wIntegerSetValue( b, b->low>0?b->low:0.0 );
- gtk_widget_show( b->widget );
- gtkAddButton( (wControl_p)b );
- gtkAddHelpString( b->widget, helpStr );
- gtk_signal_connect( GTK_OBJECT(b->widget), "changed", GTK_SIGNAL_FUNC(integerChanged), b );
- gtk_signal_connect( GTK_OBJECT(b->widget), "activate", GTK_SIGNAL_FUNC(integerActivated), b );
- if (option & BO_READONLY)
- gtk_entry_set_editable( GTK_ENTRY(b->widget), FALSE );
- return b;
-}
diff --git a/app/wlib/gtklib/gtksplash.c b/app/wlib/gtklib/gtksplash.c
deleted file mode 100644
index 0f49774..0000000
--- a/app/wlib/gtklib/gtksplash.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/** \file gtksplash.c
- * Handling of the Splash Window functions
- *
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtksplash.c,v 1.5 2009-05-31 14:48:58 m_fischer Exp $
- */
-
-/* XTrkCad - Model Railroad CAD
- * Copyright (C) 2007 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 <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include "gtkint.h"
-
-#define LOGOFILENAME "logo.bmp"
-
-static GtkWidget *window; /** splash window handle */
-static GtkWidget *message; /** window handle for progress message */
-
-/**
- * Create the splash window shown during startup. The function loads the logo
- * bitmap and displays the program name and version as passed.
- *
- * \param IN appName the product name to be shown
- * \param IN appVer the product version to be shown
- * \return TRUE if window was created, FALSE if an error occured
- */
-
-int
-wCreateSplash( char *appName, char *appVer )
-{
- GtkWidget *vbox;
- GtkWidget *image;
- GtkWidget *label;
- char *temp;
- char logoPath[BUFSIZ];
-
- /* create the basic window */
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_decorated( GTK_WINDOW (window), FALSE );
- gtk_window_set_title (GTK_WINDOW (window), appName);
- gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
- gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
- gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
-#if GTK_MINOR_VERSION > 5
- gtk_window_set_focus_on_map (GTK_WINDOW (window), FALSE);
-#endif
-
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (vbox);
- gtk_container_add (GTK_CONTAINER (window), vbox);
-
- /* add the logo image to the top of the splash window */
- sprintf( logoPath, "%s/" LOGOFILENAME, wGetAppLibDir());
- image = gtk_image_new_from_file ( logoPath );
- gtk_widget_show (image);
- gtk_box_pack_start (GTK_BOX (vbox), image, TRUE, TRUE, 0);
- gtk_misc_set_alignment (GTK_MISC (image), 0, 0);
-
- /* put the product name into the window */
-
- temp = malloc( strlen( appName ) + strlen( appVer ) + 2 );
- if( !temp )
- return( FALSE );
-
- sprintf( temp, "%s %s", appName, appVer );
-
- label = gtk_label_new ( temp );
- gtk_widget_show (label);
- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
- gtk_label_set_selectable (GTK_LABEL (label), FALSE);
- gtk_misc_set_padding (GTK_MISC (label), 6, 2);
-
- free( temp );
-
- label = gtk_label_new ("Application is starting...");
- gtk_widget_show (label);
- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
- gtk_label_set_line_wrap (GTK_LABEL (label), FALSE);
- gtk_misc_set_padding (GTK_MISC (label), 6, 2);
-#if GTK_MINOR_VERSION > 5
- gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
-#endif
- message = label;
-
- gtk_widget_show( window );
-
- return( TRUE );
-}
-
-/**
- * Update the progress message inside the splash window
- * msg text message to display
- * return nonzero if ok
- */
-
-int
-wSetSplashInfo( char *msg )
-{
- if( msg ) {
- gtk_label_set_text( (GtkLabel *)message, msg );
- wFlush();
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Destroy the splash window.
- *
- */
-
-void
-wDestroySplash( void )
-{
- /* kill window */
- gtk_widget_destroy( window );
- return;
-}
diff --git a/app/wlib/gtklib/gtktext.c b/app/wlib/gtklib/gtktext.c
deleted file mode 100644
index e067f43..0000000
--- a/app/wlib/gtklib/gtktext.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/** \file gtktext.c
- * Multi-line Text Boxes
- */
-
-/* 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.
- */
-
-#define GTK_ENABLE_BROKEN
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "i18n.h"
-#include "gtkint.h"
-
-/*
- * Disable USE_TEXTVIEW to use the deprecated gtk_text
- */
-#define USE_TEXTVIEW
-
-
-struct PrintData {
- wText_p tb;
- gint lines_per_page;
- gdouble font_size;
- gchar **lines;
- gint total_lines;
- gint total_pages;
-};
-
-#define HEADER_HEIGHT 20.0
-#define HEADER_GAP 8.5
-
-struct wText_t {
- WOBJ_COMMON
- wPos_t width, height;
- int changed;
- GtkWidget * text;
- GtkWidget * vscroll;
- };
-
-EXPORT void wTextClear(
- wText_p bt )
-{
-#ifdef USE_TEXTVIEW
- GtkTextBuffer * tb;
-#endif
- if (bt->text == 0) abort();
-#ifdef USE_TEXTVIEW
- tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) );
- gtk_text_buffer_set_text( tb, "", -1 );
- if (bt->option & BO_READONLY)
- gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE );
-#else
- gtk_text_set_point( GTK_TEXT(bt->text), 0 );
- gtk_text_forward_delete( GTK_TEXT(bt->text), gtk_text_get_length( GTK_TEXT(bt->text) ) );
- if (bt->option & BO_READONLY)
- gtk_text_set_editable( GTK_TEXT(bt->text), FALSE );
-#endif
- bt->changed = FALSE;
-}
-
-EXPORT void wTextAppend(
- wText_p bt,
- const char * text )
-{
-#ifdef USE_TEXTVIEW
- GtkTextBuffer * tb;
- GtkTextIter ti1, ti2;
-#else
- static GdkFont * fixedRegularFont = NULL;
- static GdkFont * fixedBoldFont = NULL;
- static GdkFont * variableRegularFont = NULL;
- static GdkFont * variableBoldFont = NULL;
- GdkFont * regularFont = NULL;
- GdkFont * boldFont = NULL;
-#endif
- wBool_t doBold;
- char * cp;
- int len;
-
- if (bt->text == 0) abort();
-#ifdef USE_TEXTVIEW
- tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) );
-#else
- if ((bt->option&BT_FIXEDFONT)) {
- if (fixedRegularFont==NULL)
- fixedRegularFont = gdk_font_load( "-*-courier-medium-r-*-*-12-*-*-*-*-*-iso8859-*" );
- if (fixedBoldFont==NULL)
- fixedBoldFont = gdk_font_load( "-*-courier-bold-r-*-*-12-*-*-*-*-*-iso8859-*" );
- regularFont = fixedRegularFont;
- boldFont = fixedBoldFont;
- } else {
- if (variableRegularFont==NULL)
- variableRegularFont = gdk_font_load( "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-iso8859-*" );
- if (variableBoldFont==NULL)
- variableBoldFont = gdk_font_load( "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-iso8859-*" );
- regularFont = variableRegularFont;
- boldFont = variableBoldFont;
- }
-#endif
- /*gtk_text_freeze( GTK_TEXT (bt->text) );*/
- doBold = FALSE;
- text = gtkConvertInput( text );
- while ( text && *text ) {
- if ( (bt->option & BT_DOBOLD) != 0 &&
- ( cp = strchr( text, doBold?'>':'<' ) ) != NULL ) {
- len = cp-text;
- cp++;
- } else {
- len = -1;
- cp = NULL;
- }
- if ( len != 0 ) {
-#ifdef USE_TEXTVIEW
- gtk_text_buffer_get_bounds( tb, &ti1, &ti2 );
- if ( !doBold )
- gtk_text_buffer_insert( tb, &ti2, text, len );
- else
- gtk_text_buffer_insert_with_tags_by_name( tb, &ti2, text, len, "bold", NULL );
-#else
- gtk_text_insert( GTK_TEXT(bt->text), doBold?boldFont:regularFont, &bt->text->style->black, NULL, text, len );
-#endif
- }
- text = cp;
- doBold = !doBold;
- }
- /*gtk_text_set_point( GTK_TEXT(bt->text), gtk_text_get_length( GTK_TEXT(bt->text) )-1 );*/
- /*gtk_text_thaw( GTK_TEXT (bt->text) );*/
- bt->changed = FALSE;
-}
-
-EXPORT void gtkTextFreeze(
- wText_p bt )
-{
-#ifdef USE_TEXTVIEW
- gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE );
-#else
- gtk_text_freeze( GTK_TEXT (bt->text) );
-#endif
-}
-
-EXPORT void gtkTextThaw(
- wText_p bt )
-{
-#ifdef USE_TEXTVIEW
- gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), TRUE );
-#else
- gtk_text_thaw( GTK_TEXT (bt->text) );
-#endif
-}
-
-EXPORT void wTextReadFile(
- wText_p bt,
- const char * fileName )
-{
- FILE * f;
- char buff[BUFSIZ+1];
- if (fileName) {
- f = fopen( fileName, "r" );
- if (f == NULL) {
- perror( fileName );
- return;
- }
- while (fgets( buff, sizeof buff, f ) != NULL ) {
- wTextAppend( bt, buff );
- }
- }
-}
-
-
-#ifdef USE_TEXTVIEW
-static char * gtkGetText(
- wText_p bt )
-{
- GtkTextBuffer * tb;
- GtkTextIter ti1, ti2;
- char * cp;
- if (bt->text == 0) abort();
- tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) );
- gtk_text_buffer_get_bounds( tb, &ti1, &ti2 );
- cp = gtk_text_buffer_get_text( tb, &ti1, &ti2, FALSE );
- cp = gtkConvertOutput( cp );
- return cp;
-}
-#endif
-
-
-EXPORT wBool_t wTextSave(
- wText_p bt,
- const char * fileName )
-{
-#ifndef USE_TEXTVIEW
- int siz, pos, cnt;
-#endif
- FILE * f;
- char * cp;
-
- f = fopen( fileName, "w" );
- if (f==NULL) {
- wNoticeEx( NT_ERROR, fileName, "Ok", NULL );
- return FALSE;
- }
-#ifdef USE_TEXTVIEW
- cp = gtkGetText( bt );
- fwrite( cp, 1, strlen(cp), f );
- free(cp);
-#else
- siz = gtk_text_get_length( GTK_TEXT(bt->text) );
- pos = 0;
- cnt = BUFSIZ;
- while (pos<siz) {
- if (pos+cnt>siz)
- cnt = siz-pos;
- cp = gtk_editable_get_chars( GTK_EDITABLE(bt->text), pos, pos+cnt );
- if (cp == NULL)
- break;
- fwrite( cp, 1, cnt, f );
- free(cp);
- pos += cnt;
- }
-#endif
- fclose(f);
- return TRUE;
-}
-/**
- * Begin the printing by retrieving the contents of the text box and
- * count the lines of text.
- *
- * \param operation IN the GTK print operation
- * \param context IN print context
- * \param pd IN data structure for user data
- *
- */
-
-static void
-begin_print (GtkPrintOperation *operation,
- GtkPrintContext *context,
- struct PrintData *pd)
-{
- gchar *contents;
- gdouble height;
-
- contents = gtkGetText( pd->tb );
- pd->lines = g_strsplit (contents, "\n", 0);
-
- /* Count the total number of lines in the file. */
- /* ignore the header lines */
- pd->total_lines = 6;
- while (pd->lines[pd->total_lines] != NULL)
- pd->total_lines++;
-
- /* Based on the height of the page and font size, calculate how many lines can be
- * rendered on a single page. A padding of 3 is placed between lines as well.
- * Space for page header, table header and footer lines is subtracted from the total size
- */
- height = gtk_print_context_get_height (context) - (pd->font_size + 3) - 2 * ( HEADER_HEIGHT + HEADER_GAP );
- pd->lines_per_page = floor (height / (pd->font_size + 3));
- pd->total_pages = (pd->total_lines - 1) / pd->lines_per_page + 1;
- gtk_print_operation_set_n_pages (operation, pd->total_pages);
-
- free( contents );
-}
-
-/**
- * Draw the page, which includes a header with the file name and page number along
- * with one page of text with a font of "Monospace 10".
- *
- * \param operation IN the GTK print operation
- * \param context IN print context
- * \param page_nr IN page to print
- * \param pd IN data structure for user data
- *
- *
- */
-
-static void
-draw_page (GtkPrintOperation *operation,
- GtkPrintContext *context,
- gint page_nr,
- struct PrintData *pd )
-{
- cairo_t *cr;
- PangoLayout *layout;
- gdouble width, text_height, height;
- gint line, i, text_width, layout_height;
- PangoFontDescription *desc;
- gchar *page_str;
-
- cr = gtk_print_context_get_cairo_context (context);
- width = gtk_print_context_get_width (context);
-
- layout = gtk_print_context_create_pango_layout (context);
- desc = pango_font_description_from_string ("Monospace");
- pango_font_description_set_size (desc, pd->font_size * PANGO_SCALE);
-
- /*
- * render the header line with document type parts list on left and
- * first line of layout title on right
- */
-
- pango_layout_set_font_description (layout, desc);
- pango_layout_set_text (layout, pd->lines[ 0 ], -1); // document type
- pango_layout_set_width (layout, -1);
- pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
- pango_layout_get_size (layout, NULL, &layout_height);
- text_height = (gdouble) layout_height / PANGO_SCALE;
-
- cairo_move_to (cr, 0, (HEADER_HEIGHT - text_height) / 2);
- pango_cairo_show_layout (cr, layout);
-
- pango_layout_set_text (layout, pd->lines[ 2 ], -1); // layout title
- pango_layout_get_size (layout, &text_width, NULL);
- pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
-
- cairo_move_to (cr, width - (text_width / PANGO_SCALE),
- (HEADER_HEIGHT - text_height) / 2);
- pango_cairo_show_layout (cr, layout);
-
- /* Render the column header */
- cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP + pd->font_size + 3 );
- pango_layout_set_text (layout, pd->lines[ 6 ], -1);
- pango_cairo_show_layout (cr, layout);
- cairo_rel_move_to (cr, 0, pd->font_size + 3 );
- pango_layout_set_text (layout, pd->lines[ 7 ], -1);
- pango_cairo_show_layout (cr, layout);
-
- /* Render the page text with the specified font and size. */
- cairo_rel_move_to (cr, 0, pd->font_size + 3 );
- line = page_nr * pd->lines_per_page + 8;
- for (i = 0; i < pd->lines_per_page && line < pd->total_lines; i++)
- {
- pango_layout_set_text (layout, pd->lines[line], -1);
- pango_cairo_show_layout (cr, layout);
- cairo_rel_move_to (cr, 0, pd->font_size + 3);
- line++;
- }
-
- /*
- * Render the footer line with date on the left and page number
- * on the right
- */
- pango_layout_set_text (layout, pd->lines[ 5 ], -1); // date
- pango_layout_set_width (layout, -1);
- pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
- pango_layout_get_size (layout, NULL, &layout_height);
- text_height = (gdouble) layout_height / PANGO_SCALE;
-
- height = gtk_print_context_get_height (context);
- cairo_move_to (cr, 0, height - ((HEADER_HEIGHT - text_height) / 2));
- pango_cairo_show_layout (cr, layout);
-
- page_str = g_strdup_printf (_("%d of %d"), page_nr + 1, pd->total_pages); // page number
- pango_layout_set_text( layout, page_str, -1 );
- pango_layout_get_size (layout, &text_width, NULL);
- pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
-
- cairo_move_to (cr, width - (text_width / PANGO_SCALE),
- height - ((HEADER_HEIGHT - text_height) / 2));
- pango_cairo_show_layout (cr, layout);
-
- g_free (page_str);
- g_object_unref (layout);
- pango_font_description_free (desc);
-}
-
-/**
- * Clean up after the printing operation since it is done.
- *
- * \param operation IN the GTK print operation
- * \param context IN print context
- * \param pd IN data structure for user data
- *
- *
- */
-static void
-end_print (GtkPrintOperation *operation,
- GtkPrintContext *context,
- struct PrintData *pd)
-{
- g_strfreev (pd->lines);
- free( pd );
-}
-
-/**
- * Print the content of a multi line text box. This function is only used
- * for printing the parts list. So it makes some assumptions on the structure
- * and the content. Change if the multi line entry is changed.
- * The deprecated gtk_text is not supported by this function.
- *
- * Thanks to Andrew Krause's book for a good starting point.
- *
- * \param bt IN the text field
- * \return TRUE on success, FALSE on error
- */
-
-EXPORT wBool_t wTextPrint(
- wText_p bt )
-{
- GtkPrintOperation *operation;
- GtkWidget *dialog;
- GError *error = NULL;
- gint res;
- struct PrintData *data;
-
- /* Create a new print operation, applying saved print settings if they exist. */
- operation = gtk_print_operation_new ();
- WlibApplySettings( operation );
-
- data = malloc(sizeof( struct PrintData));
- data->font_size = 10.0;
- data->tb = bt;
-
- g_signal_connect (G_OBJECT (operation), "begin_print",
- G_CALLBACK (begin_print), (gpointer) data);
- g_signal_connect (G_OBJECT (operation), "draw_page",
- G_CALLBACK (draw_page), (gpointer) data);
- g_signal_connect (G_OBJECT (operation), "end_print",
- G_CALLBACK (end_print), (gpointer) data);
-
- /* Run the default print operation that will print the selected file. */
- res = gtk_print_operation_run (operation, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
- GTK_WINDOW(gtkMainW->gtkwin), &error);
-
- /* If the print operation was accepted, save the new print settings. */
- if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
- {
- WlibSaveSettings( operation );
- }
- /* Otherwise, report that the print operation has failed. */
- else if (error)
- {
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- error->message);
-
- g_error_free (error);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- }
- g_object_unref (operation);
-
- return TRUE;
-}
-
-
-EXPORT int wTextGetSize(
- wText_p bt )
-{
-#ifdef USE_TEXTVIEW
- char * cp = gtkGetText( bt );
- int len = strlen( cp );
- free( cp );
- return len;
-#else
- return (int)gtk_text_get_length( GTK_TEXT(bt->text) );
-#endif
-}
-
-
-EXPORT void wTextGetText(
- wText_p bt,
- char * text,
- int len )
-{
- char * cp;
-#ifdef USE_TEXTVIEW
- cp = gtkGetText(bt);
- strncpy( text, cp, len );
- free( cp );
-#else
- cp = gtk_editable_get_chars( GTK_EDITABLE(bt->text), 0, len );
- strncpy( text, cp, len );
-#endif
-}
-
-
-EXPORT void wTextSetReadonly (
- wText_p bt,
- wBool_t ro )
-{
-#ifdef USE_TEXTVIEW
- gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), !ro );
-#else
- gtk_text_set_editable( GTK_TEXT(bt->text), !ro );
-#endif
- if (ro) {
- bt->option |= BO_READONLY;
- } else {
- bt->option &= ~BO_READONLY;
- }
-}
-
-
-EXPORT wBool_t wTextGetModified(
- wText_p bt )
-{
- return bt->changed;
-}
-
-
-EXPORT void wTextSetSize(
- wText_p bt,
- wPos_t w,
- wPos_t h )
-{
-#ifdef USE_TEXTVIEW
- gtk_widget_set_size_request( bt->widget, w, h );
-// gtk_widget_set_size_request( bt->text, w-15, h );
-// gtk_widget_set_size_request( bt->vscroll, 15, h );
-#else
- gtk_widget_set_usize( bt->widget, w, h );
- gtk_widget_set_usize( bt->text, w-15, h );
- gtk_widget_set_usize( bt->vscroll, 15, h );
- gtk_widget_queue_resize( GTK_WIDGET(bt->widget) );
- gtk_widget_queue_resize( GTK_WIDGET(bt->text) );
- gtk_widget_queue_resize( GTK_WIDGET(bt->vscroll) );
-#endif
- bt->w = w;
- bt->h = h;
-}
-
-
-EXPORT void wTextComputeSize(
- wText_p bt,
- int rows,
- int cols,
- wPos_t *width,
- wPos_t *height )
-{
- *width = rows * 7;
- *height = cols * 14;
-}
-
-
-EXPORT void wTextSetPosition(
- wText_p bt,
- int pos )
-{
-#ifdef USE_TEXTVIEW
- /* TODO */
-#else
- GTK_TEXT(bt->text)->first_line_start_index = pos;
- gtk_text_set_word_wrap( GTK_TEXT(bt->text), TRUE );
- gtk_text_set_point( GTK_TEXT(bt->text), pos );
-#endif
-}
-
-static void textChanged(
- GtkWidget * widget,
- wText_p bt )
-{
- if (bt == 0)
- return;
- bt->changed = TRUE;
-}
-
-
-EXPORT wText_p wTextCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- long option,
- wPos_t width,
- wPos_t height )
-{
- wText_p bt;
-#ifdef USE_TEXTVIEW
- GtkTextBuffer * tb;
-#else
- GtkRequisition requisition;
-#endif
- bt = gtkAlloc( parent, B_MULTITEXT, x, y, labelStr, sizeof *bt, NULL );
- gtkComputePos( (wControl_p)bt );
- bt->width = width;
- bt->height = height;
- bt->option = option;
- gtkComputePos( (wControl_p)bt );
-
-#ifdef USE_TEXTVIEW
- bt->widget = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bt->widget),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
- bt->text = gtk_text_view_new();
- if (bt->text == 0) abort();
- gtk_container_add (GTK_CONTAINER (bt->widget), bt->text);
- tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(bt->text) );
- gtk_text_buffer_create_tag( tb, "bold", "weight", PANGO_WEIGHT_BOLD, NULL);
-/* gtk_text_buffer_create_tag( tb, "italic", "style", PANGO_STYLE_ITALIC, NULL); */
-/* gtk_text_buffer_create_tag( tb, "bolditalic", "weight", PANGO_WEIGHT_BOLD, "style", PANGO_STYLE_ITALIC, NULL); */
- bt->vscroll = gtk_vscrollbar_new( GTK_TEXT_VIEW(bt->text)->vadjustment );
- if (bt->vscroll == 0) abort();
-#else
- bt->widget = gtk_hbox_new( FALSE, 0 );
- bt->text = gtk_text_new( NULL, NULL );
- if (bt->text == 0) abort();
- gtk_box_pack_start( GTK_BOX(bt->widget), bt->text, FALSE, FALSE, 0 );
- bt->vscroll = gtk_vscrollbar_new( GTK_TEXT(bt->text)->vadj );
- if (bt->vscroll == 0) abort();
- gtk_box_pack_start( GTK_BOX(bt->widget), bt->vscroll, FALSE, FALSE, 0 );
-#endif
- if (option&BT_CHARUNITS) {
- width *= 7;
- height *= 14;
- }
- gtk_widget_show( bt->text );
- gtk_widget_show( bt->vscroll );
- gtk_widget_show( bt->widget );
-#ifdef USE_TEXTVIEW
-// gtk_widget_set_size_request( GTK_WIDGET(bt->text), width, height );
-// gtk_widget_set_size_request( GTK_WIDGET(bt->vscroll), -1, height );
- gtk_widget_set_size_request( GTK_WIDGET(bt->widget), width+15/*requisition.width*/, height );
-#else
- gtk_widget_set_usize( GTK_WIDGET(bt->text), width, height );
- gtk_widget_set_usize( GTK_WIDGET(bt->vscroll), -1, height );
- gtk_widget_size_request( GTK_WIDGET(bt->vscroll), &requisition );
- gtk_widget_set_usize( GTK_WIDGET(bt->widget), width+15/*requisition.width*/, height );
-#endif
- if (bt->option&BO_READONLY) {
-#ifdef USE_TEXTVIEW
- gtk_text_view_set_editable( GTK_TEXT_VIEW(bt->text), FALSE );
- gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(bt->text), FALSE);
-#else
- gtk_text_set_editable( GTK_TEXT(bt->text), FALSE );
-#endif
- }
-
-#ifdef USE_TEXTVIEW
- gtk_fixed_put( GTK_FIXED(parent->widget), bt->widget, bt->realX, bt->realY );
-#else
- gtk_container_add( GTK_CONTAINER(parent->widget), bt->widget );
- gtk_widget_set_uposition( bt->widget, bt->realX, bt->realY );
-#endif
- gtkControlGetSize( (wControl_p)bt );
- if (labelStr)
- bt->labelW = gtkAddLabel( (wControl_p)bt, labelStr );
-#ifdef USE_TEXTVIEW
- gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(bt->text), GTK_WRAP_WORD );
-#else
- gtk_text_set_word_wrap( GTK_TEXT(bt->text), TRUE );
-#endif
- gtk_widget_realize( bt->text );
- gtkAddButton( (wControl_p)bt );
- gtkAddHelpString( bt->widget, helpStr );
-#ifdef USE_TEXTVIEW
- g_signal_connect( G_OBJECT(tb), "changed", GTK_SIGNAL_FUNC(textChanged), bt );
-#else
- gtk_signal_connect( GTK_OBJECT(bt->text), "changed", GTK_SIGNAL_FUNC(textChanged), bt );
-#endif
- return bt;
-}
diff --git a/app/wlib/gtklib/gtkwindow.c b/app/wlib/gtklib/gtkwindow.c
deleted file mode 100644
index b86b173..0000000
--- a/app/wlib/gtklib/gtkwindow.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/** \file gtkwindow.c
- * Basic window handling stuff.
- *
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/gtkwindow.c,v 1.12 2010-04-28 04:04:38 dspagnol Exp $
- */
-
-/* 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 <stdlib.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-
-#include "gtkint.h"
-
-wWin_p gtkMainW;
-
-#define FOUR (4)
-#define MENUH (24)
-
-#define MIN_WIN_WIDTH (50)
-#define MIN_WIN_HEIGHT (50)
-
-#define SECTIONWINDOWSIZE "gtklib window size"
-#define SECTIONWINDOWPOS "gtklib window pos"
-
-extern wBool_t listHelpStrings;
-
-static wControl_p firstWin = NULL, lastWin;
-static int keyState;
-static wBool_t gtkBlockEnabled = TRUE;
-
-/*
- *****************************************************************************
- *
- * Window Utilities
- *
- *****************************************************************************
- */
-
-/**
- * Get the window size from the resource (.rc) file. The size is saved under the key
- * SECTIONWINDOWSIZE.window name
- *
- * \param win IN window
- * \param nameStr IN window name
- */
-
-static void getWinSize( wWin_p win, const char * nameStr )
-{
- int w, h;
- const char *cp;
- char *cp1, *cp2;
-
- if ( (win->option&F_RESIZE) &&
- (win->option&F_RECALLPOS) &&
- (cp = wPrefGetString( SECTIONWINDOWSIZE, nameStr)) &&
- (w = strtod( cp, &cp1 ), cp != cp1) &&
- (h = strtod( cp1, &cp2 ), cp1 != cp2) ) {
- if (w < 10)
- w = 10;
- if (h < 10)
- h = 10;
- win->w = win->origX = w;
- win->h = win->origY = h;
- win->option &= ~F_AUTOSIZE;
- }
-}
-
-/**
- * Save the window size to the resource (.rc) file. The size is saved under the key
- * SECTIONWINDOWSIZE.window name
- *
- * \param win IN window
- */
-
-static void saveSize( wWin_p win )
-{
- char pos_s[20];
- if ( (win->option&F_RESIZE) &&
- (win->option&F_RECALLPOS) &&
- GTK_WIDGET_VISIBLE( GTK_WIDGET(win->gtkwin) ) ) {
- sprintf( pos_s, "%d %d", win->w, win->h-(FOUR + ((win->option&F_MENUBAR)?MENUH:0) ) );
- wPrefSetString( SECTIONWINDOWSIZE, win->nameStr, pos_s );
- }
-}
-
-/**
- * Get the window position from the resource (.rc) file. The position is saved under the key
- * SECTIONWINDOWPOS.window name
- *
- * \param win IN window
- */
-
-static void getPos( wWin_p win )
-{
- int x, y;
- const char *cp;
- char *cp1, *cp2;
- wPos_t gtkDisplayWidth = gdk_screen_width();
- wPos_t gtkDisplayHeight = gdk_screen_height();
-
- if ( (win->option&F_RECALLPOS) &&
- (!win->shown) ) {
- if ((cp = wPrefGetString( SECTIONWINDOWPOS, win->nameStr))) {
- x = strtod( cp, &cp1 );
- if (cp == cp1)
- return;
- y = strtod( cp1, &cp2 );
- if (cp2 == cp1)
- return;
- if ( y > gtkDisplayHeight-win->h )
- y = gtkDisplayHeight-win->h;
- if ( x > gtkDisplayWidth-win->w )
- x = gtkDisplayWidth-win->w;
- if ( x <= 0 )
- x = 1;
- if ( y <= 0 )
- y = 1;
- gtk_window_move( GTK_WINDOW(win->gtkwin), x, y );
- gtk_window_resize( GTK_WINDOW(win->gtkwin), win->w, win->h );
- }
- }
-}
-
-/**
- * Save the window position to the resource (.rc) file. The position is saved under the key
- * SECTIONWINDOWPOS.window name
- *
- * \param win IN window
- */
-
-static void savePos( wWin_p win )
-{
- int x, y;
- char pos_s[20];
- if ( (win->option&F_RECALLPOS) ) {
- gdk_window_get_position( GTK_WIDGET(win->gtkwin)->window, &x, &y );
- x -= 5;
- y -= 25;
- sprintf( pos_s, "%d %d", x, y );
- wPrefSetString( SECTIONWINDOWPOS, win->nameStr, pos_s );
- }
-}
-
-/**
- * Returns the dimensions of <win>.
- *
- * \param win IN window handle
- * \param width OUT width of window
- * \param height OUT height of window minus menu bar size
- */
-
-EXPORT void wWinGetSize(
- wWin_p win, /* Window */
- wPos_t * width, /* Returned window width */
- wPos_t * height ) /* Returned window height */
-{
- GtkRequisition requisition;
- wPos_t w, h;
- gtk_widget_size_request( win->gtkwin, &requisition );
- w = win->w;
- h = win->h;
- if ( win->option&F_AUTOSIZE ) {
- if ( win->realX > w )
- w = win->realX;
- if ( win->realY > h )
- h = win->realY;
- }
- *width = w;
- *height = h - FOUR - ((win->option&F_MENUBAR)?MENUH:0);
-}
-
-/**
- * Sets the dimensions of <w> to <widht> and <height>.
- *
- * \param win IN window
- * \param width IN new width
- * \param height IN new height
- */
-
-EXPORT void wWinSetSize(
- wWin_p win, /* Window */
- wPos_t width, /* Window width */
- wPos_t height ) /* Window height */
-{
- win->busy = TRUE;
- win->w = width;
- win->h = height + FOUR + ((win->option&F_MENUBAR)?MENUH:0);
- gtk_widget_set_size_request( win->gtkwin, win->w, win->h );
- gtk_widget_set_size_request( win->widget, win->w, win->h );
- win->busy = FALSE;
-
-}
-
-/**
- * Shows or hides window <win>. If <win> is created with 'F_BLOCK' option then the applications other
- * windows are disabled and 'wWinShow' doesnot return until the window <win> is closed by calling
- * 'wWinShow(<win>,FALSE)'.
- *
- * \param win IN window
- * \param show IN visibility state
- */
-
-EXPORT void wWinShow(
- wWin_p win, /* Window */
- wBool_t show ) /* Command */
-{
- GtkRequisition requisition;
- if (debugWindow >= 2) printf("Set Show %s\n", win->labelStr?win->labelStr:"No label" );
- if (win->widget == 0) abort();
- if (show) {
- keyState = 0;
- getPos( win );
- if ( win->option & F_AUTOSIZE ) {
- gtk_widget_size_request( win->gtkwin, &requisition );
- if ( requisition.width != win->w || requisition.height != win->h ) {
- gtk_widget_set_size_request( win->gtkwin, win->w, win->h );
- gtk_widget_set_size_request( win->widget, win->w, win->h );
- if (win->option&F_MENUBAR) {
- gtk_widget_set_size_request( win->menubar, win->w, MENUH );
- }
- }
- }
- if ( !win->shown ) {
- gtk_widget_show( win->gtkwin );
- gtk_widget_show( win->widget );
- }
- gdk_window_raise( win->gtkwin->window );
- if ( win->shown && win->modalLevel > 0 )
- gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), TRUE );
- win->shown = show;
- win->modalLevel = 0;
-
- if ( (!gtkBlockEnabled) || (win->option & F_BLOCK) == 0) {
- wFlush();
- } else {
- gtkDoModal( win, TRUE );
- }
- } else {
- wFlush();
- saveSize( win );
- savePos( win );
- win->shown = show;
- if ( gtkBlockEnabled && (win->option & F_BLOCK) != 0) {
- gtkDoModal( win, FALSE );
- }
- gtk_widget_hide( win->gtkwin );
- gtk_widget_hide( win->widget );
- }
-}
-
-/**
- * Block windows against user interactions. Done during demo mode etc.
- *
- * \param enabled IN blocked if TRUE
- */
-
-EXPORT void wWinBlockEnable(
- wBool_t enabled )
-{
- gtkBlockEnabled = enabled;
-}
-
-/**
- * Returns whether the window is visible.
- *
- * \param win IN window
- * \return TRUE if visible, FALSE otherwise
- */
-
-EXPORT wBool_t wWinIsVisible(
- wWin_p win )
-{
- return win->shown;
-}
-
-/**
- * Sets the title of <win> to <title>.
- *
- * \param varname1 IN window
- * \param varname2 IN new title
- */
-
-EXPORT void wWinSetTitle(
- wWin_p win, /* Window */
- const char * title ) /* New title */
-{
- gtk_window_set_title( GTK_WINDOW(win->gtkwin), title );
-}
-
-/**
- * Sets the window <win> to busy or not busy. Sets the cursor accordingly
- *
- * \param varname1 IN window
- * \param varname2 IN TRUE if busy, FALSE otherwise
- */
-
-EXPORT void wWinSetBusy(
- wWin_p win, /* Window */
- wBool_t busy ) /* Command */
-{
- GdkCursor * cursor;
- if (win->gtkwin == 0) abort();
- if ( busy )
- cursor = gdk_cursor_new ( GDK_WATCH );
- else
- cursor = NULL;
- gdk_window_set_cursor (win->gtkwin->window, cursor);
- if ( cursor )
- gdk_cursor_destroy (cursor);
- gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), busy==0 );
-}
-
-
-EXPORT void gtkDoModal(
- wWin_p win0,
- wBool_t modal )
-{
- wWin_p win;
- for ( win=(wWin_p)firstWin; win; win=(wWin_p)win->next ) {
- if ( win->shown && win != win0 ) {
- if ( modal ) {
- if ( win->modalLevel == 0 )
- gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), FALSE );
- win->modalLevel++;
- } else {
- if ( win->modalLevel > 0 ) {
- win->modalLevel--;
- if ( win->modalLevel == 0 )
- gtk_widget_set_sensitive( GTK_WIDGET(win->gtkwin), TRUE );
- }
- }
- if ( win->modalLevel < 0 ) {
- fprintf( stderr, "DoModal: %s modalLevel < 0", win->nameStr?win->nameStr:"<NULL>" );
- abort();
- }
- }
- }
- if ( modal ) {
- gtk_main();
- } else {
- gtk_main_quit();
- }
-}
-
-/**
- * Returns the Title of <win>.
- *
- * \param win IN window
- * \return pointer to window title
- */
-
-EXPORT const char * wWinGetTitle(
- wWin_p win ) /* Window */
-{
- return win->labelStr;
-}
-
-
-EXPORT void wWinClear(
- wWin_p win,
- wPos_t x,
- wPos_t y,
- wPos_t width,
- wPos_t height )
-{
-}
-
-
-EXPORT void wWinDoCancel(
- wWin_p win )
-{
- wControl_p b;
- for (b=win->first; b; b=b->next) {
- if ((b->type == B_BUTTON) && (b->option & BB_CANCEL) ) {
- gtkButtonDoAction( (wButton_p)b );
- }
- }
-}
-
-/*
- ******************************************************************************
- *
- * Call Backs
- *
- ******************************************************************************
- */
-
-static gint window_delete_event(
- GtkWidget *widget,
- GdkEvent *event,
- wWin_p win )
-{
- wControl_p b;
- /* if you return FALSE in the "delete_event" signal handler,
- * GTK will emit the "destroy" signal. Returning TRUE means
- * you don't want the window to be destroyed.
- * This is useful for popping up 'are you sure you want to quit ?'
- * type dialogs. */
-
- /* Change TRUE to FALSE and the main window will be destroyed with
- * a "delete_event". */
-
- for ( b = win->first; b; b=b->next )
- if (b->doneProc)
- b->doneProc( b );
- if (win->winProc) {
- win->winProc( win, wClose_e, win->data );
- if (win != gtkMainW)
- wWinShow( win, FALSE );
- }
- return (TRUE);
-}
-
-static int window_redraw(
- wWin_p win,
- wBool_t doWinProc )
-{
- wControl_p b;
-
- if (win==NULL)
- return FALSE;
-
- for (b=win->first; b != NULL; b = b->next) {
- if (b->repaintProc)
- b->repaintProc( b );
- }
-
- return FALSE;
-}
-
-static int fixed_expose_event(
- GtkWidget * widget,
- GdkEventExpose * event,
- wWin_p win )
-{
- if (event->count==0)
- return window_redraw( win, TRUE );
- else
- return FALSE;
-}
-
-static int window_configure_event(
- GtkWidget * widget,
- GdkEventConfigure * event,
- wWin_p win )
-{
- wPos_t h;
-
- if (win==NULL)
- return FALSE;
-
- h = event->height - FOUR;
- if (win->option&F_MENUBAR)
- h -= MENUH;
- if (win->option&F_RESIZE) {
- if ( event->width < 10 || event->height < 10 )
- return TRUE;
- if (win->w != event->width || win->h != event->height) {
- win->w = event->width;
- win->h = event->height;
- if ( win->w < MIN_WIN_WIDTH )
- win->w = MIN_WIN_WIDTH;
- if ( win->h < MIN_WIN_HEIGHT )
- win->h = MIN_WIN_HEIGHT;
- if (win->option&F_MENUBAR)
- gtk_widget_set_size_request( win->menubar, win->w, MENUH );
-
- if (win->busy==FALSE && win->winProc) {
- win->winProc( win, wResize_e, win->data );
- }
- }
- }
- return FALSE;
-}
-
-/**
- * Get current state of shift, ctrl or alt keys.
- *
- * \return or'ed value of WKEY_SHIFT, WKEY_CTRL and WKEY_ALT depending on state
- */
-
-int wGetKeyState( void )
-{
- return keyState;
-}
-
-wBool_t catch_shift_ctrl_alt_keys(
- GtkWidget * widget,
- GdkEventKey *event,
- void * data )
-{
- int state;
-
- state = 0;
- switch (event->keyval) {
- case GDK_Shift_L:
- case GDK_Shift_R:
- state |= WKEY_SHIFT;
- break;
- case GDK_Control_L:
- case GDK_Control_R:
- state |= WKEY_CTRL;
- break;
- case GDK_Alt_L:
- case GDK_Alt_R:
- state |= WKEY_ALT;
- break;
- }
- if ( state != 0 ) {
- if (event->type == GDK_KEY_PRESS)
- keyState |= state;
- else
- keyState &= ~state;
- return TRUE;
- }
- return FALSE;
-}
-
-static gint window_char_event(
- GtkWidget * widget,
- GdkEventKey *event,
- wWin_p win )
-{
- wControl_p bb;
- if ( catch_shift_ctrl_alt_keys( widget, event, win ) )
- return FALSE;
- if (event->type == GDK_KEY_RELEASE)
- return FALSE;
-
- if ( event->state == 0 ) {
- if ( event->keyval == GDK_Escape ) {
- for ( bb=win->first; bb; bb=bb->next ) {
- if ( bb->type == B_BUTTON && (bb->option&BB_CANCEL) ) {
- gtkButtonDoAction( (wButton_p)bb );
- return TRUE;
- }
- }
- }
- }
- if ( gtkHandleAccelKey( event ) ) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-
-/*
- *******************************************************************************
- *
- * Main and Popup Windows
- *
- *******************************************************************************
- */
-
-
-
-static wWin_p wWinCommonCreate(
- wWin_p parent,
- int winType,
- wPos_t x,
- wPos_t y,
- const char * labelStr,
- const char * nameStr,
- long option,
- wWinCallBack_p winProc,
- void * data )
-{
- wWin_p w;
- int h;
-
- w = gtkAlloc( NULL, winType, x, y, labelStr, sizeof *w, data );
- w->busy = TRUE;
- w->option = option;
- getWinSize( w, nameStr );
-
- h = FOUR;
- if (w->option&F_MENUBAR)
- h += MENUH;
-
- if ( winType == W_MAIN ) {
- w->gtkwin = gtk_window_new( GTK_WINDOW_TOPLEVEL );
- } else {
- w->gtkwin = gtk_window_new( GTK_WINDOW_TOPLEVEL );
- if ( gtkMainW )
- gtk_window_set_transient_for( GTK_WINDOW(w->gtkwin), GTK_WINDOW(gtkMainW->gtkwin) );
- }
-
- if( option & F_HIDE )
- gtk_widget_hide( w->gtkwin );
-
- /* center window on top of parent window */
- if( option & F_CENTER )
- gtk_window_set_position(GTK_WINDOW(w->gtkwin), GTK_WIN_POS_CENTER_ON_PARENT );
-
- w->widget = gtk_fixed_new();
- if (w->widget == 0) abort();
-
- if (w->option&F_MENUBAR) {
- w->menubar = gtk_menu_bar_new();
- gtk_container_add( GTK_CONTAINER(w->widget), w->menubar );
- gtk_widget_show( w->menubar );
- gtk_widget_set_size_request( w->menubar, -1, MENUH );
- }
-
- gtk_container_add( GTK_CONTAINER(w->gtkwin), w->widget );
-
- if (w->option&F_AUTOSIZE) {
- w->realX = 0;
- w->w = 0;
- w->realY = h;
- w->h = 0;
- } else {
- w->w = w->realX = w->origX;
- w->h = w->realY = w->origY+h;
- gtk_widget_set_size_request( w->gtkwin, w->w, w->h );
- gtk_widget_set_size_request( w->widget, w->w, w->h );
- if (w->option&F_MENUBAR) {
- gtk_widget_set_size_request( w->menubar, w->w, MENUH );
- }
- }
-
- w->first = w->last = NULL;
-
- w->winProc = winProc;
-
- gtk_signal_connect (GTK_OBJECT (w->gtkwin), "delete_event",
- GTK_SIGNAL_FUNC (window_delete_event), w);
- gtk_signal_connect (GTK_OBJECT (w->widget), "expose_event",
- GTK_SIGNAL_FUNC (fixed_expose_event), w);
- gtk_signal_connect (GTK_OBJECT (w->gtkwin), "configure_event",
- GTK_SIGNAL_FUNC (window_configure_event), w);
- gtk_signal_connect (GTK_OBJECT (w->gtkwin), "key_press_event",
- GTK_SIGNAL_FUNC (window_char_event), w);
- gtk_signal_connect (GTK_OBJECT (w->gtkwin), "key_release_event",
- GTK_SIGNAL_FUNC (window_char_event), w);
- gtk_widget_set_events (w->widget, GDK_EXPOSURE_MASK );
- gtk_widget_set_events ( GTK_WIDGET(w->gtkwin), GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK );
-
- /**
- * \todo { set_policy is deprecated and should be replaced by set_resizable. In order to do that
- * the library has to be cleared up from calls to set_size_request as these set the minimum widget size
- * to the current size preventing the user from re-sizing the window to a smaller size. At least this
- * is my current assumption ;-) }
- */
- if (w->option & F_RESIZE) {
- gtk_window_set_policy( GTK_WINDOW(w->gtkwin), TRUE, TRUE, TRUE );
-// gtk_window_set_resizable( GTK_WINDOW(w->gtkwin), TRUE );
- } else {
-// gtk_window_set_resizable( GTK_WINDOW(w->gtkwin), FALSE );
- gtk_window_set_policy( GTK_WINDOW(w->gtkwin), FALSE, FALSE, TRUE );
- }
-
- w->lastX = 0;
- w->lastY = h;
- w->shown = FALSE;
- w->nameStr = nameStr?strdup( nameStr ):NULL;
- if (labelStr)
- gtk_window_set_title( GTK_WINDOW(w->gtkwin), labelStr );
- if (listHelpStrings)
- printf( "WINDOW - %s\n", nameStr?nameStr:"<NULL>" );
-
- if (firstWin) {
- lastWin->next = (wControl_p)w;
- } else {
- firstWin = (wControl_p)w;
- }
- lastWin = (wControl_p)w;
- gtk_widget_show( w->widget );
- gtk_widget_realize( w->gtkwin );
-
- w->busy = FALSE;
- return w;
-}
-
-/**
- * \todo { investigate and implement this function for setting the correct icon as necessary.
- * It looks like these functions are never called at the moment. }
- */
-
-EXPORT void wWinSetBigIcon(
- wWin_p win, /* Main window */
- wIcon_p ip ) /* The icon */
-/*
-Create an Icon from a X-bitmap.
-*/
-{
-#ifdef LATER
- GdkPixmap * pixmap;
- GdkBitmap * mask;
- pixmap = gtkMakeIcon( win->gtkwin, ip, &mask );
- gdk_window_set_icon( win->gtkwin->window, NULL, pixmap, mask );
- gdk_pixmap_unref( pixmap );
- gdk_bitmap_unref( mask );
-#endif
-}
-
-
-/**
- * \todo { investigate and implement this function for setting the correct icon as necessary.
- * It looks like these functions are never called at the moment. }
- */
-
-
-EXPORT void wWinSetSmallIcon(
- wWin_p win, /* Main window */
- wIcon_p ip ) /* The icon */
-/*
-Create an Icon from a X-bitmap.
-*/
-{
- GdkBitmap * mask;
- if ( ip->gtkIconType == gtkIcon_bitmap ) {
- mask = gdk_bitmap_create_from_data( win->gtkwin->window, ip->bits, ip->w, ip->h );
- gdk_window_set_icon( win->gtkwin->window, NULL, mask, mask );
- /*gdk_bitmap_unref( mask );*/
- }
-}
-
-/**
- * Initialize the application's main window. This function does the necessary initialization
- * of the application including creation of the main window.
- *
- * \param name IN internal name of the application. Used for filenames etc.
- * \param x IN Initial window width
- * \param y IN Initial window height
- * \param helpStr IN Help topic string
- * \param labelStr IN window title
- * \param nameStr IN Window name
- * \param option IN options for window creation
- * \param winProc IN pointer to main window procedure
- * \param data IN User context
- * \return window handle or NULL on error
- */
-
-EXPORT wWin_p wWinMainCreate(
- const char * name, /* Application name */
- wPos_t x, /* Initial window width */
- wPos_t y, /* Initial window height */
- const char * helpStr, /* Help topic string */
- const char * labelStr, /* Window title */
- const char * nameStr, /* Window name */
- long option, /* Options */
- wWinCallBack_p winProc, /* Call back function */
- void * data ) /* User context */
-{
- char *pos;
-
- if( pos = strchr( name, ';' )) {
- /* if found, split application name and configuration name */
- strcpy( wConfigName, pos + 1 );
- } else {
- /* if not found, application name and configuration name are same */
- strcpy( wConfigName, name );
- }
-
- gtkMainW = wWinCommonCreate( NULL, W_MAIN, x, y, labelStr, nameStr, option, winProc, data );
-
- wDrawColorWhite = wDrawFindColor( 0xFFFFFF );
- wDrawColorBlack = wDrawFindColor( 0x000000 );
-
- gdk_window_set_group( gtkMainW->gtkwin->window, gtkMainW->gtkwin->window );
- return gtkMainW;
-}
-
-/**
- * Create a new popup window.
- *
- * \param parent IN Parent window (may be NULL)
- * \param x IN Initial window width
- * \param y IN Initial window height
- * \param helpStr IN Help topic string
- * \param labelStr IN Window title
- * \param nameStr IN Window name
- * \param option IN Options
- * \param winProc IN call back function
- * \param data IN User context information
- * \return handle for new window
- */
-
-EXPORT wWin_p wWinPopupCreate(
- wWin_p parent,
- wPos_t x,
- wPos_t y,
- const char * helpStr,
- const char * labelStr,
- const char * nameStr,
- long option,
- wWinCallBack_p winProc,
- void * data )
-{
- wWin_p win;
-
- if (parent == NULL) {
- if (gtkMainW == NULL)
- abort();
- parent = gtkMainW;
- }
- win = wWinCommonCreate( parent, W_POPUP, x, y, labelStr, nameStr, option, winProc, data );
- gdk_window_set_group( win->gtkwin->window, gtkMainW->gtkwin->window );
-
- return win;
-}
-
-
-/**
- * Terminates the applicaton with code <rc>. Before closing the main window
- * call back is called with wQuit_e. The program is terminated without exiting
- * the main message loop.
- *
- * \param rc IN exit code
- * \return never returns
- */
-
-
-EXPORT void wExit(
- int rc ) /* Application return code */
-{
- wWin_p win;
- for ( win = (wWin_p)firstWin; win; win = (wWin_p)win->next ) {
- if ( GTK_WIDGET_VISIBLE( GTK_WIDGET(win->gtkwin) ) ) {
- saveSize( win );
- savePos( win );
- }
- }
- wPrefFlush();
- if (gtkMainW && gtkMainW->winProc != NULL)
- gtkMainW->winProc( gtkMainW, wQuit_e, gtkMainW->data );
-
- exit( rc );
-}
diff --git a/app/wlib/gtklib/gtkxpm.c b/app/wlib/gtklib/gtkxpm.c
deleted file mode 100644
index 54ce5a6..0000000
--- a/app/wlib/gtklib/gtkxpm.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/** \file gtkxpm.c
- * XPM creation functions
- */
-
-/* XTrackCad - 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.
- */
-
- #include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include "gtkint.h"
-
- #include "uthash.h"
-
-struct xpmColTable {
- int color; /* color value (rgb) */
- char name[ 5 ]; /* corresponding character representation */
- UT_hash_handle hh; /* makes this structure hashable */
-};
-
-static struct xpmColTable *colTable = NULL;
-
-// must be 64 chars long
-static char colVal[] = ".*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-//struct wDraw_t {
- //WOBJ_COMMON
- //void * context;
- //wDrawActionCallBack_p action;
- //wDrawRedrawCallBack_p redraw;
-
- //double dpi;
-
- //GdkGC * gc;
- //wDrawWidth lineWidth;
- //wDrawOpts opts;
- //wPos_t maxW;
- //wPos_t maxH;
- //unsigned long lastColor;
- //wBool_t lastColorInverted;
- //const char * helpStr;
-
- //wPos_t lastX;
- //wPos_t lastY;
-
- //wBool_t delayUpdate;
- //};
-
- /**
- * Export as XPM bitmap file. During creation of the color table, a 4 byte color
- * encoding is assumed and a table created accordingly. Once the whole picture has been scanned
- * the correct number ist known. When writing to disk only the needed number of bytes per entry
- * is written.
- * This routine was heavily inspired by on implementation for TK written by Jan Nijtmans.
- *
- * \param d IN the drawing area ?
- * \param fileName IN fully qualified filename for the bitmap file.
- * \return TRUE on success, FALSE on error
- */
-
-wBool_t wBitMapWriteFile( wDraw_p d, const char * fileName )
-{
- GdkImage * image;
- gint x, y;
- guint32 pixel;
- FILE * f;
- int cc = 0;
- struct xpmColTable *ct, *tmp;
- int numChars;
-
- image = gdk_image_get( (GdkWindow*)d->pixmap, 0, 0, d->w, d->h );
- if (!image) {
- wNoticeEx( NT_ERROR, "WriteBitMap: image_get failed", "Ok", NULL );
- return FALSE;
- }
-
- f = fopen( fileName, "w" );
- if (!f) {
- perror( fileName );
- return FALSE;
- }
- fprintf( f, "/* XPM */\n" );
- fprintf( f, "static char * xtrkcad_bitmap[] = {\n" );
- fprintf( f, "/* width height num_colors chars_per_pixel */\n" );
-
- // count colors used and create the color table in the same pass
- for( y = 0; y < d->h;y ++ ) {
- for (x = 0; x < d->w; x++ ) {
-
- pixel = gdk_image_get_pixel( image, x, y );
- //check whether color is new
-
- HASH_FIND(hh, colTable, &pixel, sizeof( guint32 ), ct);
- if( !ct ) {
- // not found previously, so add a new color table entry
- int i;
- int c;
-
- ct = malloc( sizeof( struct xpmColTable ) );
- ct->name[ 4 ] = '\0';
- for( i = 3, c = cc; i >= 0; i--, c>>=6 ) {
- (ct->name)[ i ] = colVal[ c & 0x3F ];
- }
- ct->color = pixel;
-
- HASH_ADD(hh, colTable, color, sizeof( guint32 ), ct);
- cc++;
- }
- }
- }
-
- // calculate how many characters are needed for the color table
- numChars = 1;
- if( cc > 0x3ffff ) {
- numChars = 4;
- } else {
- if( cc > 0xfff ) {
- numChars = 3;
- } else {
- if( cc > 0x3f ) {
- numChars = 2;
- }
- }
- }
- // print color table
- fprintf( f, "\"%d %d %d %d\"\n", d->w, d->h, cc, numChars );
- fprintf( f, "/* colors */\n" );
- for( ct = colTable; ct != NULL; ct = ct->hh.next )
- fprintf( f, "\"%s c #%6.6x\",\n", (ct->name) + (4 - numChars ), ct->color );
-
- // print the pixels
- fprintf( f, "/* pixels */\n" );
- for ( y=0; y<d->h; y++ ) {
- fprintf( f, "\"" );
- for ( x=0; x<d->w; x++ ) {
- pixel = gdk_image_get_pixel( image, x, y );
- HASH_FIND( hh, colTable, &pixel, sizeof(guint32), ct );
- fputs( (ct->name) + (4 - numChars ), f );
- }
- fprintf( f, "\"%s\n", (y<d->h-1)?",":"" );
- }
-
- // delete the hash and free the content
- HASH_ITER(hh, colTable, ct, tmp) {
- HASH_DEL(colTable,ct);
- free(ct);
- }
-
- gdk_image_destroy( image );
- fprintf( f, "};\n" );
- fclose( f );
- return TRUE;
-}
diff --git a/app/wlib/gtklib/help.c b/app/wlib/gtklib/help.c
new file mode 100644
index 0000000..dbb69f6
--- /dev/null
+++ b/app/wlib/gtklib/help.c
@@ -0,0 +1,69 @@
+/** \file help.c
+ * main help function
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis and (C) 2007 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.
+ */
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+/**
+ * Handle the commands issued from the Help drop-down. Currently, we only have a table
+ * of contents, but search etc. might be added in the future.
+ *
+ * \param data IN command value
+ *
+ */
+
+static void
+DoHelpMenu(void *data)
+{
+ int func = (intptr_t)data;
+
+ switch (func) {
+ case 1:
+ wHelp("index");
+ break;
+
+ default:
+ break;
+ }
+
+ return;
+}
+
+/**
+ * Add the entries for Help to the drop-down.
+ *
+ * \param m IN handle of drop-down
+ *
+ */
+
+void wMenuAddHelp(wMenu_p m)
+{
+ wMenuPushCreate(m, NULL, _("&Contents"), 0, DoHelpMenu, (void*)1);
+}
diff --git a/app/wlib/gtklib/ixhelp.c b/app/wlib/gtklib/ixhelp.c
new file mode 100644
index 0000000..6d85b2b
--- /dev/null
+++ b/app/wlib/gtklib/ixhelp.c
@@ -0,0 +1,441 @@
+/** \file ixhelp.c
+ * use the Webkit2-based 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.
+ */
+
+#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>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+#include <webkit/webkit.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+void load_into_view(char *file,
+ int requested_view); // Prototype to please clang.
+
+/* globals and defines related to the HTML help window */
+
+#define HTMLERRORTEXT "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=US-ASCII\">" \
+ "<title>Help Error</title><body><h1>Error - help information can not be found.</h1><p>" \
+ "The help information you requested cannot be found on this system.<br><pre>%s: %s</pre><p>" \
+ "Usually this is an installation problem, Make sure that XTrackCAD and the included " \
+ "HTML files are installed properly and can be found via the XTRKCADLIB environment " \
+ "variable. Also make sure that the user has sufficient access rights to read these" \
+ "files.</p></body></html>"
+
+
+#define SLIDERPOSDEFAULT 180 /**< default value for slider position */
+
+#define HTMLHELPSECTION "gtklib html help" /**< section name for html help window preferences */
+#define SLIDERPREFNAME "sliderpos" /**< name for the slider position preference */
+#define WINDOWPOSPREFNAME "position" /**< name for the window position preference */
+#define WINDOWSIZEPREFNAME "size" /**< name for the window size preference */
+
+#define BACKBUTTON "back"
+#define FORWARDBUTTON "forward"
+#define HOMEBUTTON "home"
+#define CONTENTBUTTON "contents"
+#define TOCDOC "tocDoc"
+#define CONTENTSDOC "contentsDoc"
+#define TOCVIEW "viewLeft"
+#define CONTENTSVIEW "viewRight"
+#define PANED "hpane"
+
+enum pane_views { MAIN_VIEW, CONTENTS_VIEW };
+
+static char *directory; /**< base directory for HTML files */
+
+static GtkWidget *wHelpWindow; /**< handle for the help window */
+static GtkWidget *main_view; /** handle for the help main data pane */
+static GtkWidget *contents_view; /** handle for the help contents pane */
+
+#define GLADE_HOOKUP_OBJECT(component,widget,name) \
+ g_object_set_data_full (G_OBJECT (component), name, \
+ gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
+
+#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
+ g_object_set_data (G_OBJECT (component), name, widget)
+
+static GtkWidget*
+lookup_widget(GtkWidget *widget, const gchar *widget_name)
+{
+ GtkWidget *parent, *found_widget;
+
+ for (;;) {
+ if (GTK_IS_MENU(widget)) {
+ parent = gtk_menu_get_attach_widget(GTK_MENU(widget));
+ } else {
+ parent = widget->parent;
+ }
+
+ if (!parent) {
+ parent = (GtkWidget*) g_object_get_data(G_OBJECT(widget), "GladeParentKey");
+ }
+
+ if (parent == NULL) {
+ break;
+ }
+
+ widget = parent;
+ }
+
+ found_widget = (GtkWidget*) g_object_get_data(G_OBJECT(widget),
+ widget_name);
+
+ if (!found_widget) {
+ g_warning("Widget not found: %s", widget_name);
+ }
+
+ return found_widget;
+}
+
+
+
+
+/**
+ * create a new horizontal pane and place it into container.
+ * The separator position is read from the resource configuration and set accordingly.
+ * Also a callback is specified that will be executed when the slider has been moved.
+ *
+ * \PARAM container IN the container into which the pane will be stuffed.
+ * \PARAM property IN the name of the property for the slider position
+ *
+ * \return the HPaned handle
+ */
+
+GtkWidget *
+CreateHPaned(GtkBox *container, char *property)
+{
+ GtkWidget *hpaned;
+ long posSlider;
+
+ /* the horizontal slider */
+ hpaned = gtk_hpaned_new();
+ gtk_container_set_border_width(GTK_CONTAINER(hpaned), 6);
+
+ wPrefGetInteger(HTMLHELPSECTION, SLIDERPREFNAME, &posSlider, SLIDERPOSDEFAULT);
+ gtk_paned_set_position(GTK_PANED(hpaned), (int)posSlider);
+
+ /* pack the horizontal slider into the main window */
+ gtk_box_pack_start(container, hpaned, TRUE, TRUE, 0);
+ gtk_widget_show(hpaned);
+
+ return (hpaned);
+}
+
+/**
+ * Handler for the delete-event issued on the help window.We are saving window
+ * information (eg. position) and are hiding the window instead of closing it.
+ *
+ * \PARAM win IN the window to be destroyed
+ * \PARAM event IN unused
+ * \PARAM ptr IN unused
+ *
+ * \RETURN FALSE
+ */
+
+static gboolean
+DestroyHelpWindow(GtkWidget *win, GdkEvent *event, void *ptr)
+{
+ int i;
+ GtkWidget *widget;
+ char tmp[ 20 ];
+
+ gint x, y;
+
+ /* get the slider position and save it */
+ widget = lookup_widget(win, PANED);
+ i = gtk_paned_get_position(GTK_PANED(widget));
+ wPrefSetInteger(HTMLHELPSECTION, SLIDERPREFNAME, i);
+
+ /* get the window position */
+ gtk_window_get_position((GtkWindow *)win, &x, &y);
+ sprintf(tmp, "%d %d", x, y);
+ wPrefSetString(HTMLHELPSECTION, WINDOWPOSPREFNAME, tmp);
+
+ /* get the window size */
+ gtk_window_get_size((GtkWindow *)win , &x, &y);
+ sprintf(tmp, "%d %d", x, y);
+ wPrefSetString(HTMLHELPSECTION, WINDOWSIZEPREFNAME, tmp);
+
+ gtk_widget_hide(win);
+ return TRUE;
+}
+
+void back_button_clicked(GtkWidget *widget, gpointer data)
+{
+ webkit_web_view_go_back(WEBKIT_WEB_VIEW(data));
+}
+
+void forward_button_clicked(GtkWidget *widget, gpointer data)
+{
+ webkit_web_view_go_forward(WEBKIT_WEB_VIEW(data));
+}
+
+void home_button_clicked(GtkWidget *widget, gpointer data)
+{
+ load_into_view("index.html", MAIN_VIEW);
+}
+
+/* Toggles the contents pane */
+void contents_button_clicked(GtkWidget *widget, gpointer data)
+{
+ if (gtk_paned_get_position(GTK_PANED(data)) < 50) {
+ gtk_paned_set_position(GTK_PANED(data), 370);
+ } else {
+ gtk_paned_set_position(GTK_PANED(data), 0);
+ }
+}
+
+gboolean contents_click_handler(
+ WebKitWebView *web_view,
+ WebKitWebFrame *frame,
+ WebKitNetworkRequest *request,
+ WebKitWebNavigationAction *navigation_action,
+ WebKitWebPolicyDecision *policy_decision,
+ gpointer data)
+{
+
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(data),
+ webkit_network_request_get_uri(request));
+
+ return TRUE;
+}
+
+/**
+ * Initialize the buttons for the help window
+ */
+void initialize_buttons(GtkWidget *main_vbox, GtkWidget *content_hpane)
+{
+ GtkWidget *buttons_hbuttonbox;
+ GtkWidget *back_button;
+ GtkWidget *forward_button;
+ GtkWidget *home_button;
+ GtkWidget *contents_button;
+
+ // define and attach signals to buttons
+ back_button = gtk_button_new_with_label(_("Back"));
+ g_signal_connect(back_button, "clicked", G_CALLBACK(back_button_clicked),
+ G_OBJECT(main_view));
+
+ forward_button = gtk_button_new_with_label(_("Forward"));
+ g_signal_connect(forward_button, "clicked", G_CALLBACK(forward_button_clicked),
+ G_OBJECT(main_view));
+
+ home_button = gtk_button_new_with_label(_("Home"));
+ g_signal_connect(home_button, "clicked", G_CALLBACK(home_button_clicked),
+ G_OBJECT(main_view));
+
+ contents_button = gtk_button_new_with_label(_("Contents"));
+ g_signal_connect(contents_button, "clicked",
+ G_CALLBACK(contents_button_clicked), G_OBJECT(content_hpane));
+
+ // button layout
+ buttons_hbuttonbox = gtk_hbutton_box_new();
+ gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), back_button);
+ gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), forward_button);
+ gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), home_button);
+ gtk_container_add(GTK_CONTAINER(buttons_hbuttonbox), contents_button);
+ gtk_box_pack_start(GTK_BOX(main_vbox), buttons_hbuttonbox, FALSE, TRUE, 0);
+ gtk_box_set_spacing(GTK_BOX(buttons_hbuttonbox), 6);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(buttons_hbuttonbox),
+ GTK_BUTTONBOX_START);
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT(main_view, back_button, BACKBUTTON);
+ GLADE_HOOKUP_OBJECT(main_view, forward_button, FORWARDBUTTON);
+ GLADE_HOOKUP_OBJECT(main_view, home_button, HOMEBUTTON);
+ GLADE_HOOKUP_OBJECT(main_view, contents_button, CONTENTBUTTON);
+}
+
+/**
+ * Create the help windows including all contained widgets and the needed HTML documents.
+ *
+ * \RETURN handle of the created window.
+ */
+
+GtkWidget*
+CreateHelpWindow(void)
+{
+ GtkWidget *main_vbox;
+ GtkWidget *main_view_scroller;
+ GtkWidget *contents_view_scroller;
+ GtkWidget *content_hpane;
+
+ int width;
+ int height;
+ int x, y;
+ int w = 0, h = 0;
+ const char *pref;
+
+ wHelpWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ width = gdk_screen_get_width(gtk_window_get_screen((GtkWindow *)wHelpWindow));
+ height = gdk_screen_get_height(gtk_window_get_screen((GtkWindow *)wHelpWindow));
+
+ pref = wPrefGetString(HTMLHELPSECTION, WINDOWSIZEPREFNAME);
+
+ if (pref) {
+ sscanf(pref, "%d %d", &w, &h);
+
+ if (w > width) {
+ w = width;
+ }
+
+ if (h > height) {
+ h = height;
+ }
+ } else {
+ w = (width * 2)/ 5;
+ h = height - 100;
+ }
+
+ pref = wPrefGetString(HTMLHELPSECTION, WINDOWPOSPREFNAME);
+
+ if (pref) {
+ sscanf(pref, "%d %d", &x, &y);
+
+ if (y > height - h) {
+ y = height - h;
+ }
+
+ if (x > width - w) {
+ x = width - w;
+ }
+ } else {
+ x = (width * 3) / 5 - 10;
+ y = 70;
+ }
+
+ gtk_window_resize((GtkWindow *)wHelpWindow, w, h);
+ gtk_window_move((GtkWindow *)wHelpWindow, x, y);
+
+ gtk_window_set_title(GTK_WINDOW(wHelpWindow), "XTrkCad Help");
+
+ g_signal_connect(G_OBJECT(wHelpWindow), "delete-event",
+ G_CALLBACK(DestroyHelpWindow), NULL);
+
+ main_view_scroller = gtk_scrolled_window_new(NULL, NULL);
+ contents_view_scroller = gtk_scrolled_window_new(NULL, NULL);
+ main_view = webkit_web_view_new();
+ contents_view = webkit_web_view_new();
+ // must be done here as it gets locked down later
+ load_into_view("contents.html", CONTENTS_VIEW);
+ gtk_widget_set_size_request(GTK_WIDGET(wHelpWindow), x, y);
+
+ main_vbox = gtk_vbox_new(FALSE, 5);
+ gtk_container_add(GTK_CONTAINER(wHelpWindow), main_vbox);
+
+ gtk_container_add(GTK_CONTAINER(main_view_scroller), main_view);
+
+ gtk_container_add(GTK_CONTAINER(contents_view_scroller), contents_view);
+
+ content_hpane = gtk_hpaned_new();
+ initialize_buttons(main_vbox, content_hpane);
+ gtk_container_add(GTK_CONTAINER(content_hpane), contents_view_scroller);
+ gtk_container_add(GTK_CONTAINER(content_hpane), main_view_scroller);
+ gtk_box_pack_start(GTK_BOX(main_vbox), content_hpane, TRUE, TRUE, 0);
+
+ gtk_paned_set_position(GTK_PANED(content_hpane), 370);
+
+ g_signal_connect(contents_view, "navigation-policy-decision-requested",
+ G_CALLBACK(contents_click_handler), G_OBJECT(main_view));
+
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF(wHelpWindow, wHelpWindow, "wHelpWindow");
+ GLADE_HOOKUP_OBJECT(wHelpWindow, content_hpane, PANED);
+ GLADE_HOOKUP_OBJECT(wHelpWindow, contents_view, TOCVIEW);
+ GLADE_HOOKUP_OBJECT(wHelpWindow, main_view, CONTENTSVIEW);
+
+ return wHelpWindow;
+}
+
+void load_into_view(char *file, int requested_view)
+{
+ GtkWidget *view;
+
+ switch (requested_view) {
+ case MAIN_VIEW:
+ view = main_view;
+ break;
+
+ case CONTENTS_VIEW:
+ view = contents_view;
+ break;
+
+ default:
+ printf("*** error, could not find view");
+ break;
+ }
+
+ char fileToLoad[250] = "file://";
+ strcat(fileToLoad,directory);
+ strcat(fileToLoad,file);
+
+ //debug printf("*** loading %s into pane %d.\n", fileToLoad, requested_view);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(view), fileToLoad);
+}
+
+/**
+ * Invoke the help system to display help for <topic>.
+ *
+ * \param topic IN topic string
+ */
+
+void wHelp(const char * topic)
+{
+ char *htmlFile;
+
+ if (!wHelpWindow) {
+ directory = malloc(BUFSIZ);
+ assert(directory != NULL);
+
+ sprintf(directory, "%s/html/", wGetAppLibDir());
+
+ wHelpWindow = CreateHelpWindow();
+ /* load the default content */
+ load_into_view("index.html", MAIN_VIEW);
+ }
+
+ /* need space for the 'html' extension plus dot plus \0 */
+ htmlFile = malloc(strlen(topic) + 6);
+ assert(htmlFile != NULL);
+
+ sprintf(htmlFile, "%s.html", topic);
+
+ load_into_view(htmlFile, MAIN_VIEW);
+ gtk_widget_show_all(wHelpWindow);
+ gtk_window_present(GTK_WINDOW(wHelpWindow));
+}
diff --git a/app/wlib/gtklib/lines.c b/app/wlib/gtklib/lines.c
new file mode 100644
index 0000000..bd787a6
--- /dev/null
+++ b/app/wlib/gtklib/lines.c
@@ -0,0 +1,150 @@
+/** \file lines.c
+ * Window for drawing simple line drawing
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis,
+ * 2016 Martin Fischer <m_fischer@sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <cairo.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Lines
+ *
+ *****************************************************************************
+ */
+
+struct wLine_t {
+ WOBJ_COMMON
+ wBool_t visible;
+ int count;
+ wLines_t * lines;
+};
+
+/**
+ * Perform redrawing of the lines window
+ *
+ * \param b IN window handle
+ * \return
+ */
+
+static void linesRepaint(wControl_p b)
+{
+ wLine_p bl = (wLine_p)(b);
+ int i;
+ wWin_p win = (wWin_p)(bl->parent);
+ GdkDrawable * window;
+ cairo_t *cr;
+
+ if (!bl->visible) {
+ return;
+ }
+
+ window = gtk_widget_get_window(win->widget);
+ cr = gdk_cairo_create(window);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+ cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
+
+ for (i=0; i<bl->count; i++) {
+ cairo_set_line_width(cr, bl->lines[i].width);
+ cairo_move_to(cr, bl->lines[i].x0, bl->lines[i].y0);
+ cairo_line_to(cr, bl->lines[i].x1, bl->lines[i].y1);
+ cairo_stroke(cr);
+ }
+
+ cairo_destroy(cr);
+}
+
+/**
+ * Set visibility state of lines window
+ *
+ * \param bl IN window
+ * \param visible IN new visibility state
+ * \return
+ */
+
+void wlibLineShow(
+ wLine_p bl,
+ wBool_t visible)
+{
+ bl->visible = visible;
+}
+
+/**
+ * Create a window consisting of several lines
+ *
+ * \param parent IN parent window
+ * \param labelStr IN label - unused
+ * \param count IN number of lines
+ * \param lines IN list of line coordinates
+ * \return handle of new window
+ */
+
+wLine_p wLineCreate(
+ wWin_p parent,
+ const char * labelStr,
+ int count,
+ wLines_t * lines)
+{
+ wLine_p linesWindow;
+ int i;
+ linesWindow = (wLine_p)wlibAlloc(parent, B_LINES, 0, 0, labelStr,
+ sizeof *linesWindow, NULL);
+ linesWindow->visible = TRUE;
+ linesWindow->count = count;
+ linesWindow->lines = lines;
+ linesWindow->w = linesWindow->h = 0;
+
+ for (i=0; i<count; i++) {
+ if (lines[i].x0 > linesWindow->w) {
+ linesWindow->w = lines[i].x0;
+ }
+
+ if (lines[i].y0 > linesWindow->h) {
+ linesWindow->h = lines[i].y0;
+ }
+
+ if (lines[i].x1 > linesWindow->w) {
+ linesWindow->w = lines[i].x1;
+ }
+
+ if (lines[i].y1 > linesWindow->h) {
+ linesWindow->h = lines[i].y1;
+ }
+ }
+
+ linesWindow->repaintProc = linesRepaint;
+ wlibAddButton((wControl_p)linesWindow);
+ linesWindow->widget = NULL;
+ return linesWindow;
+}
diff --git a/app/wlib/gtklib/list.c b/app/wlib/gtklib/list.c
new file mode 100644
index 0000000..bf3a56e
--- /dev/null
+++ b/app/wlib/gtklib/list.c
@@ -0,0 +1,547 @@
+/** \file list.c
+ * Listboxes, dropdown boxes, combo boxes
+ */
+/* 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include "wlib.h"
+#include "gtkint.h"
+#include "i18n.h"
+
+struct listSearch {
+ const char *search;
+ char *result;
+ int row;
+};
+
+
+/*
+ *****************************************************************************
+ *
+ * List Boxes
+ *
+ *****************************************************************************
+ */
+
+/**
+ * Remove all entries from the list
+ *
+ * \param b IN list
+ * \return
+ */
+
+void wListClear(
+ wList_p b)
+{
+ assert(b!= NULL);
+
+ b->recursion++;
+
+ if (b->type == B_DROPLIST) {
+ wDropListClear(b);
+ } else {
+ wTreeViewClear(b);
+ }
+
+ b->recursion--;
+ b->last = -1;
+ b->count = 0;
+}
+
+/**
+ * Makes the <val>th entry (0-origin) the current selection.
+ * If <val> if '-1' then no entry is selected.
+ * \param b IN List
+ * \param element IN Index
+ */
+
+void wListSetIndex(
+ wList_p b,
+ int element)
+{
+ if (b->widget == 0) {
+ abort();
+ }
+
+ b->recursion++;
+
+ if (b->type == B_DROPLIST) {
+ wDropListSetIndex(b, element);
+ } else {
+ wlibTreeViewSetSelected(b, element);
+ }
+
+ b->last = element;
+ b->recursion--;
+}
+
+/**
+ * CompareListData is called when a list is searched for a specific
+ * data entry. It is called in sequence and does a string compare
+ * between the label of the current row and the search argument. If
+ * identical the label is placed in the search argument.
+ * It is a GTK foreach() function.
+ *
+ * \param model IN searched model
+ * \param path IN unused
+ * \param iter IN current iterator
+ * \param data IN/OUT pointer to data structure with search criteria
+ * \return TRUE if identical, FALSE otherwise
+ */
+
+int
+CompareListData(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
+ gpointer data)
+{
+ wListItem_p id_p;
+ struct listSearch *search = (struct listSearch *)data;
+
+ gtk_tree_model_get(model,
+ iter,
+ LISTCOL_DATA,
+ &id_p,
+ -1);
+
+ if (id_p && id_p->label && !strcmp(id_p->label, search->search)) {
+ search->result = (char *)id_p->label;
+ return TRUE;
+ } else {
+ search->result = NULL;
+ search->row++;
+ return FALSE;
+ }
+}
+
+/**
+ * Find the row which contains the specified text.
+ *
+ * \param b IN
+ * \param val IN
+ * \returns found row or -1 if not found
+ */
+
+wIndex_t wListFindValue(
+ wList_p b,
+ const char * val)
+{
+ struct listSearch thisSearch;
+
+ assert(b!=NULL);
+ assert(b->listStore!=NULL);
+
+ thisSearch.search = val;
+ thisSearch.row = 0;
+
+ gtk_tree_model_foreach(GTK_TREE_MODEL(b->listStore), CompareListData,
+ (void *)&thisSearch);
+
+ if (!thisSearch.result) {
+ return -1;
+ } else {
+ return thisSearch.row;
+ }
+}
+
+/**
+ * Return the number of rows in the list
+ *
+ * \param b IN widget
+ * \returns number of rows
+ */
+
+wIndex_t wListGetCount(
+ wList_p b)
+{
+ if (b->type == B_DROPLIST) {
+ return wDropListGetCount(b);
+ } else {
+ return wTreeViewGetCount(b);
+ }
+}
+
+/**
+ * Get the user data for a list element
+ *
+ * \param b IN widget
+ * \param inx IN row
+ * \returns the user data for the specified row
+ */
+
+void * wListGetItemContext(
+ wList_p b,
+ wIndex_t inx)
+{
+ if (inx < 0) {
+ return NULL;
+ }
+
+ if (b->type == B_DROPLIST) {
+ return wDropListGetItemContext(b, inx);
+ } else {
+ return wTreeViewGetItemContext(b, inx);
+ }
+}
+
+/**
+ *
+ * \param bl IN widget
+ * \param labelStr IN ?
+ * \param labelSize IN ?
+ * \param listDataRet IN
+ * \param itemDataRet IN
+ * \returns
+ */
+
+wIndex_t wListGetValues(
+ wList_p bl,
+ char * labelStr,
+ int labelSize,
+ void * * listDataRet,
+ void * * itemDataRet)
+{
+ wListItem_p id_p;
+ wIndex_t inx = bl->last;
+ const char * entry_value = "";
+ void * item_data = NULL;
+
+ assert(bl != NULL);
+ assert(bl->listStore != NULL);
+
+ if (bl->type == B_DROPLIST && bl->editted) {
+ entry_value = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(
+ bl->widget))));
+ inx = bl->last = -1;
+ } else {
+ inx = bl->last;
+
+ if (inx >= 0) {
+ id_p = wlibListStoreGetContext(bl->listStore, inx);
+
+ if (id_p==NULL) {
+ fprintf(stderr, "wListGetValues - id_p == NULL\n");
+ } else {
+ entry_value = id_p->label;
+ item_data = id_p->itemData;
+ }
+ }
+ }
+
+ if (labelStr) {
+ strncpy(labelStr, entry_value, labelSize);
+ }
+
+ if (listDataRet) {
+ *listDataRet = bl->data;
+ }
+
+ if (itemDataRet) {
+ *itemDataRet = item_data;
+ }
+
+ return bl->last;
+}
+
+/**
+ * Check whether row is selected
+ * \param b IN widget
+ * \param inx IN row
+ * \returns TRUE if selected, FALSE if not existant or unselected
+ */
+
+wBool_t wListGetItemSelected(
+ wList_p b,
+ wIndex_t inx)
+{
+ wListItem_p id_p;
+
+ if (inx < 0) {
+ return FALSE;
+ }
+
+ id_p = wlibListStoreGetContext(b->listStore, inx);
+
+ if (id_p) {
+ return id_p->selected;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ * Count the number of selected rows in list
+ *
+ * \param b IN widget
+ * \returns count of selected rows
+ */
+
+wIndex_t wListGetSelectedCount(
+ wList_p b)
+{
+ wIndex_t selcnt, inx;
+
+ for (selcnt=inx=0; inx<b->count; inx++)
+ if (wListGetItemSelected(b, inx)) {
+ selcnt++;
+ }
+
+ return selcnt;
+}
+
+/**
+ * Select all items in list.
+ *
+ * \param bl IN list handle
+ * \return
+ */
+
+void wListSelectAll(wList_p bl)
+{
+ wIndex_t inx;
+ GtkTreeSelection *selection;
+
+ assert(bl != NULL);
+ // mark all items selected
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(bl->treeView));
+ gtk_tree_selection_select_all(selection);
+
+ // and synchronize the internal data structures
+ wListGetCount(bl);
+
+ for (inx=0; inx<bl->count; inx++) {
+ wListItem_p ldp;
+
+ ldp = wlibListStoreGetContext(bl->listStore, inx);
+
+ if (ldp) {
+ ldp->selected = TRUE;
+ }
+ }
+}
+
+/**
+ * Set the value for a row in the listbox
+ *
+ * \param b IN widget
+ * \param row IN row to change
+ * \param labelStr IN string with new tab separated values
+ * \param bm IN icon
+ * \param itemData IN data for row
+ * \returns TRUE
+ */
+
+wBool_t wListSetValues(
+ wList_p b,
+ wIndex_t row,
+ const char * labelStr,
+ wIcon_p bm,
+ void *itemData)
+
+{
+ assert(b->listStore != NULL);
+
+ b->recursion++;
+
+ if (b->type == B_DROPLIST) {
+ wDropListSetValues(b, row, labelStr, bm, itemData);
+ } else {
+ wlibListStoreUpdateValues(b->listStore, row, b->colCnt, (char *)labelStr, bm);
+ }
+
+ b->recursion--;
+ return TRUE;
+}
+
+/**
+ * Remove a line from the list
+ * \param b IN widget
+ * \param inx IN row
+ */
+
+void wListDelete(
+ wList_p b,
+ wIndex_t inx)
+
+{
+ GtkTreeIter iter;
+
+ assert(b->listStore != 0);
+ assert(b->type != B_DROPLIST);
+ b->recursion++;
+
+ if (b->type == B_DROPLIST) {
+ wNotice("Deleting from dropboxes is not implemented!", "Continue", NULL);
+ } else {
+ gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore),
+ &iter,
+ NULL,
+ inx);
+ gtk_list_store_remove(b->listStore, &iter);
+ b->count--;
+ }
+
+ b->recursion--;
+ return;
+}
+
+/**
+ * Get the widths of the columns
+ *
+ * \param bl IN widget
+ * \param colCnt IN number of columns
+ * \param colWidths OUT array for widths
+ * \returns
+ */
+
+int wListGetColumnWidths(
+ wList_p bl,
+ int colCnt,
+ wPos_t * colWidths)
+{
+ int inx;
+
+ if (bl->type != B_LIST) {
+ return 0;
+ }
+
+ if (bl->colWidths == NULL) {
+ return 0;
+ }
+
+ for (inx=0; inx<colCnt; inx++) {
+ if (inx < bl->colCnt) {
+ colWidths[inx] = bl->colWidths[inx];
+ } else {
+ colWidths[inx] = 0;
+ }
+ }
+
+ return bl->colCnt;
+}
+
+/**
+ * Adds a entry to the list <b> with name <name>.
+ *
+ * \param b IN widget
+ * \param labelStr IN Entry name
+ * \param bm IN Entry bitmap
+ * \param itemData IN User context
+ * \returns
+ */
+
+wIndex_t wListAddValue(
+ wList_p b,
+ const char * labelStr,
+ wIcon_p bm,
+ void * itemData)
+{
+ wListItem_p id_p;
+
+ assert(b != NULL);
+
+ b->recursion++;
+
+ id_p = (wListItem_p)g_malloc(sizeof *id_p);
+ memset(id_p, 0, sizeof *id_p);
+ id_p->itemData = itemData;
+ id_p->active = TRUE;
+
+ if (labelStr == NULL) {
+ labelStr = "";
+ }
+
+ id_p->label = strdup(labelStr);
+ id_p->listP = b;
+
+ if (b->type == B_DROPLIST) {
+ wDropListAddValue(b, (char *)labelStr, id_p);
+ } else {
+ wlibTreeViewAddRow(b, (char *)labelStr, bm, id_p);
+ }
+
+ b->count++;
+ b->recursion--;
+
+ if (b->count == 1) {
+ b->last = 0;
+ }
+
+ return b->count-1;
+}
+
+
+/**
+ * Set the size of the list
+ *
+ * \param bl IN widget
+ * \param w IN width
+ * \param h IN height (ignored for droplist)
+ */
+
+void wListSetSize(wList_p bl, wPos_t w, wPos_t h)
+{
+ if (bl->type == B_DROPLIST) {
+ gtk_widget_set_size_request(bl->widget, w, -1);
+ } else {
+ gtk_widget_set_size_request(bl->widget, w, h);
+ }
+
+ bl->w = w;
+ bl->h = h;
+}
+
+/**
+ * Create a single column list box (not what the names suggests!)
+ * \todo Improve or discard totally, in this case, remove from param.c \
+ * as well.
+ *
+ * \param varname1 IN this is a variable
+ * \param varname2 OUT and another one that is modified
+ * \return describe the return value
+ */
+
+wList_p wComboListCreate(
+ wWin_p parent, /* Parent window */
+ wPos_t x, /* X-position */
+ wPos_t y, /* Y-position */
+ const char * helpStr, /* Help string */
+ const char * labelStr, /* Label */
+ long option, /* Options */
+ long number, /* Number of displayed list entries */
+ wPos_t width, /* Width */
+ long *valueP, /* Selected index */
+ wListCallBack_p action, /* Callback */
+ void *data) /* Context */
+{
+ wNotice("ComboLists are not implemented!", "Abort", NULL);
+ abort();
+}
+
+
diff --git a/app/wlib/gtklib/liststore.c b/app/wlib/gtklib/liststore.c
new file mode 100644
index 0000000..eb53ea7
--- /dev/null
+++ b/app/wlib/gtklib/liststore.c
@@ -0,0 +1,267 @@
+/** \file liststore.c
+ * Handling of the list store used for tree views and drop boxes
+ */
+
+/*
+ *
+ * Copyright 2016 Martin Fischer <m_fischer@users.sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include "gtkint.h"
+
+/**
+ * Get data of one row in a list
+ * \param b IN list widget
+ * \param inx IN row to retrieve
+ * \param childR IN list for data (?)
+ * \returns
+ */
+
+wListItem_p wlibListItemGet(
+ GtkListStore *ls,
+ wIndex_t inx,
+ GList ** childR)
+{
+ wListItem_p id_p;
+
+ assert(ls != NULL);
+
+ if (childR) {
+ *childR = NULL;
+ }
+
+ if (inx < 0) {
+ return NULL;
+ }
+
+ id_p = wlibListStoreGetContext(ls, inx);
+
+ return id_p;
+}
+
+/**
+ * Get the context (user data) for a row in the list store
+ *
+ * \param ls IN list store
+ * \param inx IN row
+ * \returns pointer to data
+ */
+
+void *
+wlibListStoreGetContext(GtkListStore *ls, int inx)
+{
+ GtkTreeIter iter;
+ gchar *string = NULL;
+ gboolean result;
+ gint childs;
+
+ childs = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(ls),
+ NULL);
+
+ if (inx < childs) {
+ result = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(ls),
+ &iter,
+ NULL,
+ inx);
+
+ if (result) {
+ gtk_tree_model_get(GTK_TREE_MODEL(ls),
+ &iter,
+ LISTCOL_DATA,
+ &string,
+ -1);
+ } else {
+ printf("Invalid index %d for list!\n", inx);
+
+ }
+ }
+
+ return (string);
+}
+
+
+/**
+ * Clear the list store
+ *
+ * \param listStore IN
+ */
+
+void
+wlibListStoreClear(GtkListStore *listStore)
+{
+ assert(listStore != NULL);
+
+ /** \todo this looks like a memory leak. should probably free the id's */
+ gtk_list_store_clear(listStore);
+}
+
+/**
+ * Create a list store. The list store will have one column for user
+ * data that will not be displayed, a column for a bitmap and <cnt>
+ * colors for data.
+ *
+ * \param colCnt IN number of additional columns
+ * \returns the list store
+ */
+
+GtkListStore *
+wlibNewListStore(int colCnt)
+{
+ GtkListStore *ls;
+ GType *colTypes;
+ int i;
+
+ /* create the list store, using strings for all columns */
+ colTypes = g_malloc(sizeof(GType) * (colCnt + LISTCOL_TEXT));
+ colTypes[ LISTCOL_BITMAP ] = GDK_TYPE_PIXBUF;
+ colTypes[ LISTCOL_DATA ] = G_TYPE_POINTER;
+
+ for (i = 0; i < colCnt; i++) {
+ colTypes[ LISTCOL_TEXT + i ] = G_TYPE_STRING;
+ }
+
+ ls = gtk_list_store_newv(colCnt + LISTCOL_TEXT, colTypes);
+ g_free(colTypes);
+
+ return (ls);
+}
+
+/**
+ * Update the list store at the iter's position
+ *
+ * \param ls IN list store
+ * \param iter IN iterator into list store
+ * \param labels IN tab separated label string
+ * \returns number of updated columns
+ */
+
+static int
+wlibListStoreUpdateIter(GtkListStore *ls, GtkTreeIter *iter, char *labels)
+{
+ char *convertedLabels;
+ char *text;
+ char *start;
+ int current = 0;
+
+ convertedLabels = strdup(wlibConvertInput(labels));
+ start = convertedLabels;
+
+ while ((text = strchr(start, '\t')) != NULL) {
+ *text = '\0';
+ gtk_list_store_set(ls, iter, LISTCOL_TEXT + current, start, -1);
+ start = text + 1;
+ current++;
+ }
+
+ /* add the last piece of the string */
+ gtk_list_store_set(ls, iter, LISTCOL_TEXT + current, start, -1);
+
+ free(convertedLabels);
+ return (current+1);
+}
+
+/**
+ * Add a pixbuf to the list store
+ * \param ls IN list store
+ * \param iter IN position
+ * \param pixbuf IN pixbuf to add
+ */
+
+void
+wlibListStoreSetPixbuf(GtkListStore *ls, GtkTreeIter *iter, GdkPixbuf *pixbuf)
+{
+ gtk_list_store_set(ls, iter, LISTCOL_BITMAP, pixbuf, -1);
+}
+/**
+ * Add a row to the list store
+ *
+ * \param ls IN the list store
+ * \param cols IN columns in list store
+ * \param id IN id
+ * \returns number columns added
+ */
+
+int
+wlibListStoreAddData(GtkListStore *ls, GdkPixbuf *pixbuf, int cols,
+ wListItem_p id)
+{
+ GtkTreeIter iter;
+ int count;
+
+ gtk_list_store_append(ls, &iter);
+ gtk_list_store_set(ls, &iter, LISTCOL_DATA, id, -1);
+
+ if (pixbuf) {
+ wlibListStoreSetPixbuf(ls, &iter, pixbuf);
+ }
+
+ count = wlibListStoreUpdateIter(ls, &iter, (char *)id->label);
+
+ return (count);
+}
+
+/**
+ * Change a row in the list store. The passed strings are placed
+ * in the first cols text columns of the list store.
+ *
+ * \param ls IN list store
+ * \param row IN row in list store
+ * \param cols IN number of columns to set
+ * \param labels IN tab separated list of texts
+ * \param bm IN bitmap
+ * \return count of updated text fields
+ */
+
+int
+wlibListStoreUpdateValues(GtkListStore *ls, int row, int cols, char *labels,
+ wIcon_p bm)
+{
+ GtkTreeIter iter;
+ int count;
+
+ gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(ls),
+ &iter,
+ NULL,
+ row);
+
+ count = wlibListStoreUpdateIter(ls, &iter, labels);
+
+ if (bm) {
+ GdkPixbuf *pixbuf;
+
+ pixbuf = wlibMakePixbuf(bm);
+ wlibListStoreSetPixbuf(ls, &iter, pixbuf);
+ }
+
+ return (count);
+}
+
diff --git a/app/wlib/gtklib/main.c b/app/wlib/gtklib/main.c
new file mode 100644
index 0000000..9075687
--- /dev/null
+++ b/app/wlib/gtklib/main.c
@@ -0,0 +1,107 @@
+/** \file main.c
+ * Main function and initialization stuff
+ *
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005,2012 Dave Bullis 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 <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+
+static char *appName; /**< application name */
+char *wExecutableName;
+
+
+/**
+ * Initialize the application name for later use
+ *
+ * \param _appName IN Name of application
+ * \return
+ */
+
+void
+wInitAppName(char *_appName)
+{
+ appName = g_strdup( _appName );
+}
+
+char *
+wlibGetAppName()
+{
+ return( appName );
+}
+
+/*
+ *******************************************************************************
+ *
+ * Main
+ *
+ *******************************************************************************
+ */
+
+
+
+int main( int argc, char *argv[] )
+{
+ wWin_p win;
+ const char *ld;
+
+ if ( getenv( "GTKLIB_NOLOCALE" ) == 0 )
+ setlocale( LC_ALL, "en_US" );
+ gtk_init( &argc, &argv );
+
+ if ((win=wMain( argc, argv )) == NULL)
+ exit(1);
+ wExecutableName = argv[ 0 ];
+ ld = wGetAppLibDir();
+
+#ifdef WINDOWS
+
+#else
+ // set up help search path on unix boxes
+ if (ld != NULL) {
+ static char buff[BUFSIZ];
+ const char *hp;
+
+ sprintf( buff, "HELPPATH=/usr/lib/help:%s:", ld );
+ if ( (hp = getenv("HELPPATH")) != NULL )
+ strcat( buff, hp );
+ putenv( buff );
+ }
+#endif
+
+ if (!win->shown)
+ wWinShow( win, TRUE );
+
+ gtk_main();
+ exit(0);
+}
diff --git a/app/wlib/gtklib/menu.c b/app/wlib/gtklib/menu.c
new file mode 100644
index 0000000..fb115a3
--- /dev/null
+++ b/app/wlib/gtklib/menu.c
@@ -0,0 +1,1084 @@
+/** \file menu.c
+ * Menu creation and handling.
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis, 2012 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+#define WLISTITEM "wListItem" /**< id for object data */
+
+/*
+ *****************************************************************************
+ *
+ * Menus
+ *
+ *****************************************************************************
+ */
+
+typedef enum { M_MENU, M_SEPARATOR, M_PUSH, M_LIST, M_LISTITEM, M_TOGGLE, M_RADIO } mtype_e;
+typedef enum { MM_BUTT, MM_MENU, MM_BAR, MM_POPUP } mmtype_e;
+
+typedef struct{ mtype_e mtype; /**< menu entry type */
+ GtkWidget *menu_item;
+ wMenu_p parentMenu;
+ int recursion; /**< recursion counter */
+ } MOBJ_COMMON; /**< menu item specific data */
+
+
+struct wMenuItem_t {
+ WOBJ_COMMON
+ MOBJ_COMMON m;
+ };
+
+typedef struct wMenuItem_t * wMenuItem_p;
+
+// a few macros to make access to members easier
+//#define PTR2M( ptr ) ((ptr)->m)
+#define MMENUITEM( ptr ) (((ptr)->m).menu_item)
+#define MPARENT( ptr ) (((ptr)->m).parentMenu)
+#define MITEMTYPE( ptr ) (((ptr)->m).mtype)
+#define MRECURSION( ptr ) (((ptr)->m).recursion)
+
+
+struct wMenu_t {
+ WOBJ_COMMON
+ MOBJ_COMMON m;
+ mmtype_e mmtype;
+ wMenuItem_p first, last;
+ GtkWidget * menu;
+ GSList *radioGroup; /* radio button group */
+ wMenuTraceCallBack_p traceFunc;
+ void * traceData;
+ GtkLabel * labelG;
+ GtkWidget * imageG;
+ };
+
+struct wMenuPush_t {
+ WOBJ_COMMON
+ MOBJ_COMMON m;
+ wMenuCallBack_p action;
+ wBool_t enabled;
+ };
+
+struct wMenuRadio_t {
+ WOBJ_COMMON
+ MOBJ_COMMON m;
+ wMenuCallBack_p action;
+ wBool_t enabled;
+ };
+
+struct wMenuList_t {
+ WOBJ_COMMON
+ MOBJ_COMMON m;
+ int max;
+ int count;
+ wMenuListCallBack_p action;
+ };
+
+struct wMenuListItem_t {
+ WOBJ_COMMON
+ MOBJ_COMMON m;
+ wMenuList_p mlist;
+ };
+
+typedef struct wMenuListItem_t * wMenuListItem_p;
+
+struct wMenuToggle_t {
+ WOBJ_COMMON
+ MOBJ_COMMON m;
+ wMenuToggleCallBack_p action;
+ wBool_t enabled;
+ wBool_t set;
+ };
+
+
+/*-----------------------------------------------------------------*/
+
+/**
+ * Handle activate event for menu items.
+ *
+ * \param widget IN widget that emitted the signal
+ * \param value IN application data
+ * \return
+ */
+
+static void pushMenuItem(
+ GtkWidget * widget,
+ gpointer value )
+{
+ wMenuItem_p m = (wMenuItem_p)value;
+ wMenuToggle_p mt;
+
+ if (MRECURSION( m ))
+ return;
+
+ switch MITEMTYPE( m ) {
+ case M_PUSH:
+ ((wMenuPush_p)m)->action( ((wMenuPush_p)m)->data );
+ break;
+ case M_TOGGLE:
+ mt = (wMenuToggle_p)m;
+ wMenuToggleSet( mt, !mt->set );
+ mt->action( mt->set, mt->data );
+ break;
+ case M_RADIO:
+ /* NOTE: action is only called when radio button is activated, not when deactivated */
+ if( gtk_check_menu_item_get_active((GtkCheckMenuItem *)widget ) == TRUE )
+ ((wMenuRadio_p)m)->action( ((wMenuRadio_p)m)->data );
+ break;
+ case M_MENU:
+ return;
+ default:
+ /*fprintf(stderr," Oops menu\n");*/
+ return;
+ }
+ if( MPARENT(m)->traceFunc ) {
+ MPARENT(m)->traceFunc( MPARENT( m ), m->labelStr, MPARENT(m)->traceData );
+ }
+}
+
+/**
+ * Create a new menu element, add to the parent menu and to help
+ *
+ * \param m IN parent menu
+ * \param mtype IN type of new entry
+ * \param helpStr IN help topic
+ * \param labelStr IN display label
+ * \param size IN size of additional data?
+ * \return the newly created menu element
+ */
+
+static wMenuItem_p createMenuItem(
+ wMenu_p m,
+ mtype_e mtype,
+ const char * helpStr,
+ const char * labelStr,
+ int size )
+{
+ wMenuItem_p mi;
+ mi = (wMenuItem_p)wlibAlloc( NULL, B_MENUITEM, 0, 0, labelStr, size, NULL );
+ MITEMTYPE( mi )= mtype;
+
+ switch ( mtype ) {
+ case M_LIST:
+ MMENUITEM( mi ) = gtk_menu_item_new_with_mnemonic(wlibConvertInput(mi->labelStr)); // NULL; //PTR2M(m).menu_item
+ break;
+ case M_SEPARATOR:
+ MMENUITEM( mi ) = gtk_separator_menu_item_new();
+ break;
+ case M_TOGGLE:
+ MMENUITEM( mi ) = gtk_check_menu_item_new_with_mnemonic(wlibConvertInput(mi->labelStr));
+ break;
+ case M_RADIO:
+ MMENUITEM( mi ) = gtk_radio_menu_item_new_with_mnemonic(m->radioGroup, wlibConvertInput(mi->labelStr));
+ m->radioGroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (MMENUITEM( mi )));
+ break;
+ default:
+ MMENUITEM( mi ) = gtk_menu_item_new_with_mnemonic(wlibConvertInput(mi->labelStr));
+ break;
+ }
+ if (MMENUITEM( mi )) {
+ if (m)
+ gtk_menu_shell_append( (GtkMenuShell *)(m->menu), MMENUITEM( mi ) );
+
+ g_signal_connect( GTK_OBJECT(MMENUITEM( mi )), "activate",
+ G_CALLBACK(pushMenuItem), mi );
+ gtk_widget_show(MMENUITEM( mi ));
+ }
+
+ // this is a link list of all menu items belonging to a specific menu
+ // is used in automatic processing (macro)??
+ if (m) {
+ if (m->first == NULL) {
+ m->first = mi;
+ } else {
+ m->last->next = (wControl_p)mi;
+ }
+ m->last = mi;
+ }
+ mi->next = NULL;
+
+
+ if (helpStr != NULL) {
+ wlibAddHelpString( MMENUITEM( mi ), helpStr );
+ }
+ MPARENT( mi ) = m;
+ return mi;
+}
+
+
+static void setAcclKey( wWin_p w, GtkWidget * menu, GtkWidget * menu_item, int acclKey )
+{
+ int mask;
+ static GtkAccelGroup * accel_alpha_group = NULL;
+ static GtkAccelGroup * accel_nonalpha_group = NULL;
+ guint oldmods;
+
+
+ if (accel_alpha_group == NULL) {
+ accel_alpha_group = gtk_accel_group_new();
+ /*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/
+ gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_alpha_group );
+ }
+ if (accel_nonalpha_group == NULL) {
+ oldmods = gtk_accelerator_get_default_mod_mask();
+ gtk_accelerator_set_default_mod_mask( GDK_CONTROL_MASK | GDK_MOD1_MASK );
+ accel_nonalpha_group = gtk_accel_group_new();
+ /*gtk_accel_group_set_mod_mask( accel_group, GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK );*/
+ gtk_window_add_accel_group(GTK_WINDOW(gtkMainW->gtkwin), accel_nonalpha_group );
+ gtk_accelerator_set_default_mod_mask( oldmods );
+ }
+
+ mask = 0;
+ if (acclKey) {
+ int len;
+ char acclStr[40];
+
+ len = 0;
+ if (acclKey&WALT) {
+ mask |= GDK_MOD1_MASK;
+ strcpy( acclStr+len, "Meta+" );
+ len += 5;
+ }
+ if (acclKey&WSHIFT) {
+ mask |= GDK_SHIFT_MASK;
+ strcpy( acclStr+len, "Shift+" );
+ len += 6;
+ switch ( (acclKey&0xFF) ) {
+ case '0': acclKey += ')'-'0'; break;
+ case '1': acclKey += '!'-'1'; break;
+ case '2': acclKey += '@'-'2'; break;
+ case '3': acclKey += '#'-'3'; break;
+ case '4': acclKey += '$'-'4'; break;
+ case '5': acclKey += '%'-'5'; break;
+ case '6': acclKey += '^'-'6'; break;
+ case '7': acclKey += '&'-'7'; break;
+ case '8': acclKey += '*'-'8'; break;
+ case '9': acclKey += '('-'9'; break;
+ case '`': acclKey += '~'-'`'; break;
+ case '-': acclKey += '_'-'-'; break;
+ case '=': acclKey += '+'-'='; break;
+ case '\\': acclKey += '|'-'\\'; break;
+ case '[': acclKey += '{'-'['; break;
+ case ']': acclKey += '}'-']'; break;
+ case ';': acclKey += ':'-';'; break;
+ case '\'': acclKey += '"'-'\''; break;
+ case ',': acclKey += '<'-','; break;
+ case '.': acclKey += '>'-'.'; break;
+ case '/': acclKey += '?'-'/'; break;
+ default: break;
+ }
+ }
+ if (acclKey&WCTL) {
+ mask |= GDK_CONTROL_MASK;
+ strcpy( acclStr+len, "Ctrl+" );
+ len += 5;
+ }
+ acclStr[len++] = (acclKey & 0xFF);
+ acclStr[len++] = '\0';
+ gtk_widget_add_accelerator( menu_item, "activate",
+ (isalpha(acclKey&0xFF)?accel_alpha_group:accel_nonalpha_group),
+ toupper(acclKey&0xFF), mask, GTK_ACCEL_VISIBLE|GTK_ACCEL_LOCKED );
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/**
+ * Create a radio button as a menu entry
+ *
+ * \param m IN menu to be extended
+ * \param helpStr IN reference into help
+ * \param labelStr IN text for entry
+ * \param acclKey IN accelerator key to add
+ * \param action IN callback function
+ * \param data IN application data
+ * \param helpStr IN
+ * \return menu entry
+ */
+
+wMenuRadio_p wMenuRadioCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr,
+ long acclKey,
+ wMenuCallBack_p action,
+ void *data )
+{
+ wMenuRadio_p mi;
+
+ mi = (wMenuRadio_p)createMenuItem( m, M_RADIO, helpStr, labelStr, sizeof *mi );
+ //~ if (m->mmtype == MM_POPUP && !testMenuPopup)
+ //~ return mi;
+ setAcclKey( m->parent, m->menu, MMENUITEM( mi ), acclKey );
+ mi->action = action;
+ mi->data = data;
+ mi->enabled = TRUE;
+ return mi;
+}
+
+/**
+ * Set radio button active
+ *
+ * \param mi IN menu entry for radio button
+ * \return
+ */
+
+void wMenuRadioSetActive(
+ wMenuRadio_p mi )
+{
+ gtk_check_menu_item_set_active( (GtkCheckMenuItem *)MMENUITEM(mi), TRUE );
+}
+
+/*-----------------------------------------------------------------*/
+
+/**
+ * Create a menu entry
+ *
+ * \param m IN menu to be extended
+ * \param helpStr IN reference into help
+ * \param labelStr IN text for entry
+ * \param acclKey IN acceleratoor key to add
+ * \param action IN callback function
+ * \param data IN application data
+ * \return menu entry
+ */
+
+wMenuPush_p wMenuPushCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr,
+ long acclKey,
+ wMenuCallBack_p action,
+ void *data )
+{
+ wMenuPush_p mi;
+
+ mi = (wMenuPush_p)createMenuItem( m, M_PUSH, helpStr, labelStr, sizeof( struct wMenuPush_t ));
+
+ setAcclKey( m->parent, m->menu, MMENUITEM( mi ), acclKey );
+
+ mi->action = action;
+ mi->data = data;
+ mi->enabled = TRUE;
+ return mi;
+}
+
+/**
+ * Enable menu entry
+ *
+ * \param mi IN menu entry
+ * \param enable IN new state
+ * \return
+ */
+
+void wMenuPushEnable(
+ wMenuPush_p mi,
+ wBool_t enable )
+{
+ mi->enabled = enable;
+ gtk_widget_set_sensitive( GTK_WIDGET(MMENUITEM( mi )), enable );
+}
+
+
+/*-----------------------------------------------------------------*/
+/**
+ * Create a submenu
+ *
+ * \param m IN menu to be extended
+ * \param helpStr IN reference into help
+ * \param labelStr IN text for entry
+ * \return menu entry
+ */
+
+wMenu_p wMenuMenuCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr )
+{
+ wMenu_p mi;
+ mi = (wMenu_p)createMenuItem( m, M_MENU, helpStr, labelStr, sizeof( struct wMenu_t ));
+ mi->mmtype = MM_MENU;
+ mi->menu = gtk_menu_new();
+
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(MMENUITEM( mi )), mi->menu );
+ return mi;
+}
+
+
+/*-----------------------------------------------------------------*/
+/**
+ * Create a menu separator
+ *
+ * \param mi IN menu entry
+ * \return
+ */
+
+void wMenuSeparatorCreate(
+ wMenu_p m )
+{
+ createMenuItem( m, M_SEPARATOR, NULL, "", sizeof( struct wMenuItem_t ));
+}
+
+
+/*-----------------------------------------------------------------*/
+
+/**
+ * Find the start of a menu item list in a menu
+ *
+ * \param ml IN menu list to be searched
+ * \param pChildren OUT list of children in menu container
+ * \return -1 if not found, index in children list otherwise
+ */
+
+int getMlistOrigin( wMenuList_p ml, GList **pChildren )
+{
+ GtkWidget *mi;
+ int count = 0;
+ int found = -1;
+ GtkWidget *mitem = MMENUITEM( ml );
+
+ *pChildren = gtk_container_get_children( GTK_CONTAINER( MPARENT( ml )->menu ));
+ if( !*pChildren )
+ return( -1 );
+
+ while( (mi = g_list_nth_data( *pChildren, count ))) {
+ if( mi == mitem ) {
+ found = TRUE;
+ break;
+ }
+ else {
+ count++;
+ }
+ }
+
+ if( found )
+ return( count );
+ else
+ return( -1 );
+}
+
+/**
+ * Signal handler for clicking onto a menu list item.
+ * Parameters are the GtkWidget as expected and the pointer to the MenuListItem
+ *
+ * \param widget IN the GtkWidget
+ * \param value IN the menu list item
+ * \return
+ */
+
+static void pushMenuList(
+ GtkWidget * widget,
+ gpointer value )
+{
+ // pointer to the list item
+ wMenuListItem_p ml = (wMenuListItem_p)value;
+
+ if (MRECURSION( ml ))
+ return;
+
+ if (ml->mlist->count <= 0) {
+ // this should never happen
+ fprintf( stderr, "pushMenuItem: empty list\n" );
+ return;
+ }
+ // this is the applications callback routine
+ if (ml->mlist->action) {
+ const char * itemLabel;
+
+ itemLabel = gtk_menu_item_get_label( GTK_MENU_ITEM( widget ));
+
+ ml->mlist->action( 0, itemLabel, ml->data );
+ return;
+ }
+ fprintf( stderr, "pushMenuItem: item (%lx) not found\n", (long)widget );
+}
+
+/**
+ * Create a list menu entry
+ *
+ * \param m IN menu to be extended
+ * \param helpStr IN reference into help
+ * \param max IN maximum number of elements
+ * \param action IN callback function
+ * \return menu entry
+ */
+
+wMenuList_p wMenuListCreate(
+ wMenu_p m,
+ const char * helpStr,
+ int max,
+ wMenuListCallBack_p action )
+{
+ wMenuList_p mi;
+ mi = (wMenuList_p)createMenuItem( m, M_LIST, NULL, _("<Empty List>"), sizeof( struct wMenuList_t ));
+ gtk_widget_set_sensitive( GTK_WIDGET(MMENUITEM( mi )), FALSE );
+ mi->next = NULL;
+ mi->count = 0;
+ mi->max = max;
+ MPARENT( mi ) = m;
+ mi->action = action;
+ return (wMenuList_p)mi;
+}
+
+
+/**
+ * Add a new item to a list of menu entries
+ * The placeholder for the list is looked up. Then the new item is added immediately
+ * behind it. In case the maximum number of items is reached the last item is removed.
+ *
+ * \param ml IN handle for the menu list - the placeholder item
+ * \param index IN currently ignored
+ * \param labelStr IN the menu label for the new item
+ * \param data IN application data for the new item
+ * \return
+ */
+
+void wMenuListAdd(
+ wMenuList_p ml,
+ int index,
+ const char * labelStr,
+ const void * data )
+{
+ int i = 0;
+ GList * children;
+
+ i = getMlistOrigin( ml, &children );
+
+ if( i > -1 ) {
+ wMenuListItem_p mi;
+
+ // we're adding an item, so hide the default placeholder
+ gtk_widget_hide( MMENUITEM( ml ));
+
+ // delete an earlier entry with the same label
+ wMenuListDelete( ml, labelStr );
+
+ // a new item
+ ml->count ++;
+
+ // is there a maximum number of items set and reached with the new item?
+ if(( ml->max != -1 ) && ( ml->count > ml-> max )) {
+ wMenuListItem_p mold;
+ GtkWidget * item;
+
+ // get the last item in the list
+ item = g_list_nth_data( children, i + ml->max );
+ // get the pointer to the data structure
+ mold = g_object_get_data( G_OBJECT( item ), WLISTITEM );
+ // kill the menu entry
+ gtk_widget_destroy( item );
+ // free the data
+ free( (void *)mold->labelStr );
+ free( (void *)mold );
+
+ ml->count--;
+ }
+
+ // create the new menu item and initialize the data fields
+ mi = (wMenuListItem_p)wlibAlloc( NULL, B_MENUITEM, 0, 0, labelStr, sizeof( struct wMenuListItem_t ), NULL );
+ MITEMTYPE( mi ) = M_LISTITEM;
+ MMENUITEM( mi ) = gtk_menu_item_new_with_label(wlibConvertInput(mi->labelStr));
+ mi->data = (void *)data;
+ mi->mlist = ml;
+ g_object_set_data( G_OBJECT(MMENUITEM( mi )), WLISTITEM, mi );
+
+ // add the item to the menu
+ gtk_menu_shell_insert((GtkMenuShell *)(MPARENT( ml )->menu), MMENUITEM( mi ), i + 1 );
+ g_signal_connect( GTK_OBJECT(MMENUITEM( mi )), "activate", G_CALLBACK(pushMenuList), mi );
+
+ gtk_widget_show(MMENUITEM( mi ));
+ }
+
+ if( children )
+ g_list_free( children );
+}
+
+/**
+ * Remove the menu entry identified by a given label.
+ *
+ * \param ml IN menu list
+ * \param labelStr IN label string of item
+ */
+
+void wMenuListDelete(
+ wMenuList_p ml,
+ const char * labelStr )
+{
+ int i;
+ int found = FALSE;
+ GList * children;
+
+ // find the placeholder for the list in the menu
+ i = getMlistOrigin( ml, &children );
+
+ if( i > -1 ) {
+ int origin;
+ GtkWidget * item;
+ char * labelStrConverted;
+
+ // starting from the placeholder, find the menu item with the correct text
+ found = FALSE;
+ labelStrConverted = wlibConvertInput( labelStr );
+ origin = i;
+
+ // get menu item
+ // get label of item
+ // compare items
+ // if identical, leave loop
+ while( i <= origin + ml->count && !found ) {
+ const char * itemLabel;
+
+ item = g_list_nth_data( children, i );
+ itemLabel = gtk_menu_item_get_label( GTK_MENU_ITEM( item ));
+ if( !g_utf8_collate (itemLabel, labelStrConverted ))
+ found = TRUE;
+ else
+ i++;
+ }
+ if( found ) {
+ wMenuListItem_p mold;
+
+ mold = g_object_get_data( G_OBJECT( item ), WLISTITEM );
+ // kill the menu entry
+ gtk_widget_destroy( item );
+ // free the data
+ free( (void *)mold->labelStr );
+ free( (void *)mold );
+
+ ml->count--;
+ }
+ }
+
+ if( children )
+ g_list_free( children );
+}
+
+/**
+ * Get the label and the application data of a specific menu list item
+ *
+ * \param ml IN menu list
+ * \param index IN item within list
+ * \param data OUT application data
+ * \return item label
+ */
+
+const char *
+wMenuListGet( wMenuList_p ml, int index, void ** data )
+{
+ int i;
+
+ GList * children;
+ const char * itemLabel = NULL;
+
+ // check whether index is in range, if not return immediately
+ if ( index >= ml->count || ml->count <= 0 ) {
+ if (data)
+ *data = NULL;
+ return NULL;
+ }
+
+ // find the placeholder for the list in the menu
+ i = getMlistOrigin( ml, &children );
+
+ if( i > -1 ) {
+ GtkWidget * item;
+ wMenuListItem_p mold;
+
+ item = g_list_nth_data( children, i + index + 1 );
+ itemLabel = gtk_menu_item_get_label( GTK_MENU_ITEM( item ));
+ mold = g_object_get_data( G_OBJECT( GTK_MENU_ITEM( item ) ), WLISTITEM );
+ *data = mold->data;
+ }
+
+ if( children )
+ g_list_free( children );
+
+ return itemLabel;
+}
+
+/**
+ * Remove all items from menu list
+ *
+ * \param ml IN menu item list
+ */
+
+void wMenuListClear(
+ wMenuList_p ml )
+{
+ int origin;
+ GList * children;
+
+ if (ml->count == 0)
+ return;
+
+ origin = getMlistOrigin( ml, &children );
+
+ if( origin > -1 ) {
+ int i;
+
+ i = origin;
+ while( i < origin + ml->count ) {
+ wMenuListItem_p mold;
+ GtkWidget * item;
+
+ item = g_list_nth_data( children, i + 1 );
+ mold = g_object_get_data( G_OBJECT( item ), WLISTITEM );
+ // kill the menu entry
+ gtk_widget_destroy( item );
+ // free the data
+ free( (void *)mold->labelStr );
+ free( (void *)mold );
+ i++;
+ }
+ }
+
+ ml->count = 0;
+ gtk_widget_show( MMENUITEM( ml ));
+
+ if( children )
+ g_list_free( children );
+}
+/*-----------------------------------------------------------------*/
+/**
+ * Create a check box as part of a menu
+ *
+ * \param m IN menu to be extended
+ * \param helpStr IN reference into help
+ * \param labelStr IN text for entry
+ * \param acclKey IN acceleratoor key to add
+ * \param set IN initial state
+ * \param action IN callback function
+ * \param data IN application data
+ * \return menu entry
+ */
+
+wMenuToggle_p wMenuToggleCreate(
+ wMenu_p m,
+ const char * helpStr,
+ const char * labelStr,
+ long acclKey,
+ wBool_t set,
+ wMenuToggleCallBack_p action,
+ void * data )
+{
+ wMenuToggle_p mt;
+
+ mt = (wMenuToggle_p)createMenuItem( m, M_TOGGLE, helpStr, labelStr, sizeof( struct wMenuToggle_t ));
+ setAcclKey( m->parent, m->menu, MMENUITEM( mt ), acclKey );
+ mt->action = action;
+ mt->data = data;
+ mt->enabled = TRUE;
+ MPARENT( mt ) = m;
+ wMenuToggleSet( mt, set );
+
+ return mt;
+}
+
+/**
+ * Get the state of a menu check box
+ *
+ * \param mt IN menu to be extended
+ * \return current state
+ */
+
+wBool_t wMenuToggleGet(
+ wMenuToggle_p mt )
+{
+ return mt->set;
+}
+
+/**
+ * Set a menu check box active / inactive
+ *
+ * \param mt IN menu to be extended
+ * \param set IN new state
+ * \return previous state
+ */
+
+wBool_t wMenuToggleSet(
+ wMenuToggle_p mt,
+ wBool_t set )
+{
+ wBool_t rc;
+ if (mt==NULL) return 0;
+ MRECURSION( mt )++;
+ gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(MMENUITEM( mt )), set );
+ MRECURSION( mt )--;
+ rc = mt->set;
+ mt->set = set;
+ return rc;
+}
+
+/**
+ * Enable menu entry containing a check box
+ *
+ * \param mi IN menu entry
+ * \param enable IN new state
+ * \return
+ */
+
+void wMenuToggleEnable(
+ wMenuToggle_p mt,
+ wBool_t enable )
+{
+ mt->enabled = enable;
+}
+
+
+/*-----------------------------------------------------------------*/
+
+/**
+ * Set the text for a menu
+ *
+ * \param m IN menu entry
+ * \param labelStr IN new text
+ * \return
+ */
+
+void wMenuSetLabel( wMenu_p m, const char * labelStr) {
+ wlibSetLabel( m->widget, m->option, labelStr, &m->labelG, &m->imageG );
+}
+
+/**
+ * Signal handler for menu items. Parameters are the GtkWidget as
+ * expected and the pointer to the MenuListItem
+ *
+ * \param widget IN the GtkWidget
+ * \param value IN the menu list item
+ * \return
+ */
+
+static gint pushMenu(
+ GtkWidget * widget,
+ wMenu_p m )
+{
+ gtk_menu_popup( GTK_MENU(m->menu), NULL, NULL, NULL, NULL, 0, 0 );
+ /* Tell calling code that we have handled this event; the buck
+ * stops here. */
+ return TRUE;
+}
+
+/**
+ * Create a button with a drop down menu
+ *
+ * \param parent IN parent window
+ * \param x IN x position
+ * \param y IN y position
+ * \param helpStr IN help anchor string
+ * \param labelStr IN label for menu
+ * \param option IN options (Whatever they are)
+ * \return pointer to the created menu
+ */
+
+wMenu_p wMenuCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option )
+{
+ wMenu_p m;
+ m = wlibAlloc( parent, B_MENU, x, y, labelStr, sizeof( struct wMenu_t ), NULL );
+ m->mmtype = MM_BUTT;
+ m->option = option;
+ m->traceFunc = NULL;
+ m->traceData = NULL;
+ wlibComputePos( (wControl_p)m );
+
+ m->widget = gtk_button_new();
+ g_signal_connect (GTK_OBJECT(m->widget), "clicked",
+ G_CALLBACK(pushMenu), m );
+
+ m->menu = gtk_menu_new();
+
+ wMenuSetLabel( m, labelStr );
+
+ gtk_fixed_put( GTK_FIXED(parent->widget), m->widget, m->realX, m->realY );
+ wlibControlGetSize( (wControl_p)m );
+ if ( m->w < 80 && (m->option&BO_ICON)==0) {
+ m->w = 80;
+ gtk_widget_set_size_request( m->widget, m->w, m->h );
+ }
+ gtk_widget_show( m->widget );
+ wlibAddButton( (wControl_p)m );
+ wlibAddHelpString( m->widget, helpStr );
+ return m;
+}
+
+/**
+ * Add a drop-down menu to the menu bar.
+ *
+ * \param w IN main window handle
+ * \param helpStr IN unused (should be help topic )
+ * \param labelStr IN label for the drop-down menu
+ * \return pointer to the created drop-down menu
+ */
+
+wMenu_p wMenuBarAdd(
+ wWin_p w,
+ const char * helpStr,
+ const char * labelStr )
+{
+ wMenu_p m;
+ GtkWidget * menuItem;
+
+ m = wlibAlloc( w, B_MENU, 0, 0, labelStr, sizeof( struct wMenu_t ), NULL );
+ m->mmtype = MM_BAR;
+ m->realX = 0;
+ m->realY = 0;
+
+ menuItem = gtk_menu_item_new_with_mnemonic( wlibConvertInput(m->labelStr) );
+ m->menu = gtk_menu_new();
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), m->menu );
+ gtk_menu_shell_append( GTK_MENU_SHELL(w->menubar), menuItem );
+ gtk_widget_show( menuItem );
+
+ m->w = 0;
+ m->h = 0;
+
+ /* TODO: why is help not supported here? */
+ /*gtkAddHelpString( m->panel_item, helpStr );*/
+
+ return m;
+}
+
+
+/*-----------------------------------------------------------------*/
+
+/**
+ * Create a popup menu (context menu)
+ *
+ * \param w IN parent window
+ * \param labelStr IN label
+ * \return the created menu
+ */
+
+wMenu_p wMenuPopupCreate(
+ wWin_p w,
+ const char * labelStr )
+{
+ wMenu_p b;
+ b = wlibAlloc( w, B_MENU, 0, 0, labelStr, sizeof *b, NULL );
+ b->mmtype = MM_POPUP;
+ b->option = 0;
+
+ b->menu = gtk_menu_new();
+ b->w = 0;
+ b->h = 0;
+ g_signal_connect( GTK_OBJECT (b->menu), "key_press_event",
+ G_CALLBACK(catch_shift_ctrl_alt_keys), b);
+ g_signal_connect( GTK_OBJECT (b->menu), "key_release_event",
+ G_CALLBACK (catch_shift_ctrl_alt_keys), b);
+ gtk_widget_set_events ( GTK_WIDGET(b->menu), GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK );
+ return b;
+}
+
+/**
+ * Show a context menu
+ *
+ * \param mp IN the context menu
+ */
+
+void wMenuPopupShow( wMenu_p mp )
+{
+ gtk_menu_popup( GTK_MENU(mp->menu), NULL, NULL, NULL, NULL, 0, 0 );
+}
+
+
+/*-----------------------------------------------------------------*/
+
+/**
+ * ?? Seems to be related to macro / automatic playback functionality
+ *
+ * \param m IN
+ * \param func IN
+ * \param data IN
+ */
+
+void wMenuSetTraceCallBack(
+ wMenu_p m,
+ wMenuTraceCallBack_p func,
+ void * data )
+{
+ m->traceFunc = func;
+ m->traceData = data;
+}
+
+/**
+ * ??? same as above
+ * \param m IN
+ * \param label IN
+ * \return describe the return value
+ */
+
+wBool_t wMenuAction(
+ wMenu_p m,
+ const char * label )
+{
+ wMenuItem_p mi;
+ wMenuToggle_p mt;
+ for ( mi = m->first; mi != NULL; mi = (wMenuItem_p)mi->next ) {
+ if ( strcmp( mi->labelStr, label ) == 0 ) {
+ switch( MITEMTYPE( mi )) {
+ case M_SEPARATOR:
+ break;
+ case M_PUSH:
+ if ( ((wMenuPush_p)mi)->enabled == FALSE )
+ wBeep();
+ else
+ ((wMenuPush_p)mi)->action( ((wMenuPush_p)mi)->data );
+ break;
+ case M_TOGGLE:
+ mt = (wMenuToggle_p)mi;
+ if ( mt->enabled == FALSE ) {
+ wBeep();
+ } else {
+ wMenuToggleSet( mt, !mt->set );
+ mt->action( mt->set, mt->data );
+ }
+ break;
+ case M_MENU:
+ break;
+ case M_LIST:
+ break;
+ default:
+ /*fprintf(stderr, "Oops: wMenuAction\n");*/
+ break;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/app/wlib/gtklib/message.c b/app/wlib/gtklib/message.c
new file mode 100644
index 0000000..396b696
--- /dev/null
+++ b/app/wlib/gtklib/message.c
@@ -0,0 +1,168 @@
+/** \file message.c
+ * Message line
+ */
+
+/* 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 <stdlib.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+
+/*
+ *****************************************************************************
+ *
+ * Message Boxes
+ *
+ *****************************************************************************
+ */
+
+struct wMessage_t {
+ WOBJ_COMMON
+ GtkWidget * labelWidget;
+ const char * message;
+ wPos_t labelWidth;
+};
+
+/**
+ * Set the message text
+ *
+ * \param b IN widget
+ * \param arg IN new text
+ * \return
+ */
+
+void wMessageSetValue(
+ wMessage_p b,
+ const char * arg)
+{
+ if (b->widget == 0) {
+ abort();
+ }
+
+ gtk_label_set_text(GTK_LABEL(b->labelWidget), wlibConvertInput(arg));
+}
+
+/**
+ * Set the width of the widget
+ *
+ * \param b IN widget
+ * \param width IN new width
+ * \return
+ */
+
+void wMessageSetWidth(
+ wMessage_p b,
+ wPos_t width)
+{
+ b->labelWidth = width;
+ gtk_widget_set_size_request(b->widget, width, -1);
+}
+
+/**
+ * Get height of message text
+ * \todo Constant height doesn't make sense, change to use the window's properties and retrieve the real font size
+ *
+ * \param flags IN text properties (large or small size)
+ * \return text height
+ */
+
+wPos_t wMessageGetHeight(
+ long flags)
+{
+ return 14;
+}
+
+/**
+ * Create a window for a simple text.
+ *
+ * \param IN parent Handle of parent window
+ * \param IN x position in x direction
+ * \param IN y position in y direction
+ * \param IN labelStr ???
+ * \param IN width horizontal size of window
+ * \param IN message message to display ( null terminated )
+ * \param IN flags display options
+ * \return handle for created window
+ */
+
+ wMessage_p wMessageCreateEx(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * labelStr,
+ wPos_t width,
+ const char *message,
+ long flags)
+{
+ wMessage_p b;
+ GtkRequisition requisition;
+ GtkStyle *style;
+ PangoFontDescription *fontDesc;
+ int fontSize;
+ b = (wMessage_p)wlibAlloc(parent, B_MESSAGE, x, y, NULL, sizeof *b, NULL);
+ wlibComputePos((wControl_p)b);
+ b->message = message;
+ b->labelWidth = width;
+ b->labelWidget = gtk_label_new(message?wlibConvertInput(message):"");
+
+ /* do we need to set a special font? */
+ if (wMessageSetFont(flags)) {
+ /* get the current font descriptor */
+ style = gtk_widget_get_style(GTK_WIDGET(b->labelWidget));
+ fontDesc = style->font_desc;
+ /* get the current font size */
+ fontSize = PANGO_PIXELS(pango_font_description_get_size(fontDesc));
+
+ /* calculate the new font size */
+ if (flags & BM_LARGE) {
+ pango_font_description_set_size(fontDesc, fontSize * 1.4 * PANGO_SCALE);
+ } else {
+ pango_font_description_set_size(fontDesc, fontSize * 0.7 * PANGO_SCALE);
+ }
+
+ /* set the new font size */
+ gtk_widget_modify_font((GtkWidget *)b->labelWidget, fontDesc);
+ }
+
+ b->widget = gtk_fixed_new();
+ gtk_widget_size_request(GTK_WIDGET(b->labelWidget), &requisition);
+ gtk_container_add(GTK_CONTAINER(b->widget), b->labelWidget);
+ gtk_widget_set_size_request(b->widget, width?width:requisition.width,
+ requisition.height);
+ wlibControlGetSize((wControl_p)b);
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+ gtk_widget_show(b->widget);
+ gtk_widget_show(b->labelWidget);
+ wlibAddButton((wControl_p)b);
+
+ /* Reset font size to normal */
+ if (wMessageSetFont(flags)) {
+ pango_font_description_set_size(fontDesc, fontSize * PANGO_SCALE);
+ }
+
+ return b;
+}
diff --git a/app/wlib/gtklib/notice.c b/app/wlib/gtklib/notice.c
new file mode 100644
index 0000000..cf4b59f
--- /dev/null
+++ b/app/wlib/gtklib/notice.c
@@ -0,0 +1,297 @@
+/** \file notice.c
+ * Misc. message type windows
+ *
+ * Copyright 2016 Martin Fischer <m_fischer@sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <signal.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+static char * wlibChgMnemonic(char *label);
+
+typedef struct {
+ GtkWidget * win;
+ GtkWidget * label;
+ GtkWidget * butt[3];
+} notice_win;
+static notice_win noticeW;
+static long noticeValue;
+
+/**
+ *
+ * @param widget IN
+ * @param value IN
+ */
+
+static void doNotice(
+ GtkWidget * widget,
+ long value)
+{
+ noticeValue = value;
+ gtk_widget_destroy(noticeW.win);
+ wlibDoModal(NULL, FALSE);
+}
+
+/**
+ * Show a notification window with a yes/no reply and an icon.
+ *
+ * \param type IN type of message: Information, Warning, Error
+ * \param msg IN message to display
+ * \param yes IN text for accept button
+ * \param no IN text for cancel button
+ * \return True when accept was selected, false otherwise
+ */
+
+int wNoticeEx(int type,
+ const char * msg,
+ const char * yes,
+ const char * no)
+{
+
+ int res;
+ unsigned flag;
+ char *headline;
+ GtkWidget *dialog;
+ GtkWindow *parent = GTK_WINDOW_TOPLEVEL;
+
+ switch (type) {
+ case NT_INFORMATION:
+ flag = GTK_MESSAGE_INFO;
+ headline = _("Information");
+ break;
+
+ case NT_WARNING:
+ flag = GTK_MESSAGE_WARNING;
+ headline = _("Warning");
+ break;
+
+ case NT_ERROR:
+ flag = GTK_MESSAGE_ERROR;
+ headline = _("Error");
+ break;
+ }
+
+ if (gtkMainW) {
+ parent = GTK_WINDOW(gtkMainW->gtkwin);
+ }
+
+ dialog = gtk_message_dialog_new(parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ flag,
+ ((no==NULL)?GTK_BUTTONS_OK:GTK_BUTTONS_YES_NO),
+ "%s", msg);
+ gtk_window_set_title(GTK_WINDOW(dialog), headline);
+
+ res = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ return res == GTK_RESPONSE_OK || res == GTK_RESPONSE_YES;
+}
+
+
+/**
+ * Popup up a notice box with one or two buttons.
+ * When this notice box is displayed the application is paused and
+ * will not response to other actions.
+ *
+ * @param msg IN message
+ * @param yes IN first button label
+ * @param no IN second button label (or NULL)
+ * @returns TRUE for first FALSE for second button
+ */
+
+int wNotice(
+ const char * msg, /* Message */
+ const char * yes, /* First button label */
+ const char * no) /* Second label (or 'NULL') */
+{
+ return wNotice3(msg, yes, no, NULL);
+}
+
+/** \brief Popup a notice box with three buttons.
+ *
+ * Popup up a notice box with three buttons.
+ * When this notice box is displayed the application is paused and
+ * will not response to other actions.
+ *
+ * Pushing the first button returns 1
+ * Pushing the second button returns 0
+ * Pushing the third button returns -1
+ *
+ * \param msg Text to display in message box
+ * \param yes First button label
+ * \param no Second label (or 'NULL')
+ * \param cancel Third button label (or 'NULL')
+ *
+ * \returns 1, 0 or -1
+ */
+
+int wNotice3(
+ const char * msg, /* Message */
+ const char * affirmative, /* First button label */
+ const char * cancel, /* Second label (or 'NULL') */
+ const char * alternate)
+{
+ notice_win *nw;
+ GtkWidget * vbox;
+ GtkWidget * hbox;
+ GtkWidget * hbox1;
+ GtkWidget * image;
+ nw = &noticeW;
+
+ char *aff = NULL;
+ char *can = NULL;
+ char *alt = NULL;
+
+
+ nw->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_position(GTK_WINDOW(nw->win), GTK_WIN_POS_CENTER);
+ gtk_container_set_border_width(GTK_CONTAINER(nw->win), 0);
+ gtk_window_set_resizable(GTK_WINDOW(nw->win), FALSE);
+ gtk_window_set_modal(GTK_WINDOW(nw->win), TRUE);
+ gtk_window_set_type_hint(GTK_WINDOW(nw->win), GDK_WINDOW_TYPE_HINT_DIALOG);
+
+ vbox = gtk_vbox_new(FALSE, 12);
+ gtk_widget_show(vbox);
+ gtk_container_add(GTK_CONTAINER(nw->win), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
+
+ hbox = gtk_hbox_new(FALSE, 12);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
+ gtk_widget_show(hbox);
+
+ image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_widget_show(image);
+ gtk_box_pack_start(GTK_BOX(hbox), image, TRUE, TRUE, 0);
+ gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
+
+ /* create the text label, allow GTK to wrap and allow for markup (for future enhancements) */
+ nw->label = gtk_label_new(msg);
+ gtk_widget_show(nw->label);
+ gtk_box_pack_end(GTK_BOX(hbox), nw->label, TRUE, TRUE, 0);
+ gtk_label_set_use_markup(GTK_LABEL(nw->label), FALSE);
+ gtk_label_set_line_wrap(GTK_LABEL(nw->label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(nw->label), 0, 0);
+
+ /* this hbox will include the button bar */
+ hbox1 = gtk_hbox_new(TRUE, 0);
+ gtk_widget_show(hbox1);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, TRUE, 0);
+
+ /* add the respective buttons */
+ aff = wlibChgMnemonic((char *) affirmative);
+ nw->butt[ 0 ] = gtk_button_new_with_mnemonic(aff);
+ gtk_widget_show(nw->butt[ 0 ]);
+ gtk_box_pack_end(GTK_BOX(hbox1), nw->butt[ 0 ], TRUE, TRUE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(nw->butt[ 0 ]), 3);
+ g_signal_connect(GTK_OBJECT(nw->butt[0]), "clicked", G_CALLBACK(doNotice),
+ (void*)1);
+ gtk_widget_set_can_default(nw->butt[ 0 ], TRUE);
+
+ if (cancel) {
+ can = wlibChgMnemonic((char *) cancel);
+ nw->butt[ 1 ] = gtk_button_new_with_mnemonic(can);
+ gtk_widget_show(nw->butt[ 1 ]);
+ gtk_box_pack_end(GTK_BOX(hbox1), nw->butt[ 1 ], TRUE, TRUE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(nw->butt[ 1 ]), 3);
+ g_signal_connect(GTK_OBJECT(nw->butt[1]), "clicked", G_CALLBACK(doNotice),
+ (void*)0);
+ gtk_widget_set_can_default(nw->butt[ 1 ], TRUE);
+
+ if (alternate) {
+ alt = wlibChgMnemonic((char *) alternate);
+ nw->butt[ 2 ] = gtk_button_new_with_mnemonic(alt);
+ gtk_widget_show(nw->butt[ 2 ]);
+ gtk_box_pack_start(GTK_BOX(hbox1), nw->butt[ 2 ], TRUE, TRUE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(nw->butt[ 2 ]), 3);
+ g_signal_connect(GTK_OBJECT(nw->butt[2]), "clicked", G_CALLBACK(doNotice),
+ (void*)-1);
+ gtk_widget_set_can_default(nw->butt[ 2 ], TRUE);
+ }
+ }
+
+ gtk_widget_grab_default(nw->butt[ 0 ]);
+ gtk_widget_grab_focus(nw->butt[ 0 ]);
+
+ gtk_widget_show(nw->win);
+
+ if (gtkMainW) {
+ gtk_window_set_transient_for(GTK_WINDOW(nw->win), GTK_WINDOW(gtkMainW->gtkwin));
+ /* gdk_window_set_group( nw->win->window, gtkMainW->gtkwin->window ); */
+ }
+
+ wlibDoModal(NULL, TRUE);
+
+ if (aff) {
+ free(aff);
+ }
+
+ if (can) {
+ free(can);
+ }
+
+ if (alt) {
+ free(alt);
+ }
+
+ return noticeValue;
+}
+
+/* \brief Convert label string from Windows mnemonic to GTK
+ *
+ * The first occurence of '&' in the passed string is changed to '_'
+ *
+ * \param label the string to convert
+ * \return pointer to modified string, has to be free'd after usage
+ *
+ */
+static
+char * wlibChgMnemonic(char *label)
+{
+ char *ptr;
+ char *cp;
+
+ cp = strdup(label);
+
+ ptr = strchr(cp, '&');
+
+ if (ptr) {
+ *ptr = '_';
+ }
+
+ return (cp);
+}
+
+
diff --git a/app/wlib/gtklib/osxhelp.c b/app/wlib/gtklib/osxhelp.c
new file mode 100644
index 0000000..829ec94
--- /dev/null
+++ b/app/wlib/gtklib/osxhelp.c
@@ -0,0 +1,133 @@
+/** \file osxhelp.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+#define HELPCOMMANDPIPE "/tmp/helppipe"
+#define EXITCOMMAND "##exit##"
+#define HELPERPROGRAM "helphelper"
+
+static pid_t pidOfChild;
+static int handleOfPipe;
+extern char *wExecutableName;
+
+/**
+ * Create the fully qualified filename for the help helper
+ *
+ * \param parent IN path and filename of parent process
+ * \return filename for the child process
+ */
+
+static
+char *ChildProgramFile(char *parentProgram)
+{
+ char *startOfFilename;
+ char *childProgram;
+
+ childProgram = malloc(strlen(parentProgram)+ sizeof(HELPERPROGRAM) + 1);
+ strcpy(childProgram, parentProgram);
+ startOfFilename = strrchr(childProgram, '/');
+ strcpy(startOfFilename + 1, HELPERPROGRAM);
+
+ return (childProgram);
+}
+
+
+/**
+ * Invoke the help system to display help for <topic>.
+ *
+ * \param topic IN topic string
+ */
+
+void wHelp(const char * topic)
+{
+ pid_t newPid;
+ int len;
+ int status;
+ const char html[] = ".html";
+ char *page;
+
+ // check whether child already exists
+ if (pidOfChild != 0) {
+ if (waitpid(pidOfChild, &status, WNOHANG) > 0) {
+ // child exited -> clean up
+ close(handleOfPipe);
+ unlink(HELPCOMMANDPIPE);
+ handleOfPipe = 0;
+ pidOfChild = 0; // child exited
+ }
+ }
+
+ // (re)start child
+ if (pidOfChild == 0) {
+ mkfifo(HELPCOMMANDPIPE, 0666);
+ newPid = fork(); /* New process starts here */
+
+ if (newPid > 0) {
+ pidOfChild = newPid;
+ } else if (newPid == 0) {
+ char *child = ChildProgramFile(wExecutableName);
+
+ if (execlp(child, child, NULL) < 0) { /* never normally returns */
+ exit(8);
+ }
+
+ free(child);
+ } else { /* -1 signifies fork failure */
+ pidOfChild = 0;
+ return;
+ }
+ }
+
+ if (!handleOfPipe) {
+ handleOfPipe = open(HELPCOMMANDPIPE, O_WRONLY);
+
+ if (handleOfPipe < 0) {
+ kill(pidOfChild, SIGKILL); /* tidy up on next call */
+ }
+
+ }
+
+ page = malloc(strlen(topic) + strlen(html) + 1);
+
+ if (!page) {
+ return;
+ }
+
+ strcpy(page, topic);
+ strcat(page, html);
+ len = strlen(page);
+
+ write(handleOfPipe, &len, sizeof(int));
+ write(handleOfPipe, page, strlen(page)+1);
+
+ free(page);
+}
diff --git a/app/wlib/gtklib/pixbuf.c b/app/wlib/gtklib/pixbuf.c
new file mode 100644
index 0000000..7b8d7d1
--- /dev/null
+++ b/app/wlib/gtklib/pixbuf.c
@@ -0,0 +1,99 @@
+/** \file pixbuf.c
+ * Create pixbuf from various bitmap formats
+ */
+
+/*
+ *
+ * Copyright 2016 Martin Fischer <m_fischer@users.sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <assert.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+
+/**
+ * Create a pixbuf from a wIcon
+ *
+ * \param ip IN widget
+ * \returns a valid pixbuf
+ */
+
+GdkPixbuf* wlibMakePixbuf(
+ wIcon_p ip)
+{
+ GdkPixbuf * pixbuf;
+ char line0[40];
+ char line2[40];
+
+ assert(ip != NULL);
+
+ if (ip->gtkIconType == gtkIcon_pixmap) {
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)ip->bits);
+ } else {
+ const char * bits;
+ long rgb;
+ int row,col,wb;
+ char ** pixmapData;
+
+ wb = (ip->w+7)/8;
+ pixmapData = (char**)g_malloc((3+ip->h) * sizeof *pixmapData);
+ pixmapData[0] = line0;
+ rgb = wDrawGetRGB(ip->color);
+ sprintf(line0, " %d %d 2 1", ip->w, ip->h);
+ sprintf(line2, "# c #%2.2lx%2.2lx%2.2lx", (rgb>>16)&0xFF, (rgb>>8)&0xFF,
+ rgb&0xFF);
+ pixmapData[1] = ". c None s None";
+ pixmapData[2] = line2;
+ bits = ip->bits;
+
+ for (row = 0; row<ip->h; row++) {
+ pixmapData[row+3] = (char*)g_malloc((ip->w+1) * sizeof **pixmapData);
+
+ for (col = 0; col<ip->w; col++) {
+ if (bits[ row*wb+(col>>3) ] & (1<<(col&07))) {
+ pixmapData[row+3][col] = '#';
+ } else {
+ pixmapData[row+3][col] = '.';
+ }
+ }
+
+ pixmapData[row+3][ip->w] = 0;
+ }
+
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)pixmapData);
+
+ for (row = 0; row<ip->h; row++) {
+ g_free(pixmapData[row+3]);
+ }
+ }
+
+ return pixbuf;
+}
+
+
diff --git a/app/wlib/gtklib/png.c b/app/wlib/gtklib/png.c
new file mode 100644
index 0000000..e11869e
--- /dev/null
+++ b/app/wlib/gtklib/png.c
@@ -0,0 +1,64 @@
+/** \file png.c
+ * PNG creation
+ */
+
+/* XTrackCad - 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.
+ */
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include "gtkint.h"
+
+#define BITMAPFILEFORMAT "png"
+
+/**
+* Export as bitmap file.
+*
+* \param d IN the drawing area ?
+* \param fileName IN fully qualified filename for the bitmap file.
+* \return TRUE on success, FALSE on error
+*/
+
+wBool_t wBitMapWriteFile(wDraw_p d, const char * fileName)
+{
+ GdkPixbuf *pixbuf;
+ GError *error;
+ gboolean res;
+ pixbuf = gdk_pixbuf_get_from_drawable(NULL, (GdkWindow*)d->pixmap, NULL, 0, 0,
+ 0, 0, d->w, d->h);
+
+ if (!pixbuf) {
+ wNoticeEx(NT_ERROR, "WriteBitMap: pixbuf_get failed", "Ok", NULL);
+ return FALSE;
+ }
+
+ error = NULL;
+ res = gdk_pixbuf_save(pixbuf, fileName, BITMAPFILEFORMAT, &error, NULL);
+
+ if (res == FALSE) {
+ wNoticeEx(NT_ERROR, "WriteBitMap: pixbuf_save failed", "Ok", NULL);
+ return FALSE;
+ }
+
+ g_object_unref(pixbuf);
+ return TRUE;
+}
diff --git a/app/wlib/gtklib/print.c b/app/wlib/gtklib/print.c
index 9f4a4a8..c0993f4 100644
--- a/app/wlib/gtklib/print.c
+++ b/app/wlib/gtklib/print.c
@@ -20,25 +20,22 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <sys/types.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
-#include <pwd.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <math.h>
-#include <locale.h>
-#include <stdint.h>
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
#include "gtkint.h"
-#include <gtk/gtkprintunixdialog.h>
-#include <gtk/gtkprintjob.h>
+#include <gtk/gtkunixprint.h>
#include "wlib.h"
#include "i18n.h"
@@ -79,7 +76,8 @@ extern struct wDraw_t psPrint_d;
static wBool_t printContinue; /**< control print job, FALSE for cancelling */
static wIndex_t pageCount; /**< unused, could be used for progress indicator */
-static wIndex_t totalPageCount; /**< unused, could be used for progress indicator */
+static wIndex_t
+totalPageCount; /**< unused, could be used for progress indicator */
static double paperWidth; /**< physical paper width */
static double paperHeight; /**< physical paper height */
@@ -96,7 +94,7 @@ static long printFormat = PRINT_LANDSCAPE;
*
*/
-static void WlibGetPaperSize( void );
+static void WlibGetPaperSize(void);
/**
* Initialize printer und paper selection using the saved settings
@@ -106,57 +104,64 @@ static void WlibGetPaperSize( void );
*/
void
-WlibApplySettings( GtkPrintOperation *op )
+WlibApplySettings(GtkPrintOperation *op)
{
- gchar *filename;
- GError *err = NULL;
- GtkWidget *dialog;
-
- filename = g_build_filename( wGetAppWorkDir(), PRINTSETTINGS, NULL );
-
- if( !(settings = gtk_print_settings_new_from_file( filename, &err ))) {
- if( err->code != G_FILE_ERROR_NOENT ) {
- // ignore file not found error as defaults will be used
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- err->message);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- } else {
- // create default print settings
- settings = gtk_print_settings_new();
- }
- g_error_free (err);
- }
- g_free( filename );
-
- if (settings && op )
- gtk_print_operation_set_print_settings (op, settings);
-
- err = NULL;
- filename = g_build_filename( wGetAppWorkDir(), PAGESETTINGS, NULL );
- if( !(page_setup = gtk_page_setup_new_from_file( filename, &err ))) {
- // ignore file not found error as defaults will be used
- if( err->code != G_FILE_ERROR_NOENT ) {
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- err->message);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- } else {
- page_setup = gtk_page_setup_new();
- }
- g_error_free (err);
- } else {
- // on success get the paper dimensions
- WlibGetPaperSize();
- }
- g_free( filename );
-
- if( page_setup && op )
- gtk_print_operation_set_default_page_setup (op, page_setup);
+ gchar *filename;
+ GError *err = NULL;
+ GtkWidget *dialog;
+
+ filename = g_build_filename(wGetAppWorkDir(), PRINTSETTINGS, NULL);
+
+ if (!(settings = gtk_print_settings_new_from_file(filename, &err))) {
+ if (err->code != G_FILE_ERROR_NOENT) {
+ // ignore file not found error as defaults will be used
+ dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ } else {
+ // create default print settings
+ settings = gtk_print_settings_new();
+ }
+
+ g_error_free(err);
+ }
+
+ g_free(filename);
+
+ if (settings && op) {
+ gtk_print_operation_set_print_settings(op, settings);
+ }
+
+ err = NULL;
+ filename = g_build_filename(wGetAppWorkDir(), PAGESETTINGS, NULL);
+
+ if (!(page_setup = gtk_page_setup_new_from_file(filename, &err))) {
+ // ignore file not found error as defaults will be used
+ if (err->code != G_FILE_ERROR_NOENT) {
+ dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ } else {
+ page_setup = gtk_page_setup_new();
+ }
+
+ g_error_free(err);
+ } else {
+ // on success get the paper dimensions
+ WlibGetPaperSize();
+ }
+
+ g_free(filename);
+
+ if (page_setup && op) {
+ gtk_print_operation_set_default_page_setup(op, page_setup);
+ }
}
@@ -168,75 +173,87 @@ WlibApplySettings( GtkPrintOperation *op )
*/
void
-WlibSaveSettings( GtkPrintOperation *op )
+WlibSaveSettings(GtkPrintOperation *op)
{
- GError *err = NULL;
- gchar *filename;
- GtkWidget *dialog;
-
- if( op ) {
- if (settings != NULL)
- g_object_unref (settings);
- settings = g_object_ref (gtk_print_operation_get_print_settings (op));
- }
- filename = g_build_filename( wGetAppWorkDir(), PRINTSETTINGS, NULL );
- if( !gtk_print_settings_to_file( settings, filename, &err )) {
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- err->message);
-
- g_error_free (err);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- }
- g_free( filename );
-
- if( op ) {
- if (page_setup != NULL)
- g_object_unref (page_setup);
- page_setup = g_object_ref (gtk_print_operation_get_default_page_setup (op));
- }
- filename = g_build_filename( wGetAppWorkDir(), PAGESETTINGS, NULL );
- if( !gtk_page_setup_to_file( page_setup, filename, &err )) {
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- err->message);
-
- g_error_free (err);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- }
- g_free( filename );
+ GError *err = NULL;
+ gchar *filename;
+ GtkWidget *dialog;
+
+ if (op) {
+ if (settings != NULL) {
+ g_object_unref(settings);
+ }
+
+ settings = g_object_ref(gtk_print_operation_get_print_settings(op));
+ }
+
+ filename = g_build_filename(wGetAppWorkDir(), PRINTSETTINGS, NULL);
+
+ if (!gtk_print_settings_to_file(settings, filename, &err)) {
+ dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+
+ g_error_free(err);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ }
+
+ g_free(filename);
+
+ if (op) {
+ if (page_setup != NULL) {
+ g_object_unref(page_setup);
+ }
+
+ page_setup = g_object_ref(gtk_print_operation_get_default_page_setup(op));
+ }
+
+ filename = g_build_filename(wGetAppWorkDir(), PAGESETTINGS, NULL);
+
+ if (!gtk_page_setup_to_file(page_setup, filename, &err)) {
+ dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+
+ g_error_free(err);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ }
+
+ g_free(filename);
}
/**
- * Page setup function. Previous settings are loaded and the setup
+ * Page setup function. Previous settings are loaded and the setup
* dialog is shown. The settings are saved after the dialog ends.
*
* \param callback IN unused
*/
-void wPrintSetup( wPrintSetupCallBack_p callback )
+void wPrintSetup(wPrintSetupCallBack_p callback)
{
- GtkPageSetup *new_page_setup;
- gchar *filename;
- GError *err;
- GtkWidget *dialog;
-
- WlibApplySettings( NULL );
-
- new_page_setup = gtk_print_run_page_setup_dialog (GTK_WINDOW (gtkMainW->gtkwin),
- page_setup, settings);
- if (page_setup)
- g_object_unref (page_setup);
-
- page_setup = new_page_setup;
-
- WlibGetPaperSize();
- WlibSaveSettings( NULL );
+ GtkPageSetup *new_page_setup;
+ gchar *filename;
+ GError *err;
+ GtkWidget *dialog;
+
+ WlibApplySettings(NULL);
+
+ new_page_setup = gtk_print_run_page_setup_dialog(GTK_WINDOW(gtkMainW->gtkwin),
+ page_setup, settings);
+
+ if (page_setup) {
+ g_object_unref(page_setup);
+ }
+
+ page_setup = new_page_setup;
+
+ WlibGetPaperSize();
+ WlibSaveSettings(NULL);
}
/*****************************************************************************
@@ -257,27 +274,29 @@ void wPrintSetup( wPrintSetupCallBack_p callback )
static void setLineType(
- double lineWidth,
- wDrawLineType_e lineType,
- wDrawOpts opts )
+ double lineWidth,
+ wDrawLineType_e lineType,
+ wDrawOpts opts)
{
- cairo_t *cr = psPrint_d.printContext;
- double dashLength = DASH_LENGTH;
-
- if (lineWidth < 0.0) {
- lineWidth = P2I(-lineWidth)*2.0;
- }
-
- // make sure that there is a minimum line width used
- if ( lineWidth == 0.0 )
- lineWidth = 0.1;
-
- cairo_set_line_width( cr, lineWidth );
-
- if (lineType == wDrawLineDash)
- cairo_set_dash( cr, &dashLength, 1, 0.0 );
- else
- cairo_set_dash( cr, NULL, 0, 0.0 );
+ cairo_t *cr = psPrint_d.printContext;
+ double dashLength = DASH_LENGTH;
+
+ if (lineWidth < 0.0) {
+ lineWidth = P2I(-lineWidth)*2.0;
+ }
+
+ // make sure that there is a minimum line width used
+ if (lineWidth == 0.0) {
+ lineWidth = 0.1;
+ }
+
+ cairo_set_line_width(cr, lineWidth);
+
+ if (lineType == wDrawLineDash) {
+ cairo_set_dash(cr, &dashLength, 1, 0.0);
+ } else {
+ cairo_set_dash(cr, NULL, 0, 0.0);
+ }
}
/**
@@ -288,14 +307,14 @@ static void setLineType(
*/
static void psSetColor(
- wDrawColor color )
+ wDrawColor color)
{
- cairo_t *cr = psPrint_d.printContext;
- GdkColor* const gcolor = gtkGetColor(color, TRUE);
+ cairo_t *cr = psPrint_d.printContext;
+ GdkColor* const gcolor = wlibGetColor(color, TRUE);
- cairo_set_source_rgb(cr, gcolor->red / 65535.0,
- gcolor->green / 65535.0,
- gcolor->blue / 65535.0);
+ cairo_set_source_rgb(cr, gcolor->red / 65535.0,
+ gcolor->green / 65535.0,
+ gcolor->blue / 65535.0);
}
/**
@@ -310,26 +329,29 @@ static void psSetColor(
*/
void psPrintLine(
- wPos_t x0, wPos_t y0,
- wPos_t x1, wPos_t y1,
- wDrawWidth width,
- wDrawLineType_e lineType,
- wDrawColor color,
- wDrawOpts opts )
+ wPos_t x0, wPos_t y0,
+ wPos_t x1, wPos_t y1,
+ wDrawWidth width,
+ wDrawLineType_e lineType,
+ wDrawColor color,
+ wDrawOpts opts)
{
- if (color == wDrawColorWhite)
- return;
- if (opts&wDrawOptTemp)
- return;
-
- psSetColor(color);
- setLineType( width, lineType, opts );
-
- cairo_move_to( psPrint_d.printContext,
- x0, y0 );
- cairo_line_to( psPrint_d.printContext,
- x1, y1 );
- cairo_stroke( psPrint_d.printContext );
+ if (color == wDrawColorWhite) {
+ return;
+ }
+
+ if (opts&wDrawOptTemp) {
+ return;
+ }
+
+ psSetColor(color);
+ setLineType(width, lineType, opts);
+
+ cairo_move_to(psPrint_d.printContext,
+ x0, y0);
+ cairo_line_to(psPrint_d.printContext,
+ x1, y1);
+ cairo_stroke(psPrint_d.printContext);
}
/**
@@ -346,46 +368,65 @@ void psPrintLine(
*/
void psPrintArc(
- wPos_t x0, wPos_t y0,
- wPos_t r,
- double angle0,
- double angle1,
- wBool_t drawCenter,
- wDrawWidth width,
- wDrawLineType_e lineType,
- wDrawColor color,
- wDrawOpts opts )
+ wPos_t x0, wPos_t y0,
+ wPos_t r,
+ double angle0,
+ double angle1,
+ wBool_t drawCenter,
+ wDrawWidth width,
+ wDrawLineType_e lineType,
+ wDrawColor color,
+ wDrawOpts opts)
{
- cairo_t *cr = psPrint_d.printContext;
-
- if (color == wDrawColorWhite)
- return;
- if (opts&wDrawOptTemp)
- return;
-
- psSetColor(color);
- setLineType(width, lineType, opts);
-
- if (angle1 >= 360.0)
- angle1 = 359.999;
- angle1 = 90.0-(angle0+angle1);
- while (angle1 < 0.0) angle1 += 360.0;
- while (angle1 >= 360.0) angle1 -= 360.0;
- angle0 = 90.0-angle0;
- while (angle0 < 0.0) angle0 += 360.0;
- while (angle0 >= 360.0) angle0 -= 360.0;
-
- // draw the curve
- cairo_arc( cr, x0, y0, r, angle1 * M_PI / 180.0, angle0 * M_PI / 180.0 );
-
- if( drawCenter ) {
- // draw crosshair for center of curve
- cairo_move_to( cr, x0 - CENTERMARK_LENGTH / 2, y0 );
- cairo_line_to( cr, x0 + CENTERMARK_LENGTH / 2, y0 );
- cairo_move_to( cr, x0, y0 - CENTERMARK_LENGTH / 2 );
- cairo_line_to( cr, x0, y0 + CENTERMARK_LENGTH / 2 );
- }
- cairo_stroke( psPrint_d.printContext );
+ cairo_t *cr = psPrint_d.printContext;
+
+ if (color == wDrawColorWhite) {
+ return;
+ }
+
+ if (opts&wDrawOptTemp) {
+ return;
+ }
+
+ psSetColor(color);
+ setLineType(width, lineType, opts);
+
+ if (angle1 >= 360.0) {
+ angle1 = 359.999;
+ }
+
+ angle1 = 90.0-(angle0+angle1);
+
+ while (angle1 < 0.0) {
+ angle1 += 360.0;
+ }
+
+ while (angle1 >= 360.0) {
+ angle1 -= 360.0;
+ }
+
+ angle0 = 90.0-angle0;
+
+ while (angle0 < 0.0) {
+ angle0 += 360.0;
+ }
+
+ while (angle0 >= 360.0) {
+ angle0 -= 360.0;
+ }
+
+ // draw the curve
+ cairo_arc(cr, x0, y0, r, angle1 * M_PI / 180.0, angle0 * M_PI / 180.0);
+
+ if (drawCenter) {
+ // draw crosshair for center of curve
+ cairo_move_to(cr, x0 - CENTERMARK_LENGTH / 2, y0);
+ cairo_line_to(cr, x0 + CENTERMARK_LENGTH / 2, y0);
+ cairo_move_to(cr, x0, y0 - CENTERMARK_LENGTH / 2);
+ cairo_line_to(cr, x0, y0 + CENTERMARK_LENGTH / 2);
+ }
+
+ cairo_stroke(psPrint_d.printContext);
}
/**
@@ -399,24 +440,28 @@ void psPrintArc(
*/
void psPrintFillRectangle(
- wPos_t x0, wPos_t y0,
- wPos_t x1, wPos_t y1,
- wDrawColor color,
- wDrawOpts opts )
+ wPos_t x0, wPos_t y0,
+ wPos_t x1, wPos_t y1,
+ wDrawColor color,
+ wDrawOpts opts)
{
- cairo_t *cr = psPrint_d.printContext;
- double width = x0 - x1;
- double height = y0 - y1;
+ cairo_t *cr = psPrint_d.printContext;
+ double width = x0 - x1;
+ double height = y0 - y1;
+
+ if (color == wDrawColorWhite) {
+ return;
+ }
- if (color == wDrawColorWhite)
- return;
- if (opts&wDrawOptTemp)
- return;
- psSetColor(color);
+ if (opts&wDrawOptTemp) {
+ return;
+ }
- cairo_rectangle( cr, x0, y0, width, height );
+ psSetColor(color);
- cairo_fill( cr );
+ cairo_rectangle(cr, x0, y0, width, height);
+
+ cairo_fill(cr);
}
/**
@@ -430,25 +475,31 @@ void psPrintFillRectangle(
*/
void psPrintFillPolygon(
- wPos_t p[][2],
- int cnt,
- wDrawColor color,
- wDrawOpts opts )
+ wPos_t p[][2],
+ int cnt,
+ wDrawColor color,
+ wDrawOpts opts)
{
- int inx;
- cairo_t *cr = psPrint_d.printContext;
+ int inx;
+ cairo_t *cr = psPrint_d.printContext;
+
+ if (color == wDrawColorWhite) {
+ return;
+ }
- if (color == wDrawColorWhite)
- return;
- if (opts&wDrawOptTemp)
- return;
+ if (opts&wDrawOptTemp) {
+ return;
+ }
- psSetColor(color);
+ psSetColor(color);
- cairo_move_to( cr, p[ 0 ][ 0 ], p[ 0 ][ 1 ] );
- for (inx=0; inx<cnt; inx++)
- cairo_line_to( cr, p[ inx ][ 0 ], p[ inx ][ 1 ] );
- cairo_fill( cr );
+ cairo_move_to(cr, p[ 0 ][ 0 ], p[ 0 ][ 1 ]);
+
+ for (inx=0; inx<cnt; inx++) {
+ cairo_line_to(cr, p[ inx ][ 0 ], p[ inx ][ 1 ]);
+ }
+
+ cairo_fill(cr);
}
/**
@@ -462,21 +513,25 @@ void psPrintFillPolygon(
*/
void psPrintFillCircle(
- wPos_t x0, wPos_t y0,
- wPos_t r,
- wDrawColor color,
- wDrawOpts opts )
+ wPos_t x0, wPos_t y0,
+ wPos_t r,
+ wDrawColor color,
+ wDrawOpts opts)
{
- if (color == wDrawColorWhite)
- return;
- if (opts&wDrawOptTemp)
- return;
- psSetColor(color);
+ if (color == wDrawColorWhite) {
+ return;
+ }
+
+ if (opts&wDrawOptTemp) {
+ return;
+ }
- cairo_arc( psPrint_d.printContext,
- x0, y0, r, 0.0, 2 * M_PI );
+ psSetColor(color);
- cairo_fill( psPrint_d.printContext );
+ cairo_arc(psPrint_d.printContext,
+ x0, y0, r, 0.0, 2 * M_PI);
+
+ cairo_fill(psPrint_d.printContext);
}
@@ -503,75 +558,78 @@ void psPrintFillCircle(
*/
void psPrintString(
- wPos_t x, wPos_t y,
- double a,
- char * s,
- wFont_p fp,
- double fs,
- wDrawColor color,
- wDrawOpts opts )
+ wPos_t x, wPos_t y,
+ double a,
+ char * s,
+ wFont_p fp,
+ double fs,
+ wDrawColor color,
+ wDrawOpts opts)
{
- char * cp;
- double x0 = (double)x, y0 = (double)y;
- double text_height;
-
- cairo_t *cr;
- cairo_matrix_t matrix;
-
- PangoLayout *layout;
- PangoFontDescription *desc;
- PangoFontMetrics *metrics;
- PangoContext *pcontext;
-
- if (color == wDrawColorWhite)
- return;
-
- cr = psPrint_d.printContext;
-
- // get the current transformation matrix and transform the starting
- // point of the string
- cairo_get_matrix( cr, &matrix );
- cairo_matrix_transform_point( &matrix, &x0, &y0 );
-
- cairo_save( cr );
-
- layout = pango_cairo_create_layout( cr );
-
- // set the correct font and size
- /** \todo use a getter function instead of double conversion */
- desc = pango_font_description_from_string (gtkFontTranslate( fp ));
-
- //don't know why the size has to be reduced to 75% :-(
- pango_font_description_set_size(desc, fs * PANGO_SCALE *0.75 );
-
- // render the string to a Pango layout
- pango_layout_set_font_description (layout, desc);
- pango_layout_set_text (layout, s, -1);
- pango_layout_set_width (layout, -1);
- pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
-
- // get the height of the string
- pcontext = pango_cairo_create_context( cr );
- metrics = pango_context_get_metrics(pcontext, desc, pango_context_get_language(pcontext));
- text_height = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
-
- // transform the string to the correct position
- cairo_identity_matrix( cr );
-
- cairo_translate( cr, x0 + text_height * sin ( -a * M_PI / 180.0) , y0 - text_height * cos ( a * M_PI / 180.0) );
- cairo_rotate( cr, -a * M_PI / 180.0 );
-
- // set the color
- psSetColor( color );
-
- // and show the string
- pango_cairo_show_layout (cr, layout);
-
- // free unused objects
- g_object_unref( layout );
- g_object_unref( pcontext );
-
- cairo_restore( cr );
+ char * cp;
+ double x0 = (double)x, y0 = (double)y;
+ double text_height;
+
+ cairo_t *cr;
+ cairo_matrix_t matrix;
+
+ PangoLayout *layout;
+ PangoFontDescription *desc;
+ PangoFontMetrics *metrics;
+ PangoContext *pcontext;
+
+ if (color == wDrawColorWhite) {
+ return;
+ }
+
+ cr = psPrint_d.printContext;
+
+ // get the current transformation matrix and transform the starting
+ // point of the string
+ cairo_get_matrix(cr, &matrix);
+ cairo_matrix_transform_point(&matrix, &x0, &y0);
+
+ cairo_save(cr);
+
+ layout = pango_cairo_create_layout(cr);
+
+ // set the correct font and size
+ /** \todo use a getter function instead of double conversion */
+ desc = pango_font_description_from_string(wlibFontTranslate(fp));
+
+ //don't know why the size has to be reduced to 75% :-(
+ pango_font_description_set_size(desc, fs * PANGO_SCALE *0.75);
+
+ // render the string to a Pango layout
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, s, -1);
+ pango_layout_set_width(layout, -1);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
+
+ // get the height of the string
+ pcontext = pango_cairo_create_context(cr);
+ metrics = pango_context_get_metrics(pcontext, desc,
+ pango_context_get_language(pcontext));
+ text_height = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
+
+ // transform the string to the correct position
+ cairo_identity_matrix(cr);
+
+ cairo_translate(cr, x0 + text_height * sin(-a * M_PI / 180.0) ,
+ y0 - text_height * cos(a * M_PI / 180.0));
+ cairo_rotate(cr, -a * M_PI / 180.0);
+
+ // set the color
+ psSetColor(color);
+
+ // and show the string
+ pango_cairo_show_layout(cr, layout);
+
+ // free unused objects
+ g_object_unref(layout);
+ g_object_unref(pcontext);
+
+ cairo_restore(cr);
}
/**
@@ -579,17 +637,17 @@ void psPrintString(
*
* \param x, y IN starting position
* \param w, h IN width and height of rectangle
- * \return
+ * \return
*/
-void wPrintClip( wPos_t x, wPos_t y, wPos_t w, wPos_t h )
+void wPrintClip(wPos_t x, wPos_t y, wPos_t w, wPos_t h)
{
- cairo_move_to( psPrint_d.printContext, x, y );
- cairo_rel_line_to( psPrint_d.printContext, w, 0 );
- cairo_rel_line_to( psPrint_d.printContext, 0, h );
- cairo_rel_line_to( psPrint_d.printContext, -w, 0 );
- cairo_close_path( psPrint_d.printContext );
- cairo_clip( psPrint_d.printContext );
+ cairo_move_to(psPrint_d.printContext, x, y);
+ cairo_rel_line_to(psPrint_d.printContext, w, 0);
+ cairo_rel_line_to(psPrint_d.printContext, 0, h);
+ cairo_rel_line_to(psPrint_d.printContext, -w, 0);
+ cairo_close_path(psPrint_d.printContext);
+ cairo_clip(psPrint_d.printContext);
}
/*****************************************************************************
@@ -604,24 +662,24 @@ void wPrintClip( wPos_t x, wPos_t y, wPos_t w, wPos_t h )
*/
static void
-WlibGetPaperSize( void )
+WlibGetPaperSize(void)
{
- double temp;
-
- bBorder = gtk_page_setup_get_bottom_margin( page_setup, GTK_UNIT_INCH );
- tBorder = gtk_page_setup_get_top_margin( page_setup, GTK_UNIT_INCH );
- lBorder = gtk_page_setup_get_left_margin( page_setup, GTK_UNIT_INCH );
- rBorder = gtk_page_setup_get_right_margin( page_setup, GTK_UNIT_INCH );
- paperHeight = gtk_page_setup_get_paper_height( page_setup, GTK_UNIT_INCH );
- paperWidth = gtk_page_setup_get_paper_width( page_setup, GTK_UNIT_INCH );
-
- // XTrackCAD does page orientation itself. Basic assumption is that the
- // paper is always oriented in portrait mode. Ignore settings by user
- if( paperHeight < paperWidth ) {
- temp = paperHeight;
- paperHeight = paperWidth;
- paperWidth = temp;
- }
+ double temp;
+
+ bBorder = gtk_page_setup_get_bottom_margin(page_setup, GTK_UNIT_INCH);
+ tBorder = gtk_page_setup_get_top_margin(page_setup, GTK_UNIT_INCH);
+ lBorder = gtk_page_setup_get_left_margin(page_setup, GTK_UNIT_INCH);
+ rBorder = gtk_page_setup_get_right_margin(page_setup, GTK_UNIT_INCH);
+ paperHeight = gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH);
+ paperWidth = gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH);
+
+ // XTrackCAD does page orientation itself. Basic assumption is that the
+ // paper is always oriented in portrait mode. Ignore settings by user
+ if (paperHeight < paperWidth) {
+ temp = paperHeight;
+ paperHeight = paperWidth;
+ paperWidth = temp;
+ }
}
/**
@@ -633,17 +691,18 @@ WlibGetPaperSize( void )
*/
void wPrintGetPageSize(
- double * w,
- double * h )
+ double * w,
+ double * h)
{
- // if necessary load the settings
- if( !settings )
- WlibApplySettings( NULL );
+ // if necessary load the settings
+ if (!settings) {
+ WlibApplySettings(NULL);
+ }
- WlibGetPaperSize();
+ WlibGetPaperSize();
- *w = paperWidth -lBorder - rBorder;
- *h = paperHeight - tBorder - bBorder;
+ *w = paperWidth -lBorder - rBorder;
+ *h = paperHeight - tBorder - bBorder;
}
/**
@@ -655,52 +714,53 @@ void wPrintGetPageSize(
*/
void wPrintGetPhysSize(
- double * w,
- double * h )
+ double * w,
+ double * h)
{
- // if necessary load the settings
- if( !settings )
- WlibApplySettings( NULL );
+ // if necessary load the settings
+ if (!settings) {
+ WlibApplySettings(NULL);
+ }
- WlibGetPaperSize();
+ WlibGetPaperSize();
- *w = paperWidth;
- *h = paperHeight;
+ *w = paperWidth;
+ *h = paperHeight;
}
/**
- * Cancel the current print job. This function is preserved here for
- * reference in case the function should be implemented again.
+ * Cancel the current print job. This function is preserved here for
+ * reference in case the function should be implemented again.
* \param context IN unused
* \return
*/
-static void printAbort( void * context )
+static void printAbort(void * context)
{
- printContinue = FALSE;
+ printContinue = FALSE;
// wWinShow( printAbortW, FALSE );
}
/**
* Initialize new page.
* The cairo_save() / cairo_restore() cycle was added to solve problems
- * with a multi page print operation. This might actually be a bug in
+ * with a multi page print operation. This might actually be a bug in
* cairo but I didn't examine that any further.
*
* \return print context for the print operation
*/
-wDraw_p wPrintPageStart( void )
+wDraw_p wPrintPageStart(void)
{
- pageCount++;
+ pageCount++;
- cairo_save( psPrint_d.printContext );
-
- return &psPrint_d;
+ cairo_save(psPrint_d.printContext);
+
+ return &psPrint_d;
}
/**
* End of page. This function returns the contents of printContinue. The
- * caller continues printing as long as TRUE is returned. Setting
- * printContinue to FALSE in an asynchronous handler therefore cleanly
+ * caller continues printing as long as TRUE is returned. Setting
+ * printContinue to FALSE in an asynchronous handler therefore cleanly
* terminates a print job at the end of the page.
*
* \param p IN ignored
@@ -708,13 +768,13 @@ wDraw_p wPrintPageStart( void )
*/
-wBool_t wPrintPageEnd( wDraw_p p )
+wBool_t wPrintPageEnd(wDraw_p p)
{
- cairo_show_page( psPrint_d.printContext );
-
- cairo_restore( psPrint_d.printContext );
-
- return printContinue;
+ cairo_show_page(psPrint_d.printContext);
+
+ cairo_restore(psPrint_d.printContext);
+
+ return printContinue;
}
/*****************************************************************************
@@ -733,76 +793,91 @@ wBool_t wPrintPageEnd( wDraw_p p )
* \return TRUE if successful, FALSE if cancelled by user
*/
-wBool_t wPrintDocStart( const char * title, int fTotalPageCount, int * copiesP )
+wBool_t wPrintDocStart(const char * title, int fTotalPageCount, int * copiesP)
{
- GtkWidget *printDialog;
- gint res;
- cairo_surface_type_t surface_type;
- cairo_matrix_t matrix;
-
- printDialog = gtk_print_unix_dialog_new( title, GTK_WINDOW(gtkMainW->gtkwin));
-
- // load the settings
- WlibApplySettings( NULL );
-
- // and apply them to the printer dialog
- gtk_print_unix_dialog_set_settings( (GtkPrintUnixDialog *)printDialog, settings );
- gtk_print_unix_dialog_set_page_setup( (GtkPrintUnixDialog *)printDialog, page_setup );
-
- res = gtk_dialog_run( (GtkDialog *)printDialog );
- if( res == GTK_RESPONSE_OK ) {
- selPrinter = gtk_print_unix_dialog_get_selected_printer( (GtkPrintUnixDialog *)printDialog );
-
- if( settings )
- g_object_unref (settings);
- settings = gtk_print_unix_dialog_get_settings( (GtkPrintUnixDialog *)printDialog );
-
- if( page_setup )
- g_object_unref( page_setup );
- page_setup = gtk_print_unix_dialog_get_page_setup( (GtkPrintUnixDialog *)printDialog );
-
- curPrintJob = gtk_print_job_new( title,
- selPrinter,
- settings,
- page_setup );
-
- psPrint_d.curPrintSurface = gtk_print_job_get_surface( curPrintJob,
- NULL );
- psPrint_d.printContext = cairo_create( psPrint_d.curPrintSurface );
-
- //update the paper dimensions
- WlibGetPaperSize();
-
- /* for the file based surfaces the resolution is 72 dpi (see documentation) */
- surface_type = cairo_surface_get_type( psPrint_d.curPrintSurface );
- if( surface_type == CAIRO_SURFACE_TYPE_PDF ||
- surface_type == CAIRO_SURFACE_TYPE_PS ||
- surface_type == CAIRO_SURFACE_TYPE_SVG )
- psPrint_d.dpi = 72;
- else
- psPrint_d.dpi = (double)gtk_print_settings_get_resolution( settings );
-
- // in XTrackCAD 0,0 is top left, in cairo bottom left. This is
- // corrected via the following transformations.
- // also the translate makes sure that the drawing is rendered
- // within the paper margins
-
- cairo_scale( psPrint_d.printContext, 1.0, -1.0 );
- cairo_translate( psPrint_d.printContext, lBorder * psPrint_d.dpi, -(paperHeight-bBorder) *psPrint_d.dpi );
-
- WlibSaveSettings( NULL );
- }
- gtk_widget_destroy (printDialog);
-
- if (copiesP)
- *copiesP = 1;
-
- printContinue = TRUE;
-
- if( res != GTK_RESPONSE_OK )
- return FALSE;
- else
- return TRUE;
+ GtkWidget *printDialog;
+ gint res;
+ cairo_surface_type_t surface_type;
+ cairo_matrix_t matrix;
+
+ printDialog = gtk_print_unix_dialog_new(title, GTK_WINDOW(gtkMainW->gtkwin));
+
+ // load the settings
+ WlibApplySettings(NULL);
+
+ // and apply them to the printer dialog
+ gtk_print_unix_dialog_set_settings((GtkPrintUnixDialog *)printDialog, settings);
+ gtk_print_unix_dialog_set_page_setup((GtkPrintUnixDialog *)printDialog,
+ page_setup);
+
+ res = gtk_dialog_run((GtkDialog *)printDialog);
+
+ if (res == GTK_RESPONSE_OK) {
+ selPrinter = gtk_print_unix_dialog_get_selected_printer((
+ GtkPrintUnixDialog *)printDialog);
+
+ if (settings) {
+ g_object_unref(settings);
+ }
+
+ settings = gtk_print_unix_dialog_get_settings((GtkPrintUnixDialog *)
+ printDialog);
+
+ if (page_setup) {
+ g_object_unref(page_setup);
+ }
+
+ page_setup = gtk_print_unix_dialog_get_page_setup((GtkPrintUnixDialog *)
+ printDialog);
+
+ curPrintJob = gtk_print_job_new(title,
+ selPrinter,
+ settings,
+ page_setup);
+
+ psPrint_d.curPrintSurface = gtk_print_job_get_surface(curPrintJob,
+ NULL);
+ psPrint_d.printContext = cairo_create(psPrint_d.curPrintSurface);
+
+ //update the paper dimensions
+ WlibGetPaperSize();
+
+ /* for the file based surfaces the resolution is 72 dpi (see documentation) */
+ surface_type = cairo_surface_get_type(psPrint_d.curPrintSurface);
+
+ if (surface_type == CAIRO_SURFACE_TYPE_PDF ||
+ surface_type == CAIRO_SURFACE_TYPE_PS ||
+ surface_type == CAIRO_SURFACE_TYPE_SVG) {
+ psPrint_d.dpi = 72;
+ } else {
+ psPrint_d.dpi = (double)gtk_print_settings_get_resolution(settings);
+ }
+
+ // in XTrackCAD 0,0 is top left, in cairo bottom left. This is
+ // corrected via the following transformations.
+ // also the translate makes sure that the drawing is rendered
+ // within the paper margins
+
+ cairo_scale(psPrint_d.printContext, 1.0, -1.0);
+ cairo_translate(psPrint_d.printContext, lBorder * psPrint_d.dpi,
+ -(paperHeight-bBorder) *psPrint_d.dpi);
+
+ WlibSaveSettings(NULL);
+ }
+
+ gtk_widget_destroy(printDialog);
+
+ if (copiesP) {
+ *copiesP = 1;
+ }
+
+ printContinue = TRUE;
+
+ if (res != GTK_RESPONSE_OK) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
}
/**
@@ -815,17 +890,18 @@ wBool_t wPrintDocStart( const char * title, int fTotalPageCount, int * copiesP )
*/
void
-doPrintJobFinished( GtkPrintJob *job, void *data, GError *err )
+doPrintJobFinished(GtkPrintJob *job, void *data, GError *err)
{
- GtkWidget *dialog;
-
- cairo_destroy( psPrint_d.printContext );
- if( err ) {
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtkMainW->gtkwin),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- err->message);
- }
+ GtkWidget *dialog;
+
+ cairo_destroy(psPrint_d.printContext);
+
+ if (err) {
+ dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ err->message);
+ }
}
/**
@@ -833,26 +909,26 @@ doPrintJobFinished( GtkPrintJob *job, void *data, GError *err )
* \return
*/
-void wPrintDocEnd( void )
+void wPrintDocEnd(void)
{
- cairo_surface_finish( psPrint_d.curPrintSurface );
+ cairo_surface_finish(psPrint_d.curPrintSurface);
- gtk_print_job_send( curPrintJob,
- doPrintJobFinished,
- NULL,
- NULL );
+ gtk_print_job_send(curPrintJob,
+ doPrintJobFinished,
+ NULL,
+ NULL);
// wWinShow( printAbortW, FALSE );
}
-wBool_t wPrintQuit( void )
+wBool_t wPrintQuit(void)
{
- return FALSE;
+ return FALSE;
}
-wBool_t wPrintInit( void )
+wBool_t wPrintInit(void)
{
- return TRUE;
+ return TRUE;
}
diff --git a/app/wlib/gtklib/single.c b/app/wlib/gtklib/single.c
new file mode 100644
index 0000000..45ed6e4
--- /dev/null
+++ b/app/wlib/gtklib/single.c
@@ -0,0 +1,335 @@
+/** \file single.c
+ * Single line entry field for text
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2005 Dave Bullis, 2012 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.
+ */
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+// #define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#include "gtkint.h"
+
+#define TIMEOUT_INACTIVITY (500) /**< timeout for entry fields in millisecs */
+
+/*
+ *****************************************************************************
+ *
+ * Text Boxes
+ *
+ *****************************************************************************
+ */
+
+struct wString_t {
+ WOBJ_COMMON
+ char *valueP; /**< pointer to result buffer */
+ wIndex_t valueL; /**< maximum length */
+ wStringCallBack_p action; /**< callback for changes */
+ wBool_t busy; /**< busy flag to prevent re-entry problems? */
+ wBool_t hasSignal; /** needs signal to be suppressed */
+ guint timer; /**< timer source for inactivity timer */
+};
+
+/**
+ * Set the string value in a string entry field
+ *
+ * \param b IN widget to be updated
+ * \param arg IN new string value
+ * \return
+ */
+
+void wStringSetValue(
+ wString_p b,
+ const char *arg)
+{
+ if (b->widget == NULL)
+ abort();
+
+ // the contents should not be changed programatically while
+ // the user is editing it
+ if( !(gtk_widget_has_focus(b->widget))) {
+ if (b->hasSignal)
+ gtk_signal_handler_block_by_data(GTK_OBJECT(b->widget), b);
+ gtk_entry_set_text(GTK_ENTRY(b->widget), arg);
+ if (b->hasSignal)
+ gtk_signal_handler_unblock_by_data(GTK_OBJECT(b->widget), b);
+ }
+}
+
+/**
+ * Set the width of the entry field
+ *
+ * \param b IN widget to be updated
+ * \param w IN new width
+ * \return
+ */
+
+void wStringSetWidth(
+ wString_p b,
+ wPos_t w)
+{
+ gtk_widget_set_size_request(b->widget, w, -1);
+ b->w = w;
+}
+
+/**
+ * Return the entered value
+ *
+ * \param b IN entry field
+ * \return the entered text
+ */
+
+const char *wStringGetValue(
+ wString_p b)
+{
+ if ( !b->widget )
+ abort();
+
+ return gtk_entry_get_text(GTK_ENTRY(b->widget));
+}
+
+/**
+ * Kill an active timer
+ *
+ * \param b IN entry field
+ * \return the entered text
+ */
+
+static gboolean killTimer(
+ GtkEntry *widget,
+ GdkEvent *event,
+ wString_p b)
+{
+
+ // remove all timers related to this widget
+ while( g_source_remove_by_user_data( b ))
+ ;
+ b->timer = 0;
+
+ if (b->action) {
+ const char *s;
+
+ s = gtk_entry_get_text(GTK_ENTRY(b->widget));
+ b->action(s, b->data);
+ }
+ gtk_editable_select_region( GTK_EDITABLE( widget ), 0, 0 );
+ return( FALSE );
+}
+
+/**
+ * Timer handler for string activity. This timer expires if the user
+ * doesn't change an entry value within the preset time.
+ */
+
+static gboolean
+timeoutString( wString_p bs )
+{
+
+ if ( !bs )
+ return( FALSE );
+ if (bs->widget == 0)
+ abort();
+
+ if (bs->action) {
+ const char *s;
+
+ s = gtk_entry_get_text(GTK_ENTRY(bs->widget));
+ if ( s )
+ bs->action(s, bs->data);
+ }
+
+ bs->timer = 0;
+ return( FALSE );
+}
+
+/**
+ * Signal handler for 'activate' signal: callback with the current value and then
+ * select the whole default value
+ *
+ * \param widget IN the edit field
+ * \param b IN the widget data structure
+ * \return
+ */
+
+static gboolean stringActivated(
+ GtkEntry *widget,
+ wString_p b)
+{
+ const char *s;
+
+ if ( !b )
+ return( FALSE );
+
+ s = wStringGetValue(b);
+
+ if (b->valueP)
+ strcpy(b->valueP, s);
+
+ if (b->action) {
+ b->action(s, b->data);
+ }
+
+ // select the complete default value to make editing it easier
+ gtk_editable_select_region( GTK_EDITABLE( widget ), 0, -1 );
+ return( FALSE );
+}
+
+/**
+ * Signal handler for changes in an entry field
+ *
+ * \param widget IN
+ * \param entry field IN
+ * \return
+ */
+
+static void stringChanged(
+ GtkEntry *widget,
+ wString_p b)
+{
+ const char *new_value;
+
+ if ( !b || b->busy )
+ return;
+
+ // get the entered value
+ new_value = wStringGetValue(b);
+ if (b->valueP != NULL)
+ strcpy(b->valueP, new_value);
+
+ //
+ if (b->action){
+ // if one exists, remove the inactivity timer
+ if( b->timer )
+ g_source_remove( b->timer );
+
+ // create a new timer
+ b->timer = g_timeout_add( TIMEOUT_INACTIVITY,
+ (GSourceFunc)timeoutString,
+ b );
+
+ }
+ return;
+}
+
+/**
+ * Create a single line entry field for a string value
+ *
+ * \param parent IN parent widget
+ * \param x IN x position
+ * \param y IN y position
+ * \param helpStr IN help anchor
+ * \param labelStr IN label
+ * \param option IN option (supported BO_READONLY )
+ * \param width IN width of entry field
+ * \param valueP IN default value
+ * \param valueL IN maximum length of entry
+ * \param action IN application callback function
+ * \param data IN application data
+ * \return the created widget
+ */
+
+wString_p wStringCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char *helpStr,
+ const char *labelStr,
+ long option,
+ wPos_t width,
+ char *valueP,
+ wIndex_t valueL,
+ wStringCallBack_p action,
+ void *data)
+{
+ wString_p b;
+
+ // create and initialize the widget
+ b = (wString_p)wlibAlloc(parent, B_TEXT, x, y, labelStr, sizeof *b, data);
+ b->valueP = valueP;
+ b->action = action;
+ b->option = option;
+ b->valueL = valueL;
+ b->timer = 0;
+ b->hasSignal = 0;
+ wlibComputePos((wControl_p)b);
+
+ // create the gtk entry field and set maximum length if desired
+ b->widget = (GtkWidget *)gtk_entry_new();
+ if (b->widget == NULL) abort();
+
+ if( valueL )
+ gtk_entry_set_max_length( GTK_ENTRY( b->widget ), valueL );
+
+ // it is assumed that the parent is a fixed layout widget and the entry can
+ // be placed at a specific position
+ gtk_fixed_put(GTK_FIXED(parent->widget), b->widget, b->realX, b->realY);
+
+ // set minimum size for widget
+ if (width)
+ gtk_widget_set_size_request(b->widget, width, -1);
+
+ // get the resulting size
+ wlibControlGetSize((wControl_p)b);
+
+ // if desired, place a label in front of the created widget
+ if (labelStr)
+ b->labelW = wlibAddLabel((wControl_p)b, labelStr);
+
+ if (option & BO_READONLY)
+ gtk_editable_set_editable(GTK_EDITABLE(b->widget), FALSE);
+
+ // set the default text and select it to make replacing it easier
+ if (b->valueP) {
+ wStringSetValue(b, b->valueP);
+ // select the text only if text is editable
+ }
+
+ // show
+ gtk_widget_show(b->widget);
+
+ // add the new widget to the list of created widgets
+ wlibAddButton((wControl_p)b);
+
+ // link into help
+ wlibAddHelpString(b->widget, helpStr);
+
+ g_signal_connect(GTK_OBJECT(b->widget), "changed", G_CALLBACK(stringChanged), b);
+ //g_signal_connect(GTK_OBJECT(b->widget), "activate", G_CALLBACK(stringActivated), b);
+ b->hasSignal = 1;
+
+ // set the default text and select it to make replacing it easier
+ if (b->valueP) {
+ wStringSetValue(b, b->valueP);
+ // select the text only if text is editable
+ }
+
+ gtk_widget_add_events( b->widget, GDK_FOCUS_CHANGE_MASK );
+ g_signal_connect(GTK_OBJECT(b->widget), "focus-out-event", G_CALLBACK(killTimer), b);
+
+ return b;
+}
diff --git a/app/wlib/gtklib/splash.c b/app/wlib/gtklib/splash.c
new file mode 100644
index 0000000..0d5be50
--- /dev/null
+++ b/app/wlib/gtklib/splash.c
@@ -0,0 +1,144 @@
+/** \file splash.c
+ * Handling of the Splash Window functions
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2007 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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+
+#include "gtkint.h"
+
+#define LOGOFILENAME "logo.bmp"
+
+static GtkWidget *window; /**< splash window handle */
+static GtkWidget *message; /**< window handle for progress message */
+
+/**
+ * Create the splash window shown during startup. The function loads the logo
+ * bitmap and displays the program name and version as passed.
+ *
+ * \param IN appName the product name to be shown
+ * \param IN appVer the product version to be shown
+ * \return TRUE if window was created, FALSE if an error occured
+ */
+
+int
+wCreateSplash(char *appName, char *appVer)
+{
+ GtkWidget *vbox;
+ GtkWidget *image;
+ GtkWidget *label;
+ char *temp;
+ char logoPath[BUFSIZ];
+
+ /* create the basic window */
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
+ gtk_window_set_title(GTK_WINDOW(window), appName);
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+ gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
+#if GTK_MINOR_VERSION > 5
+ gtk_window_set_focus_on_map(GTK_WINDOW(window), FALSE);
+#endif
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_widget_show(vbox);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+
+ /* add the logo image to the top of the splash window */
+ sprintf(logoPath, "%s/" LOGOFILENAME, wGetAppLibDir());
+ image = gtk_image_new_from_file(logoPath);
+ gtk_widget_show(image);
+ gtk_box_pack_start(GTK_BOX(vbox), image, TRUE, TRUE, 0);
+ gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
+
+ /* put the product name into the window */
+
+ temp = malloc(strlen(appName) + strlen(appVer) + 2);
+
+ if (!temp) {
+ return (FALSE);
+ }
+
+ sprintf(temp, "%s %s", appName, appVer);
+
+ label = gtk_label_new(temp);
+ gtk_widget_show(label);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_FILL);
+ gtk_label_set_selectable(GTK_LABEL(label), FALSE);
+ gtk_misc_set_padding(GTK_MISC(label), 6, 2);
+
+ free(temp);
+
+ label = gtk_label_new("Application is starting...");
+ gtk_widget_show(label);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ gtk_label_set_line_wrap(GTK_LABEL(label), FALSE);
+ gtk_misc_set_padding(GTK_MISC(label), 6, 2);
+#if GTK_MINOR_VERSION > 5
+ gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_START);
+#endif
+ message = label;
+
+ gtk_widget_show(window);
+
+ return (TRUE);
+}
+
+/**
+ * Update the progress message inside the splash window
+ * msg text message to display
+ * return nonzero if ok
+ */
+
+int
+wSetSplashInfo(char *msg)
+{
+ if (msg) {
+ gtk_label_set_text((GtkLabel *)message, msg);
+ wFlush();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Destroy the splash window.
+ *
+ */
+
+void
+wDestroySplash(void)
+{
+ /* kill window */
+ gtk_widget_destroy(window);
+ return;
+}
diff --git a/app/wlib/gtklib/square10.bmp b/app/wlib/gtklib/square10.bmp
deleted file mode 100644
index b2eee6e..0000000
--- a/app/wlib/gtklib/square10.bmp
+++ /dev/null
@@ -1,8 +0,0 @@
-#define square10_width 14
-#define square10_height 14
-// Changed to eliminate compile-time warning
-//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/wlib/gtklib/text.c b/app/wlib/gtklib/text.c
new file mode 100644
index 0000000..5445984
--- /dev/null
+++ b/app/wlib/gtklib/text.c
@@ -0,0 +1,590 @@
+/** \file text.c
+ * multi line text entry widget
+ */
+
+/* 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 <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "i18n.h"
+#include "gtkint.h"
+
+struct PrintData {
+ wText_p tb;
+ gint lines_per_page;
+ gdouble font_size;
+ gchar **lines;
+ gint total_lines;
+ gint total_pages;
+};
+
+#define HEADER_HEIGHT 20.0
+#define HEADER_GAP 8.5
+
+
+/*
+ *****************************************************************************
+ *
+ * Multi-line Text Boxes
+ *
+ *****************************************************************************
+ */
+
+struct wText_t {
+ WOBJ_COMMON
+ wPos_t width, height;
+ int changed;
+ GtkWidget *text;
+};
+
+/**
+ * Reset a text entry by clearing text and resetting the readonly and the
+ * change flag.
+ *
+ * \param bt IN text entry
+ * \return
+ */
+
+void wTextClear(wText_p bt)
+{
+ GtkTextBuffer *tb;
+ tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text));
+ gtk_text_buffer_set_text(tb, "", -1);
+
+ if (bt->option & BO_READONLY) {
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(bt->text), FALSE);
+ }
+
+ bt->changed = FALSE;
+}
+
+/**
+ * Append text to the end of the entry field's text buffer.
+ *
+ * \param bt IN text buffer
+ * \param text IN text to append
+ * \return
+ */
+
+void wTextAppend(wText_p bt,
+ const char *text)
+{
+ GtkTextBuffer *tb;
+ GtkTextIter ti1;
+
+ if (bt->text == 0) {
+ abort();
+ }
+
+ tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text));
+ // convert to utf-8
+ text = wlibConvertInput(text);
+ // append to end of buffer
+ gtk_text_buffer_get_end_iter(tb, &ti1);
+ gtk_text_buffer_insert(tb, &ti1, text, -1);
+ bt->changed = FALSE;
+}
+
+/**
+ * Get the text from a text buffer in system codepage
+ * The caller is responsible for free'ing the allocated storage.
+ *
+ * \todo handling of return from gtkConvertOutput can be improved
+ *
+ * \param bt IN the text widget
+ * \return pointer to the converted text
+ */
+
+static char *wlibGetText(wText_p bt)
+{
+ GtkTextBuffer *tb;
+ GtkTextIter ti1, ti2;
+ char *cp, *cp1, *res;
+
+ if (bt->text == 0) {
+ abort();
+ }
+
+ tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text));
+ gtk_text_buffer_get_bounds(tb, &ti1, &ti2);
+ cp = gtk_text_buffer_get_text(tb, &ti1, &ti2, FALSE);
+ cp1 = wlibConvertOutput(cp);
+ res = strdup(cp1);
+ g_free(cp);
+ return res;
+}
+
+/**
+ * Save the text from the widget to a file
+ *
+ * \param bt IN the text widget
+ * \param fileName IN name of save file
+ * \return TRUE is success, FALSE if not
+ */
+
+wBool_t wTextSave(wText_p bt, const char *fileName)
+{
+ FILE *f;
+ char *cp;
+ f = fopen(fileName, "w");
+
+ if (f==NULL) {
+ wNoticeEx(NT_ERROR, fileName, "Ok", NULL);
+ return FALSE;
+ }
+
+ cp = wlibGetText(bt);
+ fwrite(cp, 1, strlen(cp), f);
+ free(cp);
+ fclose(f);
+ return TRUE;
+}
+
+/**
+ * Begin the printing by retrieving the contents of the text box and
+ * count the lines of text.
+ *
+ * \param operation IN the GTK print operation
+ * \param context IN print context
+ * \param pd IN data structure for user data
+ *
+ */
+
+static void
+begin_print(GtkPrintOperation *operation,
+ GtkPrintContext *context,
+ struct PrintData *pd)
+{
+ gchar *contents;
+ gdouble height;
+ contents = wlibGetText(pd->tb);
+ pd->lines = g_strsplit(contents, "\n", 0);
+ /* Count the total number of lines in the file. */
+ /* ignore the header lines */
+ pd->total_lines = 6;
+
+ while (pd->lines[pd->total_lines] != NULL) {
+ pd->total_lines++;
+ }
+
+ /* Based on the height of the page and font size, calculate how many lines can be
+ * rendered on a single page. A padding of 3 is placed between lines as well.
+ * Space for page header, table header and footer lines is subtracted from the total size
+ */
+ height = gtk_print_context_get_height(context) - (pd->font_size + 3) - 2 *
+ (HEADER_HEIGHT + HEADER_GAP);
+ pd->lines_per_page = floor(height / (pd->font_size + 3));
+ pd->total_pages = (pd->total_lines - 1) / pd->lines_per_page + 1;
+ gtk_print_operation_set_n_pages(operation, pd->total_pages);
+ free(contents);
+}
+
+/**
+ * Draw the page, which includes a header with the file name and page number along
+ * with one page of text with a font of "Monospace 10".
+ *
+ * \param operation IN the GTK print operation
+ * \param context IN print context
+ * \param page_nr IN page to print
+ * \param pd IN data structure for user data
+ *
+ *
+ */
+
+static void
+draw_page(GtkPrintOperation *operation,
+ GtkPrintContext *context,
+ gint page_nr,
+ struct PrintData *pd)
+{
+ cairo_t *cr;
+ PangoLayout *layout;
+ gdouble width, text_height, height;
+ gint line, i, text_width, layout_height;
+ PangoFontDescription *desc;
+ gchar *page_str;
+ cr = gtk_print_context_get_cairo_context(context);
+ width = gtk_print_context_get_width(context);
+ layout = gtk_print_context_create_pango_layout(context);
+ desc = pango_font_description_from_string("Monospace");
+ pango_font_description_set_size(desc, pd->font_size * PANGO_SCALE);
+ /*
+ * render the header line with document type parts list on left and
+ * first line of layout title on right
+ */
+ pango_layout_set_font_description(layout, desc);
+ pango_layout_set_text(layout, pd->lines[ 0 ], -1); // document type
+ pango_layout_set_width(layout, -1);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
+ pango_layout_get_size(layout, NULL, &layout_height);
+ text_height = (gdouble) layout_height / PANGO_SCALE;
+ cairo_move_to(cr, 0, (HEADER_HEIGHT - text_height) / 2);
+ pango_cairo_show_layout(cr, layout);
+ pango_layout_set_text(layout, pd->lines[ 2 ], -1); // layout title
+ pango_layout_get_size(layout, &text_width, NULL);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
+ cairo_move_to(cr, width - (text_width / PANGO_SCALE),
+ (HEADER_HEIGHT - text_height) / 2);
+ pango_cairo_show_layout(cr, layout);
+ /* Render the column header */
+ cairo_move_to(cr, 0, HEADER_HEIGHT + HEADER_GAP + pd->font_size + 3);
+ pango_layout_set_text(layout, pd->lines[ 6 ], -1);
+ pango_cairo_show_layout(cr, layout);
+ cairo_rel_move_to(cr, 0, pd->font_size + 3);
+ pango_layout_set_text(layout, pd->lines[ 7 ], -1);
+ pango_cairo_show_layout(cr, layout);
+ /* Render the page text with the specified font and size. */
+ cairo_rel_move_to(cr, 0, pd->font_size + 3);
+ line = page_nr * pd->lines_per_page + 8;
+
+ for (i = 0; i < pd->lines_per_page && line < pd->total_lines; i++) {
+ pango_layout_set_text(layout, pd->lines[line], -1);
+ pango_cairo_show_layout(cr, layout);
+ cairo_rel_move_to(cr, 0, pd->font_size + 3);
+ line++;
+ }
+
+ /*
+ * Render the footer line with date on the left and page number
+ * on the right
+ */
+ pango_layout_set_text(layout, pd->lines[ 5 ], -1); // date
+ pango_layout_set_width(layout, -1);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
+ pango_layout_get_size(layout, NULL, &layout_height);
+ text_height = (gdouble) layout_height / PANGO_SCALE;
+ height = gtk_print_context_get_height(context);
+ cairo_move_to(cr, 0, height - ((HEADER_HEIGHT - text_height) / 2));
+ pango_cairo_show_layout(cr, layout);
+ page_str = g_strdup_printf(_("%d of %d"), page_nr + 1,
+ pd->total_pages); // page number
+ pango_layout_set_text(layout, page_str, -1);
+ pango_layout_get_size(layout, &text_width, NULL);
+ pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
+ cairo_move_to(cr, width - (text_width / PANGO_SCALE),
+ height - ((HEADER_HEIGHT - text_height) / 2));
+ pango_cairo_show_layout(cr, layout);
+ g_free(page_str);
+ g_object_unref(layout);
+ pango_font_description_free(desc);
+}
+
+/**
+ * Clean up after the printing operation since it is done.
+ *
+ * \param operation IN the GTK print operation
+ * \param context IN print context
+ * \param pd IN data structure for user data
+ *
+ *
+ */
+static void
+end_print(GtkPrintOperation *operation,
+ GtkPrintContext *context,
+ struct PrintData *pd)
+{
+ g_strfreev(pd->lines);
+ free(pd);
+}
+
+/**
+ * Print the content of a multi line text box. This function is only used
+ * for printing the parts list. So it makes some assumptions on the structure
+ * and the content. Change if the multi line entry is changed.
+ * The deprecated gtk_text is not supported by this function.
+ *
+ * Thanks to Andrew Krause's book for a good starting point.
+ *
+ * \param bt IN the text field
+ * \return TRUE on success, FALSE on error
+ */
+
+wBool_t wTextPrint(
+ wText_p bt)
+{
+ GtkPrintOperation *operation;
+ GtkWidget *dialog;
+ GError *error = NULL;
+ gint res;
+ struct PrintData *data;
+ /* Create a new print operation, applying saved print settings if they exist. */
+ operation = gtk_print_operation_new();
+ WlibApplySettings(operation);
+ data = malloc(sizeof(struct PrintData));
+ data->font_size = 10.0;
+ data->tb = bt;
+ g_signal_connect(G_OBJECT(operation), "begin_print",
+ G_CALLBACK(begin_print), (gpointer) data);
+ g_signal_connect(G_OBJECT(operation), "draw_page",
+ G_CALLBACK(draw_page), (gpointer) data);
+ g_signal_connect(G_OBJECT(operation), "end_print",
+ G_CALLBACK(end_print), (gpointer) data);
+ /* Run the default print operation that will print the selected file. */
+ res = gtk_print_operation_run(operation,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ GTK_WINDOW(gtkMainW->gtkwin), &error);
+
+ /* If the print operation was accepted, save the new print settings. */
+ if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+ WlibSaveSettings(operation);
+ }
+ /* Otherwise, report that the print operation has failed. */
+ else if (error) {
+ dialog = gtk_message_dialog_new(GTK_WINDOW(gtkMainW->gtkwin),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ error->message);
+ g_error_free(error);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ }
+
+ g_object_unref(operation);
+ return TRUE;
+}
+
+
+/**
+ * Get the length of text
+ *
+ * \param bt IN the text widget
+ * \return length of string
+ */
+
+int wTextGetSize(wText_p bt)
+{
+ char *cp = wlibGetText(bt);
+ int len = strlen(cp);
+ free(cp);
+ return len;
+}
+
+/**
+ * Get the text
+ *
+ * \param bt IN the text widget
+ * \param text IN the buffer
+ * \param len IN maximum number of bytes to return
+ * \return
+ */
+
+void wTextGetText(wText_p bt, char *text, int len)
+{
+ char *cp;
+ cp = wlibGetText(bt);
+ strncpy(text, cp, len);
+
+ if (len > 0) {
+ text[len - 1] = '\0';
+ }
+
+ free(cp);
+}
+
+/**
+ * Get the read-only state of the text entry
+ *
+ * \param bt IN the text widget
+ * \param ro IN read only flag
+ * \return
+ */
+
+void wTextSetReadonly(wText_p bt, wBool_t ro)
+{
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(bt->text), !ro);
+
+ if (ro) {
+ bt->option |= BO_READONLY;
+ } else {
+ bt->option &= ~BO_READONLY;
+ }
+}
+
+/**
+ * check whether text has been modified
+ *
+ * \param bt IN the text widget
+ * \return TRUE of changed, FALSE otherwise
+ */
+
+wBool_t wTextGetModified(wText_p bt)
+{
+ return bt->changed;
+}
+
+/**
+ * set the size of the text widget
+ *
+ * \param bt IN the text widget
+ * \param w IN width
+ * \param h IN height
+ * \return
+ */
+
+void wTextSetSize(wText_p bt, wPos_t w, wPos_t h)
+{
+ gtk_widget_set_size_request(bt->widget, w, h);
+ bt->w = w;
+ bt->h = h;
+}
+
+/**
+ * calculate the required size of the widget based on number of lines and columns
+ * \todo this calculation is based on a fixed size font and is not useful in a generic setup
+ *
+ * \param bt IN the text widget
+ * \param rows IN text rows
+ * \param cols IN text columns
+ * \param width OUT width in pixel
+ * \param height OUT height in pixel
+ * \return
+ */
+
+void wTextComputeSize(wText_p bt, int rows, int cols, wPos_t *width,
+ wPos_t *height)
+{
+ *width = rows * 7;
+ *height = cols * 14;
+}
+
+/**
+ * set the position of the text widget ????
+ *
+ * \param bt IN the text widget
+ * \param pos IN position
+ * \return
+ */
+
+void wTextSetPosition(wText_p bt, int pos)
+{
+ /* TODO */
+}
+
+/**
+ * signal handler for changed signal
+ *
+ * \param widget IN
+ * \param bt IN text entry field
+ * \return
+ */
+
+static void textChanged(GtkWidget *widget, wText_p bt)
+{
+ if (bt == 0) {
+ return;
+ }
+
+ bt->changed = TRUE;
+}
+
+/**
+ * Create a multiline text entry field
+ *
+ * \param parent IN parent window
+ * \param x IN x position
+ * \param Y IN y position
+ * \param helpStr IN balloon help string
+ * \param labelStr IN Button label ???
+ * \param option IN
+ * \param width IN
+ * \param valueP IN Current color ???
+ * \param action IN Button callback procedure
+ * \param data IN ???
+ * \return bb handle for created text widget
+ */
+
+wText_p
+wTextCreate(wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char *helpStr,
+ const char *labelStr,
+ long option,
+ wPos_t width,
+ wPos_t height)
+{
+ wText_p bt;
+ GtkTextBuffer *tb;
+ // create the widget
+ bt = wlibAlloc(parent, B_MULTITEXT, x, y, labelStr, sizeof *bt, NULL);
+ bt->width = width;
+ bt->height = height;
+ bt->option = option;
+ wlibComputePos((wControl_p)bt);
+ // create a scroll window with scroll bars that are automatically created
+ bt->widget = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(bt->widget),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ // create a text view and place it inside the scroll widget
+ bt->text = gtk_text_view_new();
+
+ if (bt->text == 0) {
+ abort();
+ }
+
+ gtk_container_add(GTK_CONTAINER(bt->widget), bt->text);
+ // get the text buffer and add a bold tag to it
+ tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bt->text));
+ gtk_text_buffer_create_tag(tb, "bold", "weight", PANGO_WEIGHT_BOLD, NULL);
+
+ // this seems to assume some fixed size fonts, not really helpful
+ if (option&BT_CHARUNITS) {
+ width *= 7;
+ height *= 14;
+ }
+
+ // show the widgets
+ gtk_widget_show(bt->text);
+ gtk_widget_show(bt->widget);
+ // set the size???
+ gtk_widget_set_size_request(GTK_WIDGET(bt->widget),
+ width+15/*requisition.width*/, height);
+
+ // configure read-only mode
+ if (bt->option&BO_READONLY) {
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(bt->text), FALSE);
+ gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(bt->text), FALSE);
+ }
+
+ if (labelStr) {
+ bt->labelW = wlibAddLabel((wControl_p)bt, labelStr);
+ }
+
+ wlibAddHelpString(bt->widget, helpStr);
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(bt->text), GTK_WRAP_WORD);
+ g_signal_connect(G_OBJECT(tb), "changed", G_CALLBACK(textChanged), bt);
+ // place the widget in a fixed position of the parent
+ gtk_fixed_put(GTK_FIXED(parent->widget), bt->widget, bt->realX, bt->realY);
+ wlibControlGetSize((wControl_p)bt);
+ wlibAddButton((wControl_p)bt);
+ // done, return the finished widget
+ return bt;
+}
diff --git a/app/wlib/gtklib/timer.c b/app/wlib/gtklib/timer.c
new file mode 100644
index 0000000..812908f
--- /dev/null
+++ b/app/wlib/gtklib/timer.c
@@ -0,0 +1,144 @@
+/** \file timer.c
+ * Timer Functions
+ *
+ * Copyright 2016 Martin Fischer <m_fischer@sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <signal.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+//#include "i18n.h"
+
+static wBool_t gtkPaused = FALSE;
+static int alarmTimer = 0;
+static struct timeval startTime;
+
+static wControl_p triggerControl = NULL;
+static setTriggerCallback_p triggerFunc = NULL;
+
+/**
+ * Signal handler for alarm timer - executes the defined function when
+ * timer expires
+ *
+ * \param data IN callback function
+ * \returns alwys 0
+ */
+
+static gint doAlarm(
+ gpointer data)
+{
+ wAlarmCallBack_p func = (wAlarmCallBack_p)data;
+
+ func();
+
+ alarmTimer = 0;
+ return FALSE;
+}
+
+/**
+ * Alarm for <count> milliseconds.
+ *
+ * \param count IN time to wait
+ * \param func IN function called when timer expires
+ */
+
+void wAlarm(
+ long count,
+ wAlarmCallBack_p func) /* milliseconds */
+{
+ gtkPaused = TRUE;
+
+ if (alarmTimer) {
+ g_source_remove(alarmTimer);
+ }
+
+ alarmTimer = g_timeout_add(count, doAlarm, (void *)(GSourceFunc)func);
+}
+
+static void doTrigger(void)
+{
+ if (triggerControl && triggerFunc) {
+ triggerFunc(triggerControl);
+ triggerFunc = NULL;
+ triggerControl = NULL;
+ }
+}
+
+void wlibSetTrigger(
+ wControl_p b,
+ setTriggerCallback_p trigger)
+{
+ triggerControl = b;
+ triggerFunc = trigger;
+ wAlarm(500, doTrigger);
+}
+
+/**
+ * Pause for <count> milliseconds.
+ *
+ * \param count IN
+ */
+
+void wPause(
+ long count) /* milliseconds */
+{
+ struct timeval timeout;
+ sigset_t signal_mask;
+ sigset_t oldsignal_mask;
+ gdk_display_sync(gdk_display_get_default());
+ timeout.tv_sec = count/1000;
+ timeout.tv_usec = (count%1000)*1000;
+ sigemptyset(&signal_mask);
+ sigaddset(&signal_mask, SIGIO);
+ sigaddset(&signal_mask, SIGALRM);
+ sigprocmask(SIG_BLOCK, &signal_mask, &oldsignal_mask);
+
+ if (select(0, NULL, NULL, NULL, &timeout) == -1) {
+ perror("wPause:select");
+ }
+
+ sigprocmask(SIG_BLOCK, &oldsignal_mask, NULL);
+}
+
+/**
+ * Get time expired since start???
+ * \todo Check where start time is initialized!!!
+ *
+ * \returns time in seconds
+ */
+
+unsigned long wGetTimer(void)
+{
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+ return (tv.tv_sec-startTime.tv_sec+1) * 1000 + tv.tv_usec /1000;
+}
diff --git a/app/wlib/gtklib/tooltip.c b/app/wlib/gtklib/tooltip.c
new file mode 100644
index 0000000..15b46d2
--- /dev/null
+++ b/app/wlib/gtklib/tooltip.c
@@ -0,0 +1,255 @@
+/** \file tooltip.c
+ * Code for tooltip / balloon help functions
+ */
+
+/* XTrkCad - Model Railroad CAD
+ * Copyright (C) 2012 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+wBool_t listHelpStrings = FALSE;
+wBool_t listMissingHelpStrings = FALSE;
+
+static wBalloonHelp_t * balloonHelpStrings;
+static int enableBalloonHelp = TRUE;
+
+static GtkWidget * balloonF; /**< balloon help control for hotbar item */
+static GtkWidget * balloonPI;
+
+static const char * balloonMsg = NULL;
+static wControl_p balloonB;
+static wPos_t balloonDx, balloonDy;
+static wBool_t balloonVisible = FALSE;
+
+
+/**
+ * Hide the currently displayed Balloon Help.
+ */
+
+void
+wlibHelpHideBalloon()
+{
+ wControlSetBalloon( balloonB, 0, 0, NULL );
+}
+
+/**
+ * Initialize tooltip array
+ *
+ * \param bh IN pointer to list of tooltips
+ * \return
+ */
+
+void wSetBalloonHelp( wBalloonHelp_t * bh )
+{
+ balloonHelpStrings = bh;
+}
+
+/**
+ * Switch tooltips on and off
+ *
+ * \param enable IN desired state (TRUE or FALSE )
+ * \return
+ */
+
+void wEnableBalloonHelp( int enable )
+{
+ enableBalloonHelp = enable;
+}
+
+/**
+ * Set the help topic string for <b> to <help>.
+ *
+ * \param b IN control
+ * \param help IN tip
+ */
+
+void wControlSetHelp(
+ wControl_p b,
+ const char * help )
+{
+ wControlSetBalloonText( b, help );
+}
+
+/**
+ * Set the help topic string for <b> to <help>.
+ *
+ * \param b IN control
+ * \param help IN tip
+ */
+
+void wControlSetBalloonText(
+ wControl_p b,
+ const char * label )
+{
+ assert(b->widget != NULL);
+
+
+ gtk_widget_set_tooltip_text( b->widget, label );
+}
+
+/**
+ * Display some help text for a widget. This is a way to create
+ * some custom tooltips for error messages and the hotbar part desc
+ * \todo Replace with standard tooltip handling and custom window
+ *
+ * \param b IN widget
+ * \param dx IN dx offset in x-direction
+ * \param dy IN dy offset in y direction
+ * \param msg IN text to display, if NULL tootip is hidden
+ * \return
+ */
+
+void wControlSetBalloon( wControl_p b, wPos_t dx, wPos_t dy, const char * msg )
+{
+ PangoLayout * layout;
+
+ wPos_t x, y;
+ wPos_t w, h;
+ wPos_t xx, yy;
+ const char * msgConverted;
+ GtkAllocation size;
+
+ /* return if there is nothing to do */
+ if (balloonVisible && balloonB == b &&
+ balloonDx == dx && balloonDy == dy && msg != NULL && balloonMsg != NULL)
+ if (strcmp(msg,balloonMsg)==0)
+ return;
+
+ /* hide the tooltip */
+ if ( msg == NULL ) {
+ if ( balloonF != NULL ) {
+ gtk_widget_hide( balloonF );
+ balloonVisible = FALSE;
+ }
+ balloonMsg = "";
+ return;
+ }
+ msgConverted = wlibConvertInput(msg);
+
+ if ( balloonF == NULL ) {
+ GtkWidget *alignment;
+
+ balloonF = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+ gtk_window_set_type_hint( GTK_WINDOW( balloonF), GDK_WINDOW_TYPE_HINT_TOOLTIP );
+ gtk_window_set_decorated (GTK_WINDOW (balloonF), FALSE );
+ gtk_window_set_resizable( GTK_WINDOW (balloonF), FALSE );
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding( GTK_ALIGNMENT(alignment), 6, 6, 6, 6 );
+
+ gtk_container_add (GTK_CONTAINER (balloonF), alignment);
+ gtk_widget_show (alignment);
+
+ balloonPI = gtk_label_new(msgConverted);
+ gtk_container_add( GTK_CONTAINER(alignment), balloonPI );
+ gtk_widget_show( balloonPI );
+ }
+ gtk_label_set_text( GTK_LABEL(balloonPI), msgConverted );
+
+ balloonDx = dx;
+ balloonDy = dy;
+ balloonB = b;
+ balloonMsg = msg;
+ gtk_widget_get_allocation(balloonPI, &size );
+ w = size.width;
+ h = size.height;
+
+ gdk_window_get_origin( gtk_widget_get_window( GTK_WIDGET(b->parent->gtkwin)), &x, &y );
+
+ x += b->realX + dx;
+ y += b->realY + b->h - dy;
+ xx = gdk_screen_width();
+ yy = gdk_screen_height();
+ if ( x < 0 ) {
+ x = 0;
+ } else if ( x+w > xx ) {
+ x = xx - w;
+ }
+ if ( y < 0 ) {
+ y = 0;
+ } else if ( y+h > yy ) {
+ y = yy - h ;
+ }
+ gtk_window_move( GTK_WINDOW( balloonF ), x, y );
+ gtk_widget_show( balloonF );
+
+ balloonVisible = TRUE;
+}
+
+/**
+* still referenced but not needed any more
+*/
+void wBalloonHelpUpdate( void )
+{
+}
+
+/**
+ * Add tooltip and reference into help system to a widget
+ *
+ * \param widget IN widget
+ * \param helpStr IN symbolic link into help system
+ */
+
+void wlibAddHelpString(
+ GtkWidget * widget,
+ const char * helpStr )
+{
+ char *string;
+ char *wAppName = wlibGetAppName();
+ wBalloonHelp_t * bhp;
+
+ if (helpStr==NULL || *helpStr==0)
+ return;
+ if ( balloonHelpStrings == NULL )
+ return;
+
+ // search for the helpStr, bhp points to the entry when found
+ for ( bhp = balloonHelpStrings; bhp->name && strcmp(bhp->name,helpStr) != 0; bhp++ )
+ ;
+
+ if (listMissingHelpStrings && !bhp->name) {
+ printf( "Missing Help String: %s\n", helpStr );
+ return;
+ }
+
+ string = malloc( strlen(wAppName) + 5 + strlen(helpStr) + 1 );
+ sprintf( string, "%sHelp/%s", wAppName, helpStr );
+
+ if(bhp->value)
+ gtk_widget_set_tooltip_text( widget, wlibConvertInput(_(bhp->value)) );
+
+ g_object_set_data( G_OBJECT( widget ), HELPDATAKEY, string );
+
+ if (listHelpStrings)
+ printf( "HELPSTR - %s\n", string );
+
+}
diff --git a/app/wlib/gtklib/treeview.c b/app/wlib/gtklib/treeview.c
new file mode 100644
index 0000000..e2f2259
--- /dev/null
+++ b/app/wlib/gtklib/treeview.c
@@ -0,0 +1,530 @@
+/** \file treeview.c
+ * Basic treeview functionality for dropbox and listbox
+ */
+
+/* XTrkCad - Model Railroad CAD
+ *
+ * Copyright 2016 Martin Fischer <m_fischer@users.sf.net>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gtkint.h"
+//#include "i18n.h"
+
+#define ROW_HEIGHT (15)
+
+/**
+ * Get the count of columns in list
+ *
+ * \param b IN widget
+ * \returns count row
+ */
+
+int
+wTreeViewGetCount(wList_p b)
+{
+ return b->count;
+}
+
+/**
+ * Clear the list
+ *
+ * \param b IN widget
+ */
+
+void
+wTreeViewClear(wList_p b)
+{
+ assert(b != NULL);
+
+ wlibListStoreClear(b->listStore);
+}
+
+/**
+ * Get the user data for a list element
+ *
+ * \param b IN widget
+ * \param inx IN row
+ * \returns the user data for the specified row
+ */
+
+void *
+wTreeViewGetItemContext(wList_p b, int row)
+{
+ wListItem_p id_p;
+
+ id_p = wlibListItemGet(b->listStore, row, NULL);
+
+ if (id_p) {
+ return id_p->itemData;
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * Returns the current selected list entry.
+ * If <val> if '-1' then no entry is selected.
+ *
+ * \param b IN widget
+ * \returns row of selected entry or -1 if none is selected
+ */
+
+wIndex_t wListGetIndex(
+ wList_p b)
+{
+ assert(b!=NULL);
+
+ return b->last;
+}
+
+/**
+ * Set an entry in the list to selected.
+ *
+ * \param b IN widget
+ * \param index IN entry if -1 the current selection is cleared
+ *
+ */
+
+void
+wlibTreeViewSetSelected(wList_p b, int index)
+{
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+
+ wListItem_p id_p;
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(b->treeView));
+
+ if (gtk_tree_selection_count_selected_rows(sel)) {
+ int inx;
+
+ gtk_tree_selection_unselect_all(sel);
+
+ // and synchronize the internal data structures
+ wTreeViewGetCount(b);
+
+ for (inx=0; inx<b->count; inx++) {
+ id_p = wlibListItemGet(b->listStore, inx, NULL);
+ id_p->selected = FALSE;
+ }
+ }
+
+ if (index != -1) {
+ gint childs;
+
+ childs = gtk_tree_model_iter_n_children (GTK_TREE_MODEL(b->listStore),
+ NULL );
+
+ if(index < childs) {
+ gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(b->listStore),
+ &iter,
+ NULL,
+ index);
+ gtk_tree_selection_select_iter(sel,
+ &iter);
+
+ id_p = wlibListItemGet(b->listStore, index, NULL);
+
+ if (id_p) {
+ id_p->selected = TRUE;
+ }
+ }
+ }
+}
+
+/**
+ * Create a new tree view for a list store. Titles are enabled optionally.
+ *
+ * \param ls IN list store
+ * \param showTitles IN add column titles
+ * \param multiSelection IN enable selecting multiple rows
+ * \returns
+ */
+
+GtkWidget *
+wlibNewTreeView(GtkListStore *ls, int showTitles, int multiSelection)
+{
+ GtkWidget *treeView;
+ GtkTreeSelection *sel;
+ assert(ls != NULL);
+
+ /* create and configure the tree view */
+ treeView = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls));
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeView), showTitles);
+
+ /* set up selection handling */
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeView));
+ gtk_tree_selection_set_mode(sel,
+ (multiSelection)?GTK_SELECTION_MULTIPLE:GTK_SELECTION_BROWSE);
+
+ return (treeView);
+}
+
+
+static int changeListColumnWidth(
+ GtkTreeViewColumn * column,
+ void * width)
+{
+ //wList_p bl = (wList_p)data;
+
+ //if (bl->recursion)
+ //return 0;
+ //if ( col >= 0 && col < bl->colCnt )
+ //bl->colWidths[col] = width;
+ return 0;
+}
+
+/**
+ * Create and initialize a column in treeview. Initially all columns are
+ * invisible. Visibility is set when values are added to the specific
+ * column
+ *
+ * \param tv IN treeview
+ * \param renderer IN renderer to use
+ * \param attribute IN attribute for column
+ * \param value IN value to set
+ */
+
+static void
+wlibAddColumn(GtkWidget *tv, int visibility, GtkCellRenderer *renderer,
+ char *attribute, int value)
+{
+ GtkTreeViewColumn *column;
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_pack_start(column,
+ renderer,
+ TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer, attribute, value);
+ gtk_tree_view_column_set_visible(column, visibility);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column);
+
+// g_signal_connect( column, "notify::width", G_CALLBACK(changeListColumnWidth), tv );
+}
+
+/**
+ * Add a number of columns to the text view. This includes the bitmap
+ * columns and a given number of text columns.
+ *
+ * \param tv IN tree view
+ * \param count IN number of text columns
+ * \returns number of columns
+ */
+
+int
+wlibTreeViewAddColumns(GtkWidget *tv, int count)
+{
+ GtkCellRenderer *renderer;
+ int i;
+
+ assert(tv != NULL);
+ renderer = gtk_cell_renderer_pixbuf_new();
+ /* first visible column is used for bitmaps */
+ wlibAddColumn(tv, FALSE, renderer, "pixbuf", LISTCOL_BITMAP);
+
+ renderer = gtk_cell_renderer_text_new();
+
+ /* add renderers to all columns */
+ for (i = 0; i < count; i++) {
+ wlibAddColumn(tv, TRUE, renderer, "text", i + LISTCOL_TEXT);
+ }
+
+ return i;
+}
+
+/**
+ * Add the titles to all columns in a tree view.
+ *
+ * \param tv IN treeview
+ * \param titles IN titles
+ * \returns number of titles set
+ */
+
+int
+wlibAddColumnTitles(GtkWidget *tv, const char **titles)
+{
+ int i = 0;
+
+ assert(tv != NULL);
+
+ if (titles) {
+ while (*titles) {
+ GtkTreeViewColumn *column;
+
+ column = gtk_tree_view_get_column(GTK_TREE_VIEW(tv), i + 1);
+
+ if (column) {
+ gtk_tree_view_column_set_title(column, titles[ i ]);
+ i++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ return i;
+}
+
+/**
+ * Add text to the text columns of the tree view and update the context
+ * information
+ *
+ * \param tv IN treeview
+ * \param cols IN number of cols to change
+ * \param label IN tab separated string of values
+ * \param userData IN additional context information
+ * \returns
+ */
+
+int
+wlibTreeViewAddData(GtkWidget *tv, int cols, char *label, GdkPixbuf *pixbuf,
+ wListItem_p userData)
+{
+ GtkListStore *listStore = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(
+ tv)));
+
+ wlibListStoreAddData(listStore, pixbuf, cols, userData);
+
+ if (pixbuf) {
+ GtkTreeViewColumn *column;
+
+ // first column in list store has pixbuf
+ column = gtk_tree_view_get_column(GTK_TREE_VIEW(tv), 0);
+ gtk_tree_view_column_set_visible(column,
+ TRUE);
+ }
+
+}
+
+/**
+ * Add a row to the tree view. As necessary the adjustment is update in
+ * order to make sure, that the list box is fully visible or has a
+ * scrollbar.
+ *
+ * \param b IN the list box
+ * \param label IN the text labels
+ * \param bm IN bitmap to show at start
+ * \param id_p IN user data
+ */
+
+void
+wlibTreeViewAddRow(wList_p b, char *label, wIcon_p bm, wListItem_p id_p)
+{
+ GtkAdjustment *adj;
+ GdkPixbuf *pixbuf = NULL;
+
+ if (bm) {
+ pixbuf = wlibMakePixbuf(bm);
+ }
+
+ wlibTreeViewAddData(b->treeView, b->colCnt, (char *)label, pixbuf, id_p);
+
+ adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(b->widget));
+
+ if (gtk_adjustment_get_upper(adj) < gtk_adjustment_get_step_increment(adj) *
+ (b->count+1)) {
+ gtk_adjustment_set_upper(adj,
+ gtk_adjustment_get_upper(adj) +
+ gtk_adjustment_get_step_increment(adj));
+ gtk_adjustment_changed(adj);
+ }
+
+ b->last = gtk_tree_model_iter_n_children(gtk_tree_view_get_model(GTK_TREE_VIEW(
+ b->treeView)),
+ NULL);
+
+}
+
+/**
+ * Function for handling a selection change. The internal data structure
+ * for the changed row is updated. If a handler function for the list
+ * is given, the data for the row are retrieved and passed to that
+ * function. This is used to update other fields in a dialog (see Price
+ * List for an example).
+ *
+ * \param selection IN current selection
+ * \param model IN
+ * \param path IN
+ * \param path_currently_selected IN
+ * \param data IN the list widget
+ */
+
+gboolean
+changeSelection(GtkTreeSelection *selection,
+ GtkTreeModel *model,
+ GtkTreePath *path,
+ gboolean path_currently_selected,
+ gpointer data)
+{
+ GtkTreeIter iter;
+ GValue value = { 0 };
+ wListItem_p id_p = NULL;
+ wList_p bl = (wList_p)data;
+ int row;
+ char *text;
+
+ text = gtk_tree_path_to_string(path);
+ row = atoi(text);
+ g_free(text);
+
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get_value(model, &iter, LISTCOL_DATA, &value);
+
+ id_p = g_value_get_pointer(&value);
+ id_p->selected = !path_currently_selected;
+
+ if (id_p->selected) {
+ bl->last = row;
+
+ if (bl->valueP) {
+ *bl->valueP = row;
+ }
+
+ if (bl->action) {
+ bl->action(row, id_p->label, 1, bl->data, id_p->itemData);
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * Create a multi column list box.
+ *
+ * \param parent IN parent window
+ * \param x IN X-position
+ * \param y IN Y-position
+ * \param helpStr IN Help string
+ * \param labelStr IN Label
+ * \param option IN Options
+ * \param number IN Number of displayed entries
+ * \param width IN Width of list
+ * \param colCnt IN Number of columns
+ * \param colWidths IN Width of columns
+ * \param colRightJust IN justification of columns
+ * \param colTitles IN array of titles for columns
+ * \param valueP IN Selected index
+ * \param action IN Callback
+ * \param data IN Context
+ * \returns created list box
+ */
+
+wList_p wListCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ long option,
+ long number,
+ wPos_t width,
+ int colCnt,
+ wPos_t * colWidths,
+ wBool_t * colRightJust,
+ const char ** colTitles,
+ long *valueP,
+ wListCallBack_p action,
+ void *data)
+{
+ GtkTreeSelection *sel;
+ wList_p bl;
+ static wPos_t zeroPos = 0;
+
+ assert(width != 0);
+
+ bl = (wList_p)wlibAlloc(parent, B_LIST, x, y, labelStr, sizeof *bl, data);
+ bl->option = option;
+ bl->number = number;
+ bl->count = 0;
+ bl->last = -1;
+ bl->valueP = valueP;
+ bl->action = action;
+ bl->listX = bl->realX;
+
+ if (colCnt <= 0) {
+ colCnt = 1;
+ colWidths = &zeroPos;
+ }
+
+ bl->colCnt = colCnt;
+ bl->colWidths = (wPos_t*)malloc(colCnt * sizeof *(wPos_t*)0);
+ memcpy(bl->colWidths, colWidths, colCnt * sizeof *(wPos_t*)0);
+
+ /* create the data structure for data */
+ bl->listStore = wlibNewListStore(colCnt);
+ /* create the widget for the list store */
+ bl->treeView = wlibNewTreeView(bl->listStore,
+ colTitles != NULL,
+ option & BL_MANY);
+
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(bl->treeView));
+
+ gtk_tree_selection_set_select_function(sel,
+ changeSelection,
+ bl,
+ NULL);
+
+ wlibTreeViewAddColumns(bl->treeView, colCnt);
+
+ wlibAddColumnTitles(bl->treeView, colTitles);
+
+ wlibComputePos((wControl_p)bl);
+
+ bl->widget = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(bl->widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(bl->widget),
+ bl->treeView);
+
+ gtk_widget_set_size_request(bl->widget, width, (number+1)*ROW_HEIGHT);
+
+/// g_signal_connect( GTK_OBJECT(bl->list), "resize_column", G_CALLBACK(changeListColumnWidth), bl );
+
+ gtk_widget_show_all(bl->widget);
+
+ gtk_fixed_put(GTK_FIXED(parent->widget), bl->widget, bl->realX, bl->realY);
+ wlibControlGetSize((wControl_p)bl);
+
+ if (labelStr) {
+ bl->labelW = wlibAddLabel((wControl_p)bl, labelStr);
+ }
+
+ wlibAddButton((wControl_p)bl);
+ wlibAddHelpString(bl->widget, helpStr);
+
+ return bl;
+}
diff --git a/app/wlib/gtklib/util.c b/app/wlib/gtklib/util.c
new file mode 100644
index 0000000..61b5b95
--- /dev/null
+++ b/app/wlib/gtklib/util.c
@@ -0,0 +1,672 @@
+/** \file util.c
+ * Some basic window functions
+ */
+
+/* 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 <stdlib.h>
+#include <signal.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gtkint.h"
+#include "i18n.h"
+
+wWin_p gtkMainW;
+
+long debugWindow = 0;
+
+char wConfigName[ 256 ];
+
+const char * wNames[] = {
+ "MAIN",
+ "POPUP",
+ "BUTT",
+ "CANCEL",
+ "POPUP",
+ "TEXT",
+ "INTEGER",
+ "FLOAT",
+ "LIST",
+ "DROPLIST",
+ "COMBOLIST",
+ "RADIO",
+ "TOGGLE",
+ "DRAW",
+ "MENU"
+ "MULTITEXT",
+ "MESSAGE",
+ "LINES",
+ "MENUITEM",
+ "BOX"
+};
+
+
+static wBool_t reverseIcon =
+#if defined(linux)
+ FALSE;
+#else
+ TRUE;
+#endif
+
+
+
+/*
+ *****************************************************************************
+ *
+ * Internal Utility functions
+ *
+ *****************************************************************************
+ */
+
+/**
+ * Create a pixbuf from a two colored bitmap in XBM format.
+ *
+ * \param ip the XBM data
+ * \returns the pixbuf
+ */
+
+GdkPixbuf* wlibPixbufFromXBM(
+ wIcon_p ip )
+{
+ GdkPixbuf * pixbuf;
+
+ char line0[40];
+ char line2[40];
+
+ char ** pixmapData;
+ int row,col,wb;
+ long rgb;
+ const char * bits;
+
+ wb = (ip->w+7)/8;
+ pixmapData = (char**)malloc((3+ip->h) * sizeof *pixmapData);
+ pixmapData[0] = line0;
+ rgb = wDrawGetRGB(ip->color);
+ sprintf(line0, " %d %d 2 1", ip->w, ip->h);
+ sprintf(line2, "# c #%2.2lx%2.2lx%2.2lx", (rgb>>16)&0xFF, (rgb>>8)&0xFF,
+ rgb&0xFF);
+ pixmapData[1] = ". c None s None";
+ pixmapData[2] = line2;
+ bits = ip->bits;
+
+ for (row = 0; row<ip->h; row++) {
+ pixmapData[row+3] = (char*)malloc((ip->w+1) * sizeof **pixmapData);
+
+ for (col = 0; col<ip->w; col++) {
+ if (bits[ row*wb+(col>>3) ] & (1<<(col&07))) {
+ pixmapData[row+3][col] = '#';
+ } else {
+ pixmapData[row+3][col] = '.';
+ }
+ }
+ pixmapData[row+3][ip->w] = 0;
+ }
+
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)pixmapData);
+
+ for (row = 0; row<ip->h; row++) {
+ free(pixmapData[row+3]);
+ }
+ return pixbuf;
+}
+
+/**
+ * Add a label to an existing widget
+ *
+ * \param b IN widget
+ * \param labelStr IN label to add
+ * \returns size of label
+ */
+
+int wlibAddLabel(wControl_p b, const char * labelStr)
+{
+ GtkRequisition requisition;
+
+ if (labelStr == NULL) {
+ return 0;
+ }
+
+ b->label = gtk_label_new(wlibConvertInput(labelStr));
+ gtk_widget_size_request(b->label, &requisition);
+ gtk_container_add(GTK_CONTAINER(b->parent->widget), b->label);
+ gtk_fixed_move(GTK_FIXED(b->parent->widget), b->label,
+ b->realX-requisition.width-8, b->realY+LABEL_OFFSET);
+
+ gtk_widget_show(b->label);
+ return requisition.width+8;
+}
+
+/**
+ * Allocate and initialize the data structure for a new widget
+ *
+ * \param parent IN parent window
+ * \param type IN type of new widget
+ * \param origX IN x position
+ * \param origY IN y position
+ * \param labelStr IN text label
+ * \param size IN size
+ * \param data IN user data to keep with widget
+ * \returns
+ */
+
+void * wlibAlloc(
+ wWin_p parent,
+ wType_e type,
+ wPos_t origX,
+ wPos_t origY,
+ const char * labelStr,
+ int size,
+ void * data)
+{
+ wControl_p w = (wControl_p)malloc(size);
+ char * cp;
+ memset(w, 0, size);
+
+ if (w == NULL) {
+ abort();
+ }
+
+ w->type = type;
+ w->parent = parent;
+ w->origX = origX;
+ w->origY = origY;
+
+ if (labelStr) {
+ cp = (char*)malloc(strlen(labelStr)+1);
+ w->labelStr = cp;
+
+ for (; *labelStr; labelStr++)
+ if (*labelStr != '&') {
+ *cp++ = *labelStr;
+ }
+
+ *cp = 0;
+ }
+
+ w->doneProc = NULL;
+ w->data = data;
+ return w;
+}
+
+/**
+ * Calculate the position for a widget
+ *
+ * \param b IN widget
+ */
+
+void wlibComputePos(
+ wControl_p b)
+{
+ wWin_p w = b->parent;
+
+ if (b->origX >= 0) {
+ b->realX = b->origX;
+ } else {
+ b->realX = w->lastX + (-b->origX) - 1;
+ }
+
+ if (b->origY >= 0) {
+ b->realY = b->origY + BORDERSIZE + ((w->option&F_MENUBAR)?MENUH:0);
+ } else {
+ b->realY = w->lastY + (-b->origY) - 1;
+ }
+}
+
+/**
+ * Initialize the internal structure with the size of the widget
+ *
+ * \param b IN widget
+ */
+
+void wlibControlGetSize(
+ wControl_p b)
+{
+ GtkRequisition requisition;
+ gtk_widget_size_request(b->widget, &requisition);
+ b->w = requisition.width;
+ b->h = requisition.height;
+}
+
+/**
+ * ???
+ * \param b IN widget
+ */
+
+void wlibAddButton(
+ wControl_p b)
+{
+ wWin_p win = b->parent;
+ wBool_t resize = FALSE;
+
+ if (win->first == NULL) {
+ win->first = b;
+ } else {
+ win->last->next = b;
+ }
+
+ win->last = b;
+ b->next = NULL;
+ b->parent = win;
+ win->lastX = b->realX + b->w;
+ win->lastY = b->realY + b->h;
+
+ if (win->option&F_AUTOSIZE) {
+ if (win->lastX > win->realX) {
+ win->realX = win->lastX;
+
+ if (win->w != (win->realX + win->origX)) {
+ resize = TRUE;
+ win->w = (win->realX + win->origX);
+ }
+ }
+
+ if (win->lastY > win->realY) {
+ win->realY = win->lastY;
+
+ if (win->h != (win->realY + win->origY)) {
+ resize = TRUE;
+ win->h = (win->realY + win->origY);
+ }
+ }
+
+ if (win->shown) {
+ if (resize) {
+ gtk_widget_set_size_request(win->gtkwin, win->w, win->h);
+ gtk_widget_set_size_request(win->widget, win->w, win->h);
+ }
+ }
+ }
+}
+
+/**
+ * Find the widget at a position
+ * \param win IN searched widget's parent window
+ * \param x IN x position inside parent
+ * \param y IN y position inside parent
+ * \returns the widget, NULL if none at the position
+ */
+
+wControl_p wlibGetControlFromPos(
+ wWin_p win,
+ wPos_t x,
+ wPos_t y)
+{
+ wControl_p b;
+ wPos_t xx, yy;
+
+ for (b=win->first; b != NULL; b = b->next) {
+ if (b->widget && gtk_widget_get_visible(b->widget)) {
+ xx = b->realX;
+ yy = b->realY;
+
+ if (xx <= x && x < xx+b->w &&
+ yy <= y && y < yy+b->h) {
+ return b;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ *****************************************************************************
+ *
+ * Exported Utility Functions
+ *
+ *****************************************************************************
+ */
+
+/**
+ * Beep!
+ * \return
+ */
+void wBeep(void)
+{
+ gdk_display_beep(gdk_display_get_default());
+}
+
+
+/**
+ * Flushs all commands to the Window.
+ */
+
+void wFlush(
+ void)
+{
+ while (gtk_events_pending()) {
+ gtk_main_iteration();
+ }
+
+ gdk_display_sync(gdk_display_get_default());
+}
+
+/**
+ * Not implemented
+ * \returns
+ */
+
+void wWinTop(wWin_p win)
+{
+}
+
+/**
+ * Not implemented
+ *
+ * \param cursor IN
+ */
+
+void wSetCursor(wCursor_t cursor)
+{
+}
+
+/**
+ * Not implemented
+ * \returns
+ */
+
+const char * wMemStats(void)
+{
+ return "No stats available";
+}
+
+/**
+ * Get the size of the screen
+ *
+ * \param w IN pointer to width
+ * \param h IN pointer to height
+ */
+
+void wGetDisplaySize(wPos_t * w, wPos_t * h)
+{
+
+ *w = gdk_screen_width();
+ *h = gdk_screen_height();
+}
+
+static dynArr_t conversionBuffer_da;
+
+/**
+ * Convert a string to UTF-8
+ *
+ * \param inString IN string to convert
+ * \returns pointer to converted string, valid until next call to conversion function
+ */
+
+char * wlibConvertInput(const char * inString)
+{
+ const char * cp;
+ char * cq;
+ int extCharCnt, inCharCnt;
+
+ /* Already UTF-8 encoded? */
+ if (g_utf8_validate(inString, -1, NULL))
+ /* Yes, do not double-convert */
+ {
+ return (char*)inString;
+ }
+
+ for (cp=inString, extCharCnt=0; *cp; cp++) {
+ if (((*cp)&0x80) != '\0') {
+ extCharCnt++;
+ }
+ }
+
+ inCharCnt = cp-inString;
+
+ if (extCharCnt == '\0') {
+ return (char*)inString;
+ }
+
+ DYNARR_SET(char, conversionBuffer_da, inCharCnt+extCharCnt+1);
+
+ for (cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++) {
+ if (((*cp)&0x80) != 0) {
+ *cq++ = 0xC0+(((*cp)&0xC0)>>6);
+ *cq++ = 0x80+((*cp)&0x3F);
+ } else {
+ *cq++ = *cp;
+ }
+ }
+
+ *cq = 0;
+ return (char*)conversionBuffer_da.ptr;
+}
+
+/**
+ * Convert a string from UTF-8 to system codepage
+ *
+ * \param inString IN string to convert
+ * \returns pointer to converted string, valid until next call to conversion function
+ */
+
+char * wlibConvertOutput(const char * inString)
+{
+ const char * cp;
+ char * cq;
+ int extCharCnt, inCharCnt;
+
+ for (cp=inString, extCharCnt=0; *cp; cp++) {
+ if (((*cp)&0xC0) == 0x80) {
+ extCharCnt++;
+ }
+ }
+
+ inCharCnt = cp-inString;
+
+ if (extCharCnt == '\0') {
+ return (char*)inString;
+ }
+
+ DYNARR_SET(char, conversionBuffer_da, inCharCnt+1);
+
+ for (cp=inString, cq=(char*)conversionBuffer_da.ptr; *cp; cp++) {
+ if (((*cp)&0x80) != 0) {
+ *cq++ = 0xC0+(((*cp)&0xC0)>>6);
+ *cq++ = 0x80+((*cp)&0x3F);
+ } else {
+ *cq++ = *cp;
+ }
+ }
+
+ *cq = '\0';
+ return (char*)conversionBuffer_da.ptr;
+}
+
+/*-----------------------------------------------------------------*/
+
+
+static dynArr_t accelData_da;
+#define accelData(N) DYNARR_N( accelData_t, accelData_da, N )
+
+static guint accelKeyMap[] = {
+ 0, /* wAccelKey_None, */
+ GDK_KEY_Delete, /* wAccelKey_Del, */
+ GDK_KEY_Insert, /* wAccelKey_Ins, */
+ GDK_KEY_Home, /* wAccelKey_Home, */
+ GDK_KEY_End, /* wAccelKey_End, */
+ GDK_KEY_Page_Up, /* wAccelKey_Pgup, */
+ GDK_KEY_Page_Down, /* wAccelKey_Pgdn, */
+ GDK_KEY_Up, /* wAccelKey_Up, */
+ GDK_KEY_Down, /* wAccelKey_Down, */
+ GDK_KEY_Right, /* wAccelKey_Right, */
+ GDK_KEY_Left, /* wAccelKey_Left, */
+ GDK_KEY_BackSpace, /* wAccelKey_Back, */
+ GDK_KEY_F1, /* wAccelKey_F1, */
+ GDK_KEY_F2, /* wAccelKey_F2, */
+ GDK_KEY_F3, /* wAccelKey_F3, */
+ GDK_KEY_F4, /* wAccelKey_F4, */
+ GDK_KEY_F5, /* wAccelKey_F5, */
+ GDK_KEY_F6, /* wAccelKey_F6, */
+ GDK_KEY_F7, /* wAccelKey_F7, */
+ GDK_KEY_F8, /* wAccelKey_F8, */
+ GDK_KEY_F9, /* wAccelKey_F9, */
+ GDK_KEY_F10, /* wAccelKey_F10, */
+ GDK_KEY_F11, /* wAccelKey_F11, */
+ GDK_KEY_F12 /* wAccelKey_F12, */
+};
+
+/**
+ * Create an accelerator key
+ *
+ * \param key IN primary key stroke
+ * \param modifier IN modifier (shift, ctrl, etc.)
+ * \param action IN function to call
+ * \param data IN data to pass to function
+ */
+
+void wAttachAccelKey(
+ wAccelKey_e key,
+ int modifier,
+ wAccelKeyCallBack_p action,
+ void * data)
+{
+ accelData_t * ad;
+
+ if (key < 1 || key > wAccelKey_F12) {
+ fprintf(stderr, "wAttachAccelKey(%d) out of range\n", (int)key);
+ return;
+ }
+
+ DYNARR_APPEND(accelData_t, accelData_da, 10);
+ ad = &accelData(accelData_da.cnt-1);
+ ad->key = key;
+ ad->modifier = modifier;
+ ad->action = action;
+ ad->data = data;
+}
+
+/**
+ * Check for accelerator definition a pressed key
+ *
+ * \param event IN key press event
+ * \returns pointer to accel key structure, NULL if not existing
+ */
+
+struct accelData_t * wlibFindAccelKey(
+ GdkEventKey * event)
+{
+ accelData_t * ad;
+ int modifier = 0;
+
+ if ((event->state & GDK_SHIFT_MASK)) {
+ modifier |= WKEY_SHIFT;
+ }
+
+ if ((event->state & GDK_CONTROL_MASK)) {
+ modifier |= WKEY_CTRL;
+ }
+
+ if ((event->state & GDK_MOD1_MASK)) {
+ modifier |= WKEY_ALT;
+ }
+
+ for (ad=&accelData(0); ad<&accelData(accelData_da.cnt); ad++)
+ if (event->keyval == accelKeyMap[ad->key] &&
+ modifier == ad->modifier) {
+ return ad;
+ }
+
+ return NULL;
+}
+
+/**
+ * Perform action when an accelerator key was pressed
+ *
+ * \param event IN key press event
+ * \returns TRUE if valid accelerator, FALSE if not
+ */
+
+wBool_t wlibHandleAccelKey(
+ GdkEventKey *event)
+{
+ accelData_t * ad = wlibFindAccelKey(event);
+
+ if (ad) {
+ ad->action(ad->key, ad->data);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Add control to circular list of synonymous controls. Synonymous controls are kept in sync by
+ * calling wControlLinkedActive for one member of the list
+ * \todo This is similar to the concept of action in gtk/glib \
+ * Maybe this would be easier to use
+ *
+ * \param b1 IN first control
+ * \param b2 IN second control
+ * \return none
+ */
+
+void wControlLinkedSet(wControl_p b1, wControl_p b2)
+{
+
+ b2->synonym = b1->synonym;
+
+ if (b2->synonym == NULL) {
+ b2->synonym = b1;
+ }
+
+ b1->synonym = b2;
+}
+
+/**
+ * Activate/deactivate a group of synonymous controls.
+ *
+ * \param b IN control
+ * \param active IN state
+ * \return none
+ */
+
+void wControlLinkedActive(wControl_p b, int active)
+{
+ wControl_p savePtr = b;
+
+ if (savePtr->type == B_MENUITEM) {
+ wMenuPushEnable((wMenuPush_p)savePtr, active);
+ } else {
+ wControlActive(savePtr, active);
+ }
+
+ savePtr = savePtr->synonym;
+
+ while (savePtr && savePtr != b) {
+
+ if (savePtr->type == B_MENUITEM) {
+ wMenuPushEnable((wMenuPush_p)savePtr, active);
+ } else {
+ wControlActive(savePtr, active);
+ }
+
+ savePtr = savePtr->synonym;
+ }
+}
diff --git a/app/wlib/gtklib/window.c b/app/wlib/gtklib/window.c
new file mode 100644
index 0000000..489f35e
--- /dev/null
+++ b/app/wlib/gtklib/window.c
@@ -0,0 +1,936 @@
+/** \file window.c
+ * Basic window handling stuff.
+ */
+
+/* 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 <stdlib.h>
+#include <string.h>
+
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gtkint.h"
+
+wWin_p gtkMainW;
+
+#define MIN_WIN_WIDTH (50)
+#define MIN_WIN_HEIGHT (50)
+
+#define SECTIONWINDOWSIZE "gtklib window size"
+#define SECTIONWINDOWPOS "gtklib window pos"
+
+extern wBool_t listHelpStrings;
+
+static wControl_p firstWin = NULL, lastWin;
+static int keyState;
+static wBool_t gtkBlockEnabled = TRUE;
+
+/*
+ *****************************************************************************
+ *
+ * Window Utilities
+ *
+ *****************************************************************************
+ */
+
+/**
+ * Get the window size from the resource (.rc) file. The size is saved under the key
+ * SECTIONWINDOWSIZE.window name
+ *
+ * \param win IN window
+ * \param nameStr IN window name
+ */
+
+static void getWinSize(wWin_p win, const char * nameStr)
+{
+ int w, h;
+ const char *cp;
+ char *cp1, *cp2;
+
+ if ((win->option&F_RESIZE) &&
+ (win->option&F_RECALLPOS) &&
+ (cp = wPrefGetString(SECTIONWINDOWSIZE, nameStr)) &&
+ (w = strtod(cp, &cp1), cp != cp1) &&
+ (h = strtod(cp1, &cp2), cp1 != cp2)) {
+ if (w < 10) {
+ w = 10;
+ }
+
+ if (h < 10) {
+ h = 10;
+ }
+
+ win->w = win->origX = w;
+ win->h = win->origY = h;
+ win->option &= ~F_AUTOSIZE;
+ }
+}
+
+/**
+ * Save the window size to the resource (.rc) file. The size is saved under the key
+ * SECTIONWINDOWSIZE.window name
+ *
+ * \param win IN window
+ */
+
+static void saveSize(wWin_p win)
+{
+
+ if ((win->option&F_RESIZE) &&
+ (win->option&F_RECALLPOS) &&
+ gtk_widget_get_visible(GTK_WIDGET(win->gtkwin))) {
+ char pos_s[20];
+
+ sprintf(pos_s, "%d %d", win->w,
+ win->h-(BORDERSIZE + ((win->option&F_MENUBAR)?MENUH:0)));
+ wPrefSetString(SECTIONWINDOWSIZE, win->nameStr, pos_s);
+ }
+}
+
+/**
+ * Get the window position from the resource (.rc) file. The position is saved under the key
+ * SECTIONWINDOWPOS.window name
+ *
+ * \param win IN window
+ */
+
+static void getPos(wWin_p win)
+{
+ char *cp1, *cp2;
+ wPos_t gtkDisplayWidth = gdk_screen_width();
+ wPos_t gtkDisplayHeight = gdk_screen_height();
+
+ if ((win->option&F_RECALLPOS) && (!win->shown)) {
+ const char *cp;
+
+ if ((cp = wPrefGetString(SECTIONWINDOWPOS, win->nameStr))) {
+ int x, y;
+
+ x = strtod(cp, &cp1);
+
+ if (cp == cp1) {
+ return;
+ }
+
+ y = strtod(cp1, &cp2);
+
+ if (cp2 == cp1) {
+ return;
+ }
+
+ if (y > gtkDisplayHeight-win->h) {
+ y = gtkDisplayHeight-win->h;
+ }
+
+ if (x > gtkDisplayWidth-win->w) {
+ x = gtkDisplayWidth-win->w;
+ }
+
+ if (x <= 0) {
+ x = 1;
+ }
+
+ if (y <= 0) {
+ y = 1;
+ }
+
+ gtk_window_move(GTK_WINDOW(win->gtkwin), x, y);
+ gtk_window_resize(GTK_WINDOW(win->gtkwin), win->w, win->h);
+ }
+ }
+}
+
+/**
+ * Save the window position to the resource (.rc) file. The position is saved under the key
+ * SECTIONWINDOWPOS.window name
+ *
+ * \param win IN window
+ */
+
+static void savePos(wWin_p win)
+{
+ int x, y;
+
+ if ((win->option&F_RECALLPOS)) {
+ char pos_s[20];
+
+ gdk_window_get_position(gtk_widget_get_window(GTK_WIDGET(win->gtkwin)), &x, &y);
+ x -= 5;
+ y -= 25;
+ sprintf(pos_s, "%d %d", x, y);
+ wPrefSetString(SECTIONWINDOWPOS, win->nameStr, pos_s);
+ }
+}
+
+/**
+ * Returns the dimensions of <win>.
+ *
+ * \param win IN window handle
+ * \param width OUT width of window
+ * \param height OUT height of window minus menu bar size
+ */
+
+void wWinGetSize(
+ wWin_p win, /* Window */
+ wPos_t * width, /* Returned window width */
+ wPos_t * height) /* Returned window height */
+{
+ GtkRequisition requisition;
+ wPos_t w, h;
+ gtk_widget_size_request(win->gtkwin, &requisition);
+ w = win->w;
+ h = win->h;
+
+ if (win->option&F_AUTOSIZE) {
+ if (win->realX > w) {
+ w = win->realX;
+ }
+
+ if (win->realY > h) {
+ h = win->realY;
+ }
+ }
+
+ *width = w;
+ *height = h - BORDERSIZE - ((win->option&F_MENUBAR)?MENUH:0);
+}
+
+/**
+ * Sets the dimensions of window
+ *
+ * \param win IN window
+ * \param width IN new width
+ * \param height IN new height
+ */
+
+void wWinSetSize(
+ wWin_p win, /* Window */
+ wPos_t width, /* Window width */
+ wPos_t height) /* Window height */
+{
+ win->busy = TRUE;
+ win->w = width;
+ win->h = height + BORDERSIZE + ((win->option&F_MENUBAR)?MENUH:0);
+ gtk_widget_set_size_request(win->gtkwin, win->w, win->h);
+ gtk_widget_set_size_request(win->widget, win->w, win->h);
+ win->busy = FALSE;
+}
+
+/**
+ * Shows or hides window <win>. If <win> is created with 'F_BLOCK' option then the applications other
+ * windows are disabled and 'wWinShow' doesnot return until the window <win> is closed by calling
+ * 'wWinShow(<win>,FALSE)'.
+ *
+ * \param win IN window
+ * \param show IN visibility state
+ */
+
+void wWinShow(
+ wWin_p win, /* Window */
+ wBool_t show) /* Command */
+{
+ GtkRequisition requisition;
+
+ if (debugWindow >= 2) {
+ printf("Set Show %s\n", win->labelStr?win->labelStr:"No label");
+ }
+
+ if (win->widget == 0) {
+ abort();
+ }
+
+ if (show) {
+ keyState = 0;
+ getPos(win);
+
+ if (win->option & F_AUTOSIZE) {
+ gtk_widget_size_request(win->gtkwin, &requisition);
+
+ if (requisition.width != win->w || requisition.height != win->h) {
+ gtk_widget_set_size_request(win->gtkwin, win->w, win->h);
+ gtk_widget_set_size_request(win->widget, win->w, win->h);
+
+ if (win->option&F_MENUBAR) {
+ gtk_widget_set_size_request(win->menubar, win->w, MENUH);
+ }
+ }
+ }
+
+ if (!win->shown) {
+ gtk_widget_show(win->gtkwin);
+ gtk_widget_show(win->widget);
+ }
+
+ gdk_window_raise(gtk_widget_get_window(win->gtkwin));
+
+ if (win->shown && win->modalLevel > 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), TRUE);
+ }
+
+ win->shown = show;
+ win->modalLevel = 0;
+
+ if ((!gtkBlockEnabled) || (win->option & F_BLOCK) == 0) {
+ wFlush();
+ } else {
+ wlibDoModal(win, TRUE);
+ }
+ } else {
+ wFlush();
+ saveSize(win);
+ savePos(win);
+ win->shown = show;
+
+ if (gtkBlockEnabled && (win->option & F_BLOCK) != 0) {
+ wlibDoModal(win, FALSE);
+ }
+
+ gtk_widget_hide(win->gtkwin);
+ gtk_widget_hide(win->widget);
+ }
+}
+
+/**
+ * Block windows against user interactions. Done during demo mode etc.
+ *
+ * \param enabled IN blocked if TRUE
+ */
+
+void wWinBlockEnable(
+ wBool_t enabled)
+{
+ gtkBlockEnabled = enabled;
+}
+
+/**
+ * Returns whether the window is visible.
+ *
+ * \param win IN window
+ * \return TRUE if visible, FALSE otherwise
+ */
+
+wBool_t wWinIsVisible(
+ wWin_p win)
+{
+ return win->shown;
+}
+
+/**
+ * Sets the title of <win> to <title>.
+ *
+ * \param varname1 IN window
+ * \param varname2 IN new title
+ */
+
+void wWinSetTitle(
+ wWin_p win, /* Window */
+ const char * title) /* New title */
+{
+ gtk_window_set_title(GTK_WINDOW(win->gtkwin), title);
+}
+
+/**
+ * Sets the window <win> to busy or not busy. Sets the cursor accordingly
+ *
+ * \param varname1 IN window
+ * \param varname2 IN TRUE if busy, FALSE otherwise
+ */
+
+void wWinSetBusy(
+ wWin_p win, /* Window */
+ wBool_t busy) /* Command */
+{
+ GdkCursor * cursor;
+
+ if (win->gtkwin == 0) {
+ abort();
+ }
+
+ if (busy) {
+ cursor = gdk_cursor_new(GDK_WATCH);
+ } else {
+ cursor = NULL;
+ }
+
+ gdk_window_set_cursor(gtk_widget_get_window(win->gtkwin), cursor);
+
+ if (cursor) {
+ gdk_cursor_unref(cursor);
+ }
+
+ gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), busy==0);
+}
+
+/**
+ * Set the modality of window. All visible windows are disabled when
+ * the window is modal. These windows are enabled again, when window
+ * is not modal. Disabling can be performed several times and enabling
+ * has to be repeated as well to re-enable a window.
+ * \todo Give this recursive enabling/disabling some thought and remove
+ *
+ * \param win0 IN window
+ * \param modal IN TRUE if window is application modal, FALSE otherwise
+ * \return
+ */
+
+void wlibDoModal(
+ wWin_p win0,
+ wBool_t modal)
+{
+ wWin_p win;
+
+ for (win=(wWin_p)firstWin; win; win=(wWin_p)win->next) {
+ if (win->shown && win != win0) {
+ if (modal) {
+ if (win->modalLevel == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), FALSE);
+ }
+
+ win->modalLevel++;
+ } else {
+ if (win->modalLevel > 0) {
+ win->modalLevel--;
+
+ if (win->modalLevel == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(win->gtkwin), TRUE);
+ }
+ }
+ }
+
+ if (win->modalLevel < 0) {
+ fprintf(stderr, "DoModal: %s modalLevel < 0",
+ win->nameStr?win->nameStr:"<NULL>");
+ abort();
+ }
+ }
+ }
+
+ if (modal) {
+ gtk_main();
+ } else {
+ gtk_main_quit();
+ }
+}
+
+/**
+ * Returns the Title of <win>.
+ *
+ * \param win IN window
+ * \return pointer to window title
+ */
+
+const char * wWinGetTitle(
+ wWin_p win) /* Window */
+{
+ return win->labelStr;
+}
+
+
+void wWinClear(
+ wWin_p win,
+ wPos_t x,
+ wPos_t y,
+ wPos_t width,
+ wPos_t height)
+{
+}
+
+
+void wWinDoCancel(
+ wWin_p win)
+{
+ wControl_p b;
+
+ for (b=win->first; b; b=b->next) {
+ if ((b->type == B_BUTTON) && (b->option & BB_CANCEL)) {
+ wlibButtonDoAction((wButton_p)b);
+ }
+ }
+}
+
+/*
+ ******************************************************************************
+ *
+ * Call Backs
+ *
+ ******************************************************************************
+ */
+
+static gint window_delete_event(
+ GtkWidget *widget,
+ GdkEvent *event,
+ wWin_p win)
+{
+ wControl_p b;
+ /* if you return FALSE in the "delete_event" signal handler,
+ * GTK will emit the "destroy" signal. Returning TRUE means
+ * you don't want the window to be destroyed.
+ * This is useful for popping up 'are you sure you want to quit ?'
+ * type dialogs. */
+
+ /* Change TRUE to FALSE and the main window will be destroyed with
+ * a "delete_event". */
+
+ for (b = win->first; b; b=b->next)
+ if (b->doneProc) {
+ b->doneProc(b);
+ }
+
+ if (win->winProc) {
+ win->winProc(win, wClose_e, win->data);
+
+ if (win != gtkMainW) {
+ wWinShow(win, FALSE);
+ }
+ }
+
+ return (TRUE);
+}
+
+static int window_redraw(
+ wWin_p win,
+ wBool_t doWinProc)
+{
+ wControl_p b;
+
+ if (win==NULL) {
+ return FALSE;
+ }
+
+ for (b=win->first; b != NULL; b = b->next) {
+ if (b->repaintProc) {
+ b->repaintProc(b);
+ }
+ }
+
+ return FALSE;
+}
+
+static int fixed_expose_event(
+ GtkWidget * widget,
+ GdkEventExpose * event,
+ wWin_p win)
+{
+ if (event->count==0) {
+ return window_redraw(win, TRUE);
+ } else {
+ return FALSE;
+ }
+}
+
+static int window_configure_event(
+ GtkWidget * widget,
+ GdkEventConfigure * event,
+ wWin_p win)
+{
+// wPos_t h;
+
+ if (win==NULL) {
+ return FALSE;
+ }
+
+ //h = event->height - BORDERSIZE;
+
+ //if (win->option&F_MENUBAR) {
+ //h -= MENUH;
+ //}
+
+ if (win->option&F_RESIZE) {
+ if (event->width < 10 || event->height < 10) {
+ return TRUE;
+ }
+
+ if (win->w != event->width || win->h != event->height) {
+ win->w = event->width;
+ win->h = event->height;
+
+ if (win->w < MIN_WIN_WIDTH) {
+ win->w = MIN_WIN_WIDTH;
+ }
+
+ if (win->h < MIN_WIN_HEIGHT) {
+ win->h = MIN_WIN_HEIGHT;
+ }
+
+ if (win->option&F_MENUBAR) {
+ gtk_widget_set_size_request(win->menubar, win->w, MENUH);
+ }
+
+ if (win->busy==FALSE && win->winProc) {
+ win->winProc(win, wResize_e, win->data);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * Get current state of shift, ctrl or alt keys.
+ *
+ * \return or'ed value of WKEY_SHIFT, WKEY_CTRL and WKEY_ALT depending on state
+ */
+
+int wGetKeyState(void)
+{
+ return keyState;
+}
+
+wBool_t catch_shift_ctrl_alt_keys(
+ GtkWidget * widget,
+ GdkEventKey *event,
+ void * data)
+{
+ int state;
+ state = 0;
+
+ switch (event->keyval) {
+ case GDK_KEY_Shift_L:
+ case GDK_KEY_Shift_R:
+ state |= WKEY_SHIFT;
+ break;
+
+ case GDK_KEY_Control_L:
+ case GDK_KEY_Control_R:
+ state |= WKEY_CTRL;
+ break;
+
+ case GDK_KEY_Alt_L:
+ case GDK_KEY_Alt_R:
+ state |= WKEY_ALT;
+ break;
+ }
+
+ if (state != 0) {
+ if (event->type == GDK_KEY_PRESS) {
+ keyState |= state;
+ } else {
+ keyState &= ~state;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint window_char_event(
+ GtkWidget * widget,
+ GdkEventKey *event,
+ wWin_p win)
+{
+ wControl_p bb;
+
+ if (catch_shift_ctrl_alt_keys(widget, event, win)) {
+ return FALSE;
+ }
+
+ if (event->type == GDK_KEY_RELEASE) {
+ return FALSE;
+ }
+
+ if (event->state == 0) {
+ if (event->keyval == GDK_KEY_Escape) {
+ for (bb=win->first; bb; bb=bb->next) {
+ if (bb->type == B_BUTTON && (bb->option&BB_CANCEL)) {
+ wlibButtonDoAction((wButton_p)bb);
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ if (wlibHandleAccelKey(event)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/*
+ *******************************************************************************
+ *
+ * Main and Popup Windows
+ *
+ *******************************************************************************
+ */
+
+/**
+ * Create a window
+ *
+ * \param parent IN parent window
+ * \param winType IN type of window
+ * \param x IN x position
+ * \param y IN y position
+ * \param labelStr IN window title
+ * \param nameStr IN
+ * \param option IN
+ * \param winProc IN window procedure
+ * \param data IN additional data to pass to the window procedure
+ * \return describe the return value
+ */
+
+static wWin_p wWinCommonCreate(
+ wWin_p parent,
+ int winType,
+ wPos_t x,
+ wPos_t y,
+ const char * labelStr,
+ const char * nameStr,
+ long option,
+ wWinCallBack_p winProc,
+ void * data)
+{
+ wWin_p w;
+ int h;
+ w = wlibAlloc(NULL, winType, x, y, labelStr, sizeof *w, data);
+ w->busy = TRUE;
+ w->option = option;
+ getWinSize(w, nameStr);
+ h = BORDERSIZE;
+
+ if (w->option&F_MENUBAR) {
+ h += MENUH;
+ }
+
+ if (winType == W_MAIN) {
+ w->gtkwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ } else {
+ w->gtkwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ if (gtkMainW) {
+ gtk_window_set_transient_for(GTK_WINDOW(w->gtkwin),
+ GTK_WINDOW(gtkMainW->gtkwin));
+ }
+ }
+
+ if (option & F_HIDE) {
+ gtk_widget_hide(w->gtkwin);
+ }
+
+ /* center window on top of parent window */
+ if (option & F_CENTER) {
+ gtk_window_set_position(GTK_WINDOW(w->gtkwin), GTK_WIN_POS_CENTER_ON_PARENT);
+ }
+
+ w->widget = gtk_fixed_new();
+
+ if (w->widget == 0) {
+ abort();
+ }
+
+ if (w->option&F_MENUBAR) {
+ w->menubar = gtk_menu_bar_new();
+ gtk_container_add(GTK_CONTAINER(w->widget), w->menubar);
+ gtk_widget_show(w->menubar);
+ gtk_widget_set_size_request(w->menubar, -1, MENUH);
+ }
+
+ gtk_container_add(GTK_CONTAINER(w->gtkwin), w->widget);
+
+ if (w->option&F_AUTOSIZE) {
+ w->realX = 0;
+ w->w = 0;
+ w->realY = h;
+ w->h = 0;
+ } else {
+ w->w = w->realX = w->origX;
+ w->h = w->realY = w->origY+h;
+ gtk_widget_set_size_request(w->gtkwin, w->w, w->h);
+ gtk_widget_set_size_request(w->widget, w->w, w->h);
+
+ if (w->option&F_MENUBAR) {
+ gtk_widget_set_size_request(w->menubar, w->w, MENUH);
+ }
+ }
+
+ w->first = w->last = NULL;
+ w->winProc = winProc;
+ g_signal_connect(GTK_OBJECT(w->gtkwin), "delete_event",
+ G_CALLBACK(window_delete_event), w);
+ g_signal_connect(GTK_OBJECT(w->widget), "expose_event",
+ G_CALLBACK(fixed_expose_event), w);
+ g_signal_connect(GTK_OBJECT(w->gtkwin), "configure_event",
+ G_CALLBACK(window_configure_event), w);
+ g_signal_connect(GTK_OBJECT(w->gtkwin), "key_press_event",
+ G_CALLBACK(window_char_event), w);
+ g_signal_connect(GTK_OBJECT(w->gtkwin), "key_release_event",
+ G_CALLBACK(window_char_event), w);
+ gtk_widget_set_events(w->widget, GDK_EXPOSURE_MASK);
+ gtk_widget_set_events(GTK_WIDGET(w->gtkwin),
+ GDK_EXPOSURE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ if (w->option & F_RESIZE) {
+ gtk_window_set_resizable(GTK_WINDOW(w->gtkwin), TRUE);
+ } else {
+ gtk_window_set_resizable(GTK_WINDOW(w->gtkwin), FALSE);
+ }
+
+ w->lastX = 0;
+ w->lastY = h;
+ w->shown = FALSE;
+ w->nameStr = nameStr?strdup(nameStr):NULL;
+
+ if (labelStr) {
+ gtk_window_set_title(GTK_WINDOW(w->gtkwin), labelStr);
+ }
+
+ if (listHelpStrings) {
+ printf("WINDOW - %s\n", nameStr?nameStr:"<NULL>");
+ }
+
+ if (firstWin) {
+ lastWin->next = (wControl_p)w;
+ } else {
+ firstWin = (wControl_p)w;
+ }
+
+ lastWin = (wControl_p)w;
+ gtk_widget_show(w->widget);
+ gtk_widget_realize(w->gtkwin);
+ w->busy = FALSE;
+ return w;
+}
+
+
+/**
+ * Initialize the application's main window. This function does the necessary initialization
+ * of the application including creation of the main window.
+ *
+ * \param name IN internal name of the application. Used for filenames etc.
+ * \param x IN Initial window width
+ * \param y IN Initial window height
+ * \param helpStr IN Help topic string
+ * \param labelStr IN window title
+ * \param nameStr IN Window name
+ * \param option IN options for window creation
+ * \param winProc IN pointer to main window procedure
+ * \param data IN User context
+ * \return window handle or NULL on error
+ */
+
+wWin_p wWinMainCreate(
+ const char * name, /* Application name */
+ wPos_t x, /* Initial window width */
+ wPos_t y, /* Initial window height */
+ const char * helpStr, /* Help topic string */
+ const char * labelStr, /* Window title */
+ const char * nameStr, /* Window name */
+ long option, /* Options */
+ wWinCallBack_p winProc, /* Call back function */
+ void * data) /* User context */
+{
+ char *pos;
+
+ if (pos = strchr(name, ';')) {
+ /* if found, split application name and configuration name */
+ strcpy(wConfigName, pos + 1);
+ } else {
+ /* if not found, application name and configuration name are same */
+ strcpy(wConfigName, name);
+ }
+
+ gtkMainW = wWinCommonCreate(NULL, W_MAIN, x, y, labelStr, nameStr, option,
+ winProc, data);
+ wDrawColorWhite = wDrawFindColor(0xFFFFFF);
+ wDrawColorBlack = wDrawFindColor(0x000000);
+ return gtkMainW;
+}
+
+/**
+ * Create a new popup window.
+ *
+ * \param parent IN Parent window (may be NULL)
+ * \param x IN Initial window width
+ * \param y IN Initial window height
+ * \param helpStr IN Help topic string
+ * \param labelStr IN Window title
+ * \param nameStr IN Window name
+ * \param option IN Options
+ * \param winProc IN call back function
+ * \param data IN User context information
+ * \return handle for new window
+ */
+
+wWin_p wWinPopupCreate(
+ wWin_p parent,
+ wPos_t x,
+ wPos_t y,
+ const char * helpStr,
+ const char * labelStr,
+ const char * nameStr,
+ long option,
+ wWinCallBack_p winProc,
+ void * data)
+{
+ wWin_p win;
+
+ if (parent == NULL) {
+ if (gtkMainW == NULL) {
+ abort();
+ }
+
+ parent = gtkMainW;
+ }
+
+ win = wWinCommonCreate(parent, W_POPUP, x, y, labelStr, nameStr, option,
+ winProc, data);
+ return win;
+}
+
+
+/**
+ * Terminates the applicaton with code <rc>. Before closing the main window
+ * call back is called with wQuit_e. The program is terminated without exiting
+ * the main message loop.
+ *
+ * \param rc IN exit code
+ * \return never returns
+ */
+
+
+void wExit(
+ int rc) /* Application return code */
+{
+ wWin_p win;
+
+ for (win = (wWin_p)firstWin; win; win = (wWin_p)win->next) {
+ if (gtk_widget_get_visible(GTK_WIDGET(win->gtkwin))) {
+ saveSize(win);
+ savePos(win);
+ }
+ }
+
+ wPrefFlush();
+
+ if (gtkMainW && gtkMainW->winProc != NULL) {
+ gtkMainW->winProc(gtkMainW, wQuit_e, gtkMainW->data);
+ }
+
+ exit(rc);
+}
diff --git a/app/wlib/gtklib/wpref.c b/app/wlib/gtklib/wpref.c
index 4df3de9..effc2a5 100644
--- a/app/wlib/gtklib/wpref.c
+++ b/app/wlib/gtklib/wpref.c
@@ -1,6 +1,5 @@
-/** \file wpref.c Handle loading and saving preferences.
- *
- * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/wlib/gtklib/wpref.c,v 1.15 2010-04-28 04:04:38 dspagnol Exp $
+/** \file wpref.c
+ * Handle loading and saving preferences.
*/
/* XTrkCad - Model Railroad CAD
@@ -24,33 +23,31 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <dirent.h>
#include <ctype.h>
+#include <dirent.h>
#include <sys/stat.h>
+#define GTK_DISABLE_SINGLE_INCLUDES
+#define GDK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#define GSEAL_ENABLE
+
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
#include "wlib.h"
+#include "gtkint.h"
#include "dynarr.h"
#include "i18n.h"
-#ifndef TRUE
-#define TRUE (1)
-#define FALSE (0)
-#endif
-
-#ifdef XTRKCAD_CMAKE_BUILD
#include "xtrkcad-config.h"
-#endif
-extern char wAppName[];
extern char wConfigName[];
static char appLibDir[BUFSIZ];
static char appWorkDir[BUFSIZ];
static char userHomeDir[BUFSIZ];
-EXPORT void wInitAppName(char *appName)
-{
- strcpy(wAppName, appName);
-}
/*
*******************************************************************************
@@ -61,16 +58,17 @@ EXPORT void wInitAppName(char *appName)
*/
-EXPORT const char * wGetAppLibDir( void )
/** Find the directory where configuration files, help, demos etc are installed.
* The search order is:
* 1. Directory specified by the XTRKCADLIB environment variable
* 2. Directory specified by XTRKCAD_INSTALL_PREFIX/share/xtrkcad
- * 3. /usr/share/xtrkcad
- * 4. /usr/local/share/xtrkcad
+ * 3. /usr/lib/xtrkcad
+ * 4. /usr/local/lib/xtrkcad
*
* \return pointer to directory name
*/
+
+const char * wGetAppLibDir( void )
{
char * cp, *ep;
char msg[BUFSIZ*2];
@@ -81,7 +79,7 @@ EXPORT const char * wGetAppLibDir( void )
return appLibDir;
}
- for (cp=wAppName,ep=envvar; *cp; cp++,ep++)
+ for (cp=wlibGetAppName(),ep=envvar; *cp; cp++,ep++)
*ep = toupper(*cp);
strcpy( ep, "LIB" );
ep = getenv( envvar );
@@ -92,24 +90,22 @@ EXPORT const char * wGetAppLibDir( void )
}
}
-#ifdef XTRKCAD_CMAKE_BUILD
strcpy(appLibDir, XTRKCAD_INSTALL_PREFIX);
strcat(appLibDir, "/share/");
- strcat(appLibDir, wAppName);
+ strcat(appLibDir, wlibGetAppName());
if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) {
return appLibDir;
}
-#endif
- strcpy( appLibDir, "/usr/share/" );
- strcat( appLibDir, wAppName );
+ strcpy( appLibDir, "/usr/lib/" );
+ strcat( appLibDir, wlibGetAppName() );
if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) {
return appLibDir;
}
- strcpy( appLibDir, "/usr/local/share/" );
- strcat( appLibDir, wAppName );
+ strcpy( appLibDir, "/usr/local/lib/" );
+ strcat( appLibDir, wlibGetAppName() );
if ((stat( appLibDir, &buf) == 0 ) && S_ISDIR( buf.st_mode)) {
return appLibDir;
}
@@ -118,11 +114,11 @@ EXPORT const char * wGetAppLibDir( void )
_("The required configuration files could not be located in the expected location.\n\n"
"Usually this is an installation problem. Make sure that these files are installed in either \n"
" %s/share/xtrkcad or\n"
- " /usr/share/%s or\n"
- " /usr/local/share/%s\n"
+ " /usr/lib/%s or\n"
+ " /usr/local/lib/%s\n"
"If this is not possible, the environment variable %s must contain "
"the name of the correct directory."),
- XTRKCAD_INSTALL_PREFIX, wAppName, wAppName, envvar );
+ XTRKCAD_INSTALL_PREFIX, wlibGetAppName(), wlibGetAppName(), envvar );
wNoticeEx( NT_ERROR, msg, _("Ok"), NULL );
appLibDir[0] = '\0';
wExit(0);
@@ -138,7 +134,7 @@ EXPORT const char * wGetAppLibDir( void )
*/
-EXPORT const char * wGetAppWorkDir(
+const char * wGetAppWorkDir(
void )
{
char tmp[BUFSIZ+20];
@@ -152,7 +148,7 @@ EXPORT const char * wGetAppWorkDir(
wNoticeEx( NT_ERROR, _("HOME is not set"), _("Exit"), NULL);
wExit(0);
}
- sprintf( appWorkDir, "%s/.%s", homeDir, wAppName );
+ sprintf( appWorkDir, "%s/.%s", homeDir, wlibGetAppName() );
if ( (dirp = opendir(appWorkDir)) != NULL ) {
closedir(dirp);
} else {
@@ -167,7 +163,7 @@ EXPORT const char * wGetAppWorkDir(
*/
struct stat stFileInfo;
char appEtcConfig[BUFSIZ];
- sprintf( appEtcConfig, "/etc/%s.rc", wAppName );
+ sprintf( appEtcConfig, "/etc/%s.rc", wlibGetAppName());
if ( stat( appEtcConfig, &stFileInfo ) == 0 ) {
char copyConfigCmd[(BUFSIZ * 2) + 3];
@@ -186,7 +182,7 @@ EXPORT const char * wGetAppWorkDir(
* \return pointer to the user's home directory
*/
-EXPORT const char *wGetUserHomeDir( void )
+const char *wGetUserHomeDir( void )
{
char *homeDir;
@@ -223,9 +219,13 @@ dynArr_t prefs_da;
#define prefs(N) DYNARR_N(prefs_t,prefs_da,N)
wBool_t prefInitted = FALSE;
+/**
+ * Read the configuration file into memory
+ */
+
static void readPrefs( void )
{
- char tmp[BUFSIZ], *sp, *np, *vp, *cp;
+ char tmp[BUFSIZ], *np, *vp, *cp;
const char * workDir;
FILE * prefFile;
prefs_t * p;
@@ -237,6 +237,8 @@ static void readPrefs( void )
if (prefFile == NULL)
return;
while ( ( fgets(tmp, sizeof tmp, prefFile) ) != NULL ) {
+ char *sp;
+
sp = tmp;
while ( *sp==' ' || *sp=='\t' ) sp++;
if ( *sp == '\n' || *sp == '#' )
@@ -276,7 +278,7 @@ static void readPrefs( void )
* \param sval IN value to save
*/
-EXPORT void wPrefSetString(
+void wPrefSetString(
const char * section, /* Section */
const char * name, /* Name */
const char * sval ) /* Value */
@@ -303,12 +305,16 @@ EXPORT void wPrefSetString(
p->val = strdup(sval);
}
+/**
+ * Get a string from the user preferences.
+ *
+ * \param section IN section in preferences file
+ * \param name IN name of parameter
+ */
-EXPORT const char * wPrefGetString(
+const char * wPrefGetString(
const char * section, /* Section */
const char * name ) /* Name */
-/*
-*/
{
prefs_t * p;
@@ -331,7 +337,7 @@ EXPORT const char * wPrefGetString(
* \param lval IN value to save
*/
-EXPORT void wPrefSetInteger(
+ void wPrefSetInteger(
const char * section, /* Section */
const char * name, /* Name */
long lval ) /* Value */
@@ -352,7 +358,7 @@ EXPORT void wPrefSetInteger(
* \return TRUE if value differs from default, FALSE if the same
*/
-EXPORT wBool_t wPrefGetInteger(
+wBool_t wPrefGetInteger(
const char * section, /* Section */
const char * name, /* Name */
long * res, /* Address of result */
@@ -382,7 +388,7 @@ EXPORT wBool_t wPrefGetInteger(
* \param lval IN the value
*/
-EXPORT void wPrefSetFloat(
+ void wPrefSetFloat(
const char * section, /* Section */
const char * name, /* Name */
double lval ) /* Value */
@@ -404,7 +410,7 @@ EXPORT void wPrefSetFloat(
*/
-EXPORT wBool_t wPrefGetFloat(
+wBool_t wPrefGetFloat(
const char * section, /* Section */
const char * name, /* Name */
double * res, /* Address of result */
@@ -426,40 +432,14 @@ EXPORT wBool_t wPrefGetFloat(
return TRUE;
}
-
-EXPORT const char * wPrefGetSectionItem(
- const char * sectionName,
- wIndex_t * index,
- const char ** name )
-{
- prefs_t * p;
-
- if (!prefInitted)
- readPrefs();
-
- if ( *index >= prefs_da.cnt )
- return NULL;
-
- for (p=&prefs((*index)++); p<&prefs(prefs_da.cnt); p++,(*index)++) {
- if ( strcmp( p->section, sectionName ) == 0 ) {
- if ( name )
- *name = p->name;
- return p->val;
- }
- }
- return NULL;
-}
-
/**
* Save the configuration to a file. The config parameters are held and updated in an array.
* To make the settings persistant, this function has to be called.
*
*/
-EXPORT void wPrefFlush(
+void wPrefFlush(
void )
-/*
-*/
{
prefs_t * p;
char tmp[BUFSIZ];
@@ -481,11 +461,13 @@ EXPORT void wPrefFlush(
fclose( prefFile );
}
+/**
+ * Clear the preferences from memory
+ * \return
+ */
-EXPORT void wPrefReset(
+void wPrefReset(
void )
-/*
-*/
{
prefs_t * p;
diff --git a/app/wlib/include/wlib.h b/app/wlib/include/wlib.h
index cf8f337..fa07454 100644
--- a/app/wlib/include/wlib.h
+++ b/app/wlib/include/wlib.h
@@ -65,6 +65,70 @@ typedef struct {
extern long debugWindow;
extern long wDebugFont;
+/*------------------------------------------------------------------------------
+ *
+ * Bitmap Controls bitmap.c
+ */
+
+wControl_p wBitmapCreate(wWin_p parent, wPos_t x, wPos_t y, long options, wIcon_p iconP);
+wIcon_p wIconCreateBitMap(wPos_t w, wPos_t h, const char *bits, wDrawColor color);
+wIcon_p wIconCreatePixMap(char *pm[]);
+void wIconSetColor(wIcon_p ip, wDrawColor color);
+
+/*------------------------------------------------------------------------------
+ *
+ * Frames around widgets boxes.c
+ *
+ */
+
+typedef enum {
+ wBoxThinB,
+ wBoxThinW,
+ wBoxAbove,
+ wBoxBelow,
+ wBoxThickB,
+ wBoxThickW,
+ wBoxRidge,
+ wBoxTrough }
+ wBoxType_e;
+
+void wBoxSetSize(wBox_p b, wPos_t w, wPos_t h);
+void wlibDrawBox(wWin_p win, wBoxType_e style, wPos_t x, wPos_t y, wPos_t w, wPos_t h);
+wBox_p wBoxCreate(wWin_p parent, wPos_t bx, wPos_t by, const char *labelStr, wBoxType_e boxTyp, wPos_t bw, wPos_t bh);
+
+/*------------------------------------------------------------------------------
+ *
+ * Buttons, toggles and radiobuttons button.c
+ *
+ */
+
+/* Creation CallBacks */
+typedef void (*wButtonCallBack_p)( void * );
+
+/* Creation Options */
+#define BB_DEFAULT (1L<<5)
+#define BB_CANCEL (1L<<6)
+#define BB_HELP (1L<<7)
+
+/* Creation CallBacks */
+typedef void (*wChoiceCallBack_p)( long, void * );
+
+/* Creation Options */
+#define BC_ICON (1L<<0)
+#define BC_HORZ (1L<<22)
+#define BC_NONE (1L<<19)
+#define BC_NOBORDER (1L<<15)
+
+void wButtonSetLabel(wButton_p bb, const char *labelStr);
+void wButtonSetBusy(wButton_p bb, int value);
+wButton_p wButtonCreate(wWin_p parent, wPos_t x, wPos_t y, const char *helpStr, const char *labelStr, long option, wPos_t width, wButtonCallBack_p action, void *data);
+void wRadioSetValue(wChoice_p bc, long value);
+long wRadioGetValue(wChoice_p bc);
+void wToggleSetValue(wChoice_p bc, long value);
+long wToggleGetValue(wChoice_p b);
+wChoice_p wRadioCreate(wWin_p parent, wPos_t x, wPos_t y, const char *helpStr, const char *labelStr, long option, const char **labels, long *valueP, wChoiceCallBack_p action, void *data);
+wChoice_p wToggleCreate(wWin_p parent, wPos_t x, wPos_t y, const char *helpStr, const char *labelStr, long option, const char **labels, long *valueP, wChoiceCallBack_p action, void *data);
+
/*------------------------------------------------------------------------------
*
@@ -217,50 +281,6 @@ void wControlLinkedActive( wControl_p b, int active );
/*------------------------------------------------------------------------------
*
- * Push buttons
- */
-
-/* Creation CallBacks */
-typedef void (*wButtonCallBack_p)( void * );
-
-/* Creation Options */
-#define BB_DEFAULT (1L<<5)
-#define BB_CANCEL (1L<<6)
-#define BB_HELP (1L<<7)
-
-wButton_p wButtonCreate( wWin_p, wPos_t, wPos_t, const char *, const char *, long,
- wPos_t, wButtonCallBack_p, void * );
-void wButtonSetLabel( wButton_p, const char * );
-void wButtonSetColor( wButton_p, wDrawColor );
-void wButtonSetBusy( wButton_p, wBool_t );
-
-
-/*------------------------------------------------------------------------------
- *
- * Radio and Toggle (Choice) Buttons
- */
-
-/* Creation CallBacks */
-typedef void (*wChoiceCallBack_p)( long, void * );
-
-/* Creation Options */
-#define BC_ICON (1L<<0)
-#define BC_HORZ (1L<<22)
-#define BC_NONE (1L<<19)
-#define BC_NOBORDER (1L<<15)
-
-wChoice_p wRadioCreate( wWin_p, wPos_t, wPos_t, const char *, const char *, long,
- const char **, long *, wChoiceCallBack_p, void * );
-wChoice_p wToggleCreate( wWin_p, wPos_t, wPos_t, const char *, const char *, long,
- const char **, long *, wChoiceCallBack_p, void * );
-void wRadioSetValue( wChoice_p, long );
-void wToggleSetValue( wChoice_p, long );
-long wRadioGetValue( wChoice_p );
-long wToggleGetValue( wChoice_p );
-
-
-/*------------------------------------------------------------------------------
- *
* String entry
*/
@@ -314,30 +334,35 @@ typedef void (*wListCallBack_p)( wIndex_t, const char *, wIndex_t, void *, void
#define BL_EDITABLE (1L<<23)
#define BL_ICON (1L<<0)
+
+/* lists, droplists and combo boxes */
+
wList_p wListCreate( wWin_p, wPos_t, wPos_t, const char *, const char *, long,
long, wPos_t, int, wPos_t *, wBool_t *, const char **, long *, wListCallBack_p, void * );
-wList_p wComboListCreate( wWin_p, wPos_t, wPos_t, const char *, const char *, long,
- long, wPos_t, long *, wListCallBack_p, void * );
wList_p wDropListCreate( wWin_p, wPos_t, wPos_t, const char *, const char *, long,
long, wPos_t, long *, wListCallBack_p, void * );
-void wListClear( wList_p );
-void wListSetIndex( wList_p, wIndex_t );
+
+wList_p wComboListCreate(wWin_p parent, wPos_t x, wPos_t y, const char *helpStr, const char *labelStr, long option, long number, wPos_t width, long *valueP, wListCallBack_p action, void *data);
+void wListClear(wList_p b);
+void wListSetIndex(wList_p b, int element);
+wIndex_t wListFindValue(wList_p b, const char *val);
+wIndex_t wListGetCount(wList_p b);
wIndex_t wListGetIndex( wList_p );
-wIndex_t wListFindValue( wList_p, const char * );
+void *wListGetItemContext(wList_p b, wIndex_t inx);
+wBool_t wListGetItemSelected(wList_p b, wIndex_t inx);
+wIndex_t wListGetSelectedCount(wList_p b);
+void wListSelectAll(wList_p bl);
+wBool_t wListSetValues(wList_p b, wIndex_t row, const char *labelStr, wIcon_p bm, void *itemData);
+void wListDelete(wList_p b, wIndex_t inx);
+int wListGetColumnWidths(wList_p bl, int colCnt, wPos_t *colWidths);
+wIndex_t wListAddValue(wList_p b, const char *labelStr, wIcon_p bm, void *itemData);
+void wListSetSize(wList_p bl, wPos_t w, wPos_t h);
+wIndex_t wListGetValues( wList_p, char *, int, void * *, void * * );
+
+/** \todo Check for the existance of following functions */
void wListSetValue( wList_p, const char * );
-int wListGetColumnWidths( wList_p, int, wPos_t * );
-wBool_t wListSetValues( wList_p, wIndex_t, const char *, wIcon_p, void * );
void wListSetActive( wList_p, wIndex_t, wBool_t );
void wListSetEditable( wList_p, wBool_t );
-wIndex_t wListAddValue( wList_p, const char *, wIcon_p, void * );
-void wListDelete( wList_p, wIndex_t );
-wIndex_t wListGetValues( wList_p, char *, int, void * *, void * * );
-void wListSelectAll( wList_p bl );
-wIndex_t wListGetCount( wList_p );
-void * wListGetItemContext( wList_p, wIndex_t );
-wBool_t wListGetItemSelected( wList_p, wIndex_t );
-wIndex_t wListGetSelectedCount( wList_p );
-void wListSetSize( wList_p, wPos_t, wPos_t );
/*------------------------------------------------------------------------------
@@ -361,26 +386,6 @@ wPos_t wMessageGetHeight( long );
/*------------------------------------------------------------------------------
*
- * Boxes
- */
-
-typedef enum {
- wBoxThinB,
- wBoxThinW,
- wBoxAbove,
- wBoxBelow,
- wBoxThickB,
- wBoxThickW,
- wBoxRidge,
- wBoxTrough }
- wBoxType_e;
-wBox_p wBoxCreate( wWin_p, wPos_t, wPos_t, const char *, wBoxType_e,
- wPos_t, wPos_t );
-void wBoxSetSize( wBox_p, wPos_t, wPos_t );
-
-
-/*------------------------------------------------------------------------------
- *
* Lines
*/
@@ -651,7 +656,7 @@ typedef enum {
typedef int (*wFilSelCallBack_p)( int files, char ** fileName, void * );
struct wFilSel_t * wFilSelCreate(wWin_p, wFilSelMode_e, int, const char *, const char *,
wFilSelCallBack_p, void * );
-int wFilSelect( struct wFilSel_t *, const char * );
+int wFilSelect( struct wFilSel_t *, const char * );
/*------------------------------------------------------------------------------
@@ -684,11 +689,4 @@ void wPrefReset( void );
void CleanupCustom( void );
-/*------------------------------------------------------------------------------
- *
- * Bitmap Controls
- */
-
-wControl_p wBitmapCreate( wWin_p parent, wPos_t xx, wPos_t yy, long options, wIcon_p iconP );
-
#endif
diff --git a/app/wlib/mswlib/mswedit.c b/app/wlib/mswlib/mswedit.c
index 5bb26ec..937a83e 100644
--- a/app/wlib/mswlib/mswedit.c
+++ b/app/wlib/mswlib/mswedit.c
@@ -109,7 +109,7 @@ void wStringSetValue(
wString_p b,
const char * arg )
{
- WORD len = strlen( arg );
+ WORD len = (WORD)strlen( arg );
SendMessage( b->hWnd, WM_SETTEXT, 0, (DWORD)arg );
#ifdef WIN32
SendMessage( b->hWnd, EM_SETSEL, len, len );
diff --git a/app/wlib/mswlib/mswmisc.c b/app/wlib/mswlib/mswmisc.c
index 85438e0..cc46e4e 100644
--- a/app/wlib/mswlib/mswmisc.c
+++ b/app/wlib/mswlib/mswmisc.c
@@ -217,7 +217,7 @@ static void doDumpControls(void)
b = controlMap(inx).b;
if ( b ) {
fprintf( dumpControlsF, "[%0.3d] [%x] %s %s %s\n", inx,
- b->hWnd,
+ (unsigned int)b->hWnd,
(b->type>=0&&b->type<=B_BOX?controlNames[b->type]:"NOTYPE"),
(b->labelStr?b->labelStr:"<NULL>"),
(b->helpStr?b->helpStr:"<NULL>") );
diff --git a/distribution/osx/CMakeLists.txt b/distribution/osx/CMakeLists.txt
index 5269250..2561fae 100644
--- a/distribution/osx/CMakeLists.txt
+++ b/distribution/osx/CMakeLists.txt
@@ -3,53 +3,12 @@ GET_TARGET_PROPERTY(XTRKCAD_LOCATION xtrkcad LOCATION)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/dependencies.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/dependencies.cmake" @ONLY)
INSTALL(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/dependencies.cmake")
-# Handle some external dependencies that can't be detected automatically ...
-SET(MACPORTS_DIR "/opt/local" CACHE PATH "Root directory containing installed MacPort packages")
-MARK_AS_ADVANCED(MACPORTS_DIR)
-
-INSTALL(DIRECTORY
- ${MACPORTS_DIR}/lib/gtk-2.0
- DESTINATION lib
- USE_SOURCE_PERMISSIONS
- )
-
-INSTALL(DIRECTORY
- ${MACPORTS_DIR}/etc/gtk-2.0
- DESTINATION etc
- USE_SOURCE_PERMISSIONS
- )
-
-INSTALL(DIRECTORY
- ${MACPORTS_DIR}/lib/pango
- DESTINATION lib
- USE_SOURCE_PERMISSIONS
- )
-
-INSTALL(DIRECTORY
- ${MACPORTS_DIR}/lib/gdk-pixbuf-2.0
- DESTINATION lib
- USE_SOURCE_PERMISSIONS
- )
-
-INSTALL(FILES
- ${MACPORTS_DIR}/etc/pango/pangorc
- ${MACPORTS_DIR}/etc/pango/pango.modules
- DESTINATION etc/pango
- )
-
-INSTALL(FILES
- ${MACPORTS_DIR}/etc/fonts/fonts.conf
- ${MACPORTS_DIR}/etc/fonts/fonts.dtd
- DESTINATION etc/fonts
- )
-
-INSTALL(FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/yosemite-fix/libxml2.2.dylib
- ${CMAKE_CURRENT_SOURCE_DIR}/yosemite-fix/libz.1.dylib
- ${CMAKE_CURRENT_SOURCE_DIR}/yosemite-fix/libiconv.2.dylib
- DESTINATION lib
-)
# Generate bundles ...
ADD_SUBDIRECTORY(bundle)
+# Add replacement bundle technique ...
+FILE(COPY gtk-bundle/ DESTINATION gtk-bundle )
+
+ADD_SUBDIRECTORY(gtk-bundle)
+
diff --git a/distribution/osx/bundle/Info.plist.in b/distribution/osx/bundle/Info.plist.in
index ba946ee..e8beb97 100644
--- a/distribution/osx/bundle/Info.plist.in
+++ b/distribution/osx/bundle/Info.plist.in
@@ -8,6 +8,10 @@
<string>XTrackCAD</string>
<key>CFBundleGetInfoString</key>
<string>@XTRKCAD_VERSION@</string>
+ <key>CFBundleHelpBookFolder</key>
+ <string>XTrackCAD.help</string>
+ <key>CFBundleHelpBookName</key>
+ <string>org.xtrkcad.help</string>
<key>CFBundleIconFile</key>
<string>XTrackCAD</string>
<key>LSMinimumSystemVersion</key>
diff --git a/distribution/osx/gtk-bundle/CMakeLists.txt b/distribution/osx/gtk-bundle/CMakeLists.txt
new file mode 100644
index 0000000..4aa1150
--- /dev/null
+++ b/distribution/osx/gtk-bundle/CMakeLists.txt
@@ -0,0 +1,20 @@
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Info-xtrkcad.plist.in ${CMAKE_CURRENT_BINARY_DIR}/info-xtrkcad.plist @ONLY)
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/xtrkcad-template.dmg.zip ${CMAKE_CURRENT_BINARY_DIR}/xtrkcad-template-dmg.zip COPYONLY)
+
+FILE(MAKE_DIRECTORY share)
+FILE(MAKE_DIRECTORY bin)
+
+INSTALL (
+FILES ${CMAKE_CURRENT_BINARY_DIR}/info-xtrkcad.plist
+DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help
+)
+INSTALL (
+FILES ${CMAKE_CURRENT_SOURCE_DIR}/toc.js
+DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/Contents/Resources/en.lproj
+)
+
+ADD_SUBDIRECTORY(XTrackCAD-help)
+
+
+
diff --git a/distribution/osx/gtk-bundle/Drag-to-Copy-Arrow.png b/distribution/osx/gtk-bundle/Drag-to-Copy-Arrow.png
new file mode 100644
index 0000000..4031d45
--- /dev/null
+++ b/distribution/osx/gtk-bundle/Drag-to-Copy-Arrow.png
Binary files differ
diff --git a/distribution/osx/gtk-bundle/XTrackCAD-help/CMakeLists.txt b/distribution/osx/gtk-bundle/XTrackCAD-help/CMakeLists.txt
new file mode 100644
index 0000000..c25d0e1
--- /dev/null
+++ b/distribution/osx/gtk-bundle/XTrackCAD-help/CMakeLists.txt
@@ -0,0 +1,14 @@
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Info-xtrkcad-help.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY)
+
+FILE(MAKE_DIRECTORY share)
+
+INSTALL (
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/Contents
+)
+
+ADD_SUBDIRECTORY(Contents)
+
+
+
diff --git a/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/CMakeLists.txt b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/CMakeLists.txt
new file mode 100644
index 0000000..eb44cea
--- /dev/null
+++ b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/CMakeLists.txt
@@ -0,0 +1,5 @@
+
+ADD_SUBDIRECTORY(Resources)
+
+
+
diff --git a/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/CMakeLists.txt b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/CMakeLists.txt
new file mode 100644
index 0000000..275bb02
--- /dev/null
+++ b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+MAKE_DIRECTORY (${CMAKE_INSTALL_PREFIX}/${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/shrd)
+
+INSTALL (
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/icon_16x16.png
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/Contents/Resources
+ )
+
+ADD_SUBDIRECTORY(en.lproj)
+
+
+
diff --git a/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/CMakeLists.txt b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/CMakeLists.txt
new file mode 100644
index 0000000..4ac56f7
--- /dev/null
+++ b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+
+INSTALL(
+
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/InfoPlist.strings
+ DESTINATION ${XTRKCAD_SHARE_INSTALL_DIR}/XTrackCAD.help/Contents/Resources/en.lproj
+ )
+
+
+
diff --git a/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/InfoPlist.strings b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/InfoPlist.strings
new file mode 100644
index 0000000..b024970
--- /dev/null
+++ b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+"CFBundleName" = "XTrackCAD Help"
+"HPDBookTitle" = "XTrackCAD Help"
diff --git a/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/icon_16x16.png b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/icon_16x16.png
new file mode 100644
index 0000000..ed29bd5
--- /dev/null
+++ b/distribution/osx/gtk-bundle/XTrackCAD-help/Contents/Resources/icon_16x16.png
Binary files differ
diff --git a/distribution/osx/gtk-bundle/XTrackCAD-help/info-xtrkcad-help.plist.in b/distribution/osx/gtk-bundle/XTrackCAD-help/info-xtrkcad-help.plist.in
new file mode 100644
index 0000000..4d149d6
--- /dev/null
+++ b/distribution/osx/gtk-bundle/XTrackCAD-help/info-xtrkcad-help.plist.in
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en_us</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.xtrkcad.help</string>
+ <key>CFInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundlePackageName</key>
+ <string>XTrackCAD</string>
+ <key>CFBundleShortVersionString</key>
+ <string>@XTRKCAD_VERSION@</string>
+ <key>CFBundleVersion</key>
+ <string>@XTRKCAD_VERSION@</string>
+ <key>CFBundleDisplayName</key>
+ <string>XTrackCAD-Help</string>
+ <key>HPDBookAccessPath</key>
+ <string>index.html</string>
+ <key>HPDBookIconPath</key>
+ <string>icon_16x16.png</string>
+ <key>HPDBookIndexPath</key>
+ <string>XTrackCAD.helpindex</string>
+ <key>HPDBookKBDProduct</key>
+ <string>xtrkcad1</string>
+ <key>HPDBookTitle</key>
+ <string>XTrackCAD Help</string>
+ <key>HPDBookType</key>
+ <string>3</string>
+ <key>HPDBookTopicListCSSPath</key>
+ <string>xtrkcad_lin.css</string>
+</dict>
+</plist>
diff --git a/distribution/osx/gtk-bundle/gtk-bundle.README b/distribution/osx/gtk-bundle/gtk-bundle.README
new file mode 100644
index 0000000..139cec7
--- /dev/null
+++ b/distribution/osx/gtk-bundle/gtk-bundle.README
@@ -0,0 +1,44 @@
+Readme for gtk-bundle directory.
+Created 12-1-2016 by Adam Richards
+
+Date: Dec-2016.
+
+The gtk-bundle technique replaces prior bundle techniques for OSX.
+
+Prerequisites:
+This directory produces files only for use with the gtk-mac-bundler tool (G-M-B).
+That tool is available as a MacPort and should be installed with
+"sudo port install gtk-mac-bundler"
+The bundler also requires a prior Macports install of GTK
+"sudo port install webkit-gtk"
+and that was the GTK level was used to build the xtrkcad binary.
+
+The ccmake process will place a copy of the binary in the /bin build subdirectory
+for use by G-M-B. It also copies over the resource share libraries into a subdirectory.
+
+Process:
+Once ccmake has been run "make" followed by "make install", the G-M-B tool is run
+pointing at the xtrkcad.bundle file.
+"cd /gtk-bundle"
+"gtk-mac-bundler xtrkcad-bundle"
+
+Output:
+G-M-B produces an .app bundle that is a self-contained executable
+from the binary xtrkcad in gtk-bundle/bin. It recursively rewires all the link pointers to be
+self-referential - that is, to point within the bundle.
+
+It uses the xtrkcad.plist to set properties of the app, including the
+icon from the .icns file. It sets the pre-run script to be xtrkcad-launcher.sh
+
+Next Steps:
+Once this xtrkcad.app file has been created, it can be moved to wherever is desirable
+- such as the Application folder. The app does not have dependencies on GTK components
+from MACPorts like the binary does - it is standalone.
+
+To produce an installable image from the .app, the disk utility can be used to create
+a RW image .dmg that the .app can be copied into.
+
+NOTE -
+It is expected that as long as the GTK level used in build can run on the OSX level used
+in build, the app bundle will work without necessarily having to be rebuilt for each OSX
+level. \ No newline at end of file
diff --git a/distribution/osx/gtk-bundle/info-xtrkcad.plist b/distribution/osx/gtk-bundle/info-xtrkcad.plist
new file mode 100644
index 0000000..d9d9bd3
--- /dev/null
+++ b/distribution/osx/gtk-bundle/info-xtrkcad.plist
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>XtrkCAD</string>
+ <key>CFBundleGetInfoString</key>
+ <string>4.24a, (C) 1997-2016 The XtrkCAD Team http://www.xtrkcad.org</string>
+ <key>CFBundleIconFile</key>
+ <string>xtrkcad-logo.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.xtrkcad</string>
+ <key>CFBundleHelpBookFolder</key>
+ <string>XTrackCAD.help</string>
+ <key>CFBundleHelpBookName</key>
+ <string>XTrackCAD Help</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>4.3.beta1</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>4.3.beta1</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright 1997 - 2016 The The XtrkCAD Team, GNU General Public License.</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.10</string>
+</dict>
+</plist>
diff --git a/distribution/osx/gtk-bundle/info-xtrkcad.plist.in b/distribution/osx/gtk-bundle/info-xtrkcad.plist.in
new file mode 100644
index 0000000..94fc56a
--- /dev/null
+++ b/distribution/osx/gtk-bundle/info-xtrkcad.plist.in
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>XtrkCAD</string>
+ <key>CFBundleGetInfoString</key>
+ <string>4.24a, (C) 1997-2016 The XtrkCAD Team http://www.xtrkcad.org</string>
+ <key>CFBundleIconFile</key>
+ <string>xtrkcad-logo.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.xtrkcad</string>
+ <key>CFBundleHelpBookFolder</key>
+ <string>XTrackCAD.help</string>
+ <key>CFBundleHelpBookName</key>
+ <string>XTrackCAD Help</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>@XTRKCAD_VERSION@</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>@XTRKCAD_VERSION@</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright 1997 - 2016 The The XtrkCAD Team, GNU General Public License.</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.10</string>
+</dict>
+</plist>
diff --git a/distribution/osx/gtk-bundle/toc.js b/distribution/osx/gtk-bundle/toc.js
new file mode 100644
index 0000000..4767236
--- /dev/null
+++ b/distribution/osx/gtk-bundle/toc.js
@@ -0,0 +1,67 @@
+<!-- Start of script to import html into div, toggle TOC button
+
+ // If in HelpViewer activate the TOC display button.
+ if ('HelpViewer' in window && 'showTOCButton' in window.HelpViewer) {
+ function toggle() {
+ var e = document.getElementById('toc');
+ if (e.style.display == 'block' || e.style.display=='')
+ {
+ e.style.display = 'none';
+ }
+ else
+ {
+ e.style.display = 'block';
+ }
+ }
+
+ function showTOCButton(state) {
+ window.HelpViewer.showTOCButton(state, toggle, toggle);
+ window.HelpViewer.setTOCButton(state);
+ }
+ window.setTimeout(showTOCButton(true), 1000);
+
+ }
+ window.onload=function() {
+ function include(a,b){
+ var c="/^(?:file):/"
+ var d=new XMLHttpRequest;
+ var e=0;
+ try {
+ d.open('GET',b,!0);
+ d.onreadystatechange=function(){
+ if (4==d.readyState) a.innerHTML=d.responseText;
+ var acc = document.getElementsByClassName("accordion");
+ var i;
+
+ for (i = 0; i < acc.length; i++) {
+ acc[i].onclick = function() {
+ var panels = document.getElementsByClassName("accordion");
+ this.classList.toggle("active");
+ var panel = this.parentElement.nextElementSibling;
+ if (panel.tagName == "DIV") {
+ if (panel.style.maxHeight){
+ panel.style.maxHeight = null;
+ } else {
+ panel.style.maxHeight = panel.scrollHeight + "px";
+ }
+ }
+ }
+ }
+ }
+ d.send();
+ } catch(f){};
+ }
+
+ var c=document.getElementsByTagName('DIV');
+ var i;
+ for(i = 0; i < c.length; i++) {
+ if (c[i].hasAttribute && c[i].hasAttribute('data-include')) {
+ include(c[i],c[i].getAttribute('data-include'));
+ };
+ }
+
+ }
+
+
+
+// End -->
diff --git a/distribution/osx/gtk-bundle/xtrkcad-bundler.sh b/distribution/osx/gtk-bundle/xtrkcad-bundler.sh
new file mode 100755
index 0000000..54928b0
--- /dev/null
+++ b/distribution/osx/gtk-bundle/xtrkcad-bundler.sh
@@ -0,0 +1,84 @@
+#!/bin/sh -x
+
+echo "Starting Xtrkcad-bundler" "@0"
+
+# Script to create Mac DMGs.
+# Created 12/1/2016
+# Author Adam Richards
+
+version="Version"
+
+while getopts "v:i:h" option; do
+ case "${option}" in
+ v) version="${OPTARG}";;
+ i) installib="${OPTARG}";;
+ h) usage;;
+ *) usage;;
+ esac
+done
+shift "$((OPTIND-1))"
+
+usage() {
+ echo "xtrkcad-bundler -i Cmake_Install_Lib [-v Version]";
+ echo " -v Version - will be appended to 'xtrkcad' in the image name";
+ echo " -i Cmake_Install_Lib where the binary and share files were placed by Make";
+ exit 1;
+
+ }
+
+if [ -z "${installib}" ]; then
+ usage;
+ exit 1;
+fi
+
+#copy in all shares
+echo "copying shares from build to share directory"
+cp -R "${installib}/share/" "share/"
+
+#copy in binary
+echo "copying binaries from build to bin directory"
+cp "${installib}/bin/xtrkcad" "bin"
+cp "${installib}/bin/helphelper" "bin"
+
+echo "executing gtk-mac-bundler"
+gtk-mac-bundler xtrkcad.bundle
+
+#Build dmg using template
+echo "making a copy of the tenplate"
+rm -f xtrkcad-template.dmg
+
+unzip -o xtrkcad-template.dmg.zip
+
+echo "mounting template copy"
+rm -rf dmg
+mkdir -p dmg
+
+hdiutil attach xtrkcad-template.dmg -quiet -noautoopen -mountpoint dmg
+
+#copy in bundle
+echo "copying in bundle"
+rm -rf "dmg/xtrkcad.app"
+cp -R "bin/xtrkcad.app" "dmg/xtrkcad.app"
+
+#convert dmg to RO
+echo "closing image"
+#dev_dmg='hdiutil info | grep "dmg" | grep "Apple_HFS"' && \
+hdiutil detach dmg -force
+master="xtrkcad-OSX-${version}"
+rm -rf "${master}".dmg
+echo "making image RO and compressed"
+hdiutil convert xtrkcad-template.dmg -format UDZO -imagekey zlib-level=9 -o "${master}"
+
+# compress the output
+
+rm -f "${master}".dmg.tar.gz
+
+tar -cvzf "${master}".dmg.tar.gz "${master}".dmg
+
+mv -f "${master}".dmg.tar.gz "${installib}"/bin
+
+rm -rf dmg
+
+echo "Tarball output image file ${master}.tar.gz is in ${installib}/bin directory"
+
+exit 0 \ No newline at end of file
diff --git a/distribution/osx/gtk-bundle/xtrkcad-launcher.sh b/distribution/osx/gtk-bundle/xtrkcad-launcher.sh
new file mode 100755
index 0000000..30988e5
--- /dev/null
+++ b/distribution/osx/gtk-bundle/xtrkcad-launcher.sh
@@ -0,0 +1,214 @@
+#!/bin/sh -x
+#
+# Author: Aaron Voisine <aaron@voisine.org>
+# Inkscape Modifications: Michael Wybrow <mjwybrow@users.sourceforge.net>
+# XTrackCAD Modifications: Timothy M. Shead <tshead@k-3d.com>
+
+if test "x$GTK_DEBUG_LAUNCHER" != x; then
+ set -x
+fi
+
+if test "x$GTK_DEBUG_GDB" != x; then
+ EXEC="gdb --args"
+else
+ EXEC=exec
+fi
+
+name=`basename "$0"`
+tmp="$0"
+tmp=`dirname "$tmp"`
+tmp=`dirname "$tmp"`
+bundle=`dirname "$tmp"`
+bundle_contents="$bundle"/Contents
+bundle_res="$bundle_contents"/Resources
+bundle_lib="$bundle_res"/lib
+bundle_bin="$bundle_res"/bin
+bundle_data="$bundle_res"/share
+bundle_etc="$bundle_res"/etc
+
+# check X installed
+if type -p "X" & > /dev/null; then
+ echo "XQuartz installed"
+ else
+ echo "XQuartz not installed"
+ osascript -e 'display dialog "XQuartz is not installed, please install it from XQuartz.org" buttons "OK" default button 1 with title "Stop"'
+ exit 1
+fi
+
+#XTRKCAD_BUNDLE="`echo "$0" | sed -e 's/\/Contents\/MacOS\/XTrackCAD//'`"
+XTRKCAD_BUNDLE="$bundle"
+XTRKCAD_RESOURCES="$XTRKCAD_BUNDLE/Contents/Resources"
+XTRKCAD_TEMP="/tmp/xtrkcad/$UID"
+XTRKCAD_ETC="$XTRKCAD_TEMP/etc"
+
+export GDK_PIXBUF_MODULE_FILE="$bundle_lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
+export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
+export PANGO_LIBDIR="$bundle_lib"
+export PANGO_SYSCONFDIR="$bundle_etc"
+
+export XDG_CONFIG_DIRS="$bundle_etc"/xdg
+export XDG_DATA_DIRS="$bundle_data"
+export GTK_DATA_PREFIX="$bundle_res"
+export GTK_EXE_PREFIX="$bundle_res"
+export GTK_PATH="$bundle_res"
+
+export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
+XTRKCAD_PANGO_RC_FILE="$XTRKCAD_RESOURCES/etc/pango/pangorc"
+
+I18NDIR="$bundle_data/locale"
+# Set the locale-related variables appropriately:
+unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE
+
+# Has a language ordering been set?
+# If so, set LC_MESSAGES and LANG accordingly; otherwise skip it.
+# First step uses sed to clean off the quotes and commas, to change - to _, and change the names for the chinese scripts from "Hans" to CN and "Hant" to TW.
+APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' `
+if test "$APPLELANGUAGES"; then
+ # A language ordering exists.
+ # Test, item per item, to see whether there is an corresponding locale.
+ for L in $APPLELANGUAGES; do
+ #test for exact matches:
+ if test -f "$I18NDIR/${L}/LC_MESSAGES/$APP.mo"; then
+ export LANG=$L
+ break
+ fi
+ #This is a special case, because often the original strings are in US
+ #English and there is no translation file.
+ if test "x$L" == "xen_US"; then
+ export LANG=$L
+ break
+ fi
+ #OK, now test for just the first two letters:
+ if test -f "$I18NDIR/${L:0:2}/LC_MESSAGES/$APP.mo"; then
+ export LANG=${L:0:2}
+ break
+ fi
+ #Same thing, but checking for any english variant.
+ if test "x${L:0:2}" == "xen"; then
+ export LANG=$L
+ break
+ fi;
+ done
+fi
+unset APPLELANGUAGES L
+
+# If we didn't get a language from the language list, try the Collation preference, in case it's the only setting that exists.
+APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder`
+if test -z ${LANG} -a -n $APPLECOLLATION; then
+ if test -f "$I18NDIR/${APPLECOLLATION:0:2}/LC_MESSAGES/$APP.mo"; then
+ export LANG=${APPLECOLLATION:0:2}
+ fi
+fi
+if test ! -z $APPLECOLLATION; then
+ export LC_COLLATE=$APPLECOLLATION
+fi
+unset APPLECOLLATION
+
+# Continue by attempting to find the Locale preference.
+APPLELOCALE=`defaults read .GlobalPreferences AppleLocale`
+
+if test -f "$I18NDIR/${APPLELOCALE:0:5}/LC_MESSAGES/$APP.mo"; then
+ if test -z $LANG; then
+ export LANG="${APPLELOCALE:0:5}"
+ fi
+
+elif test -z $LANG -a -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then
+ export LANG="${APPLELOCALE:0:2}"
+fi
+
+#Next we need to set LC_MESSAGES. If at all possilbe, we want a full
+#5-character locale to avoid the "Locale not supported by C library"
+#warning from Gtk -- even though Gtk will translate with a
+#two-character code.
+if test -n $LANG; then
+#If the language code matches the applelocale, then that's the message
+#locale; otherwise, if it's longer than two characters, then it's
+#probably a good message locale and we'll go with it.
+ if test $LANG == ${APPLELOCALE:0:5} -o $LANG != ${LANG:0:2}; then
+ export LC_MESSAGES=$LANG
+#Next try if the Applelocale is longer than 2 chars and the language
+#bit matches $LANG
+ elif test $LANG == ${APPLELOCALE:0:2} -a $APPLELOCALE > ${APPLELOCALE:0:2}; then
+ export LC_MESSAGES=${APPLELOCALE:0:5}
+#Fail. Get a list of the locales in $PREFIX/share/locale that match
+#our two letter language code and pick the first one, special casing
+#english to set en_US
+ elif test $LANG == "en"; then
+ export LC_MESSAGES="en_US"
+ else
+ LOC=`find $PREFIX/share/locale -name $LANG???`
+ for L in $LOC; do
+ export LC_MESSAGES=$L
+ done
+ fi
+else
+#All efforts have failed, so default to US english
+ export LANG="en_US"
+ export LC_MESSAGES="en_US"
+fi
+CURRENCY=`echo $APPLELOCALE | sed -En 's/.*currency=([[:alpha:]]+).*/\1/p'`
+if test "x$CURRENCY" != "x"; then
+#The user has set a special currency. Gtk doesn't install LC_MONETARY files, but Apple does in /usr/share/locale, so we're going to look there for a locale to set LC_CURRENCY to.
+ if test -f /usr/local/share/$LC_MESSAGES/LC_MONETARY; then
+ if test -a `cat /usr/local/share/$LC_MESSAGES/LC_MONETARY` == $CURRENCY; then
+ export LC_MONETARY=$LC_MESSAGES
+ fi
+ fi
+ if test -z "$LC_MONETARY"; then
+ FILES=`find /usr/share/locale -name LC_MONETARY -exec grep -H $CURRENCY {} \;`
+ if test -n "$FILES"; then
+ export LC_MONETARY=`echo $FILES | sed -En 's%/usr/share/locale/([[:alpha:]_]+)/LC_MONETARY.*%\1%p'`
+ fi
+ fi
+fi
+#No currency value means that the AppleLocale governs:
+if test -z "$LC_MONETARY"; then
+ LC_MONETARY=${APPLELOCALE:0:5}
+fi
+#For Gtk, which only looks at LC_ALL:
+export LC_ALL=$LC_MESSAGES
+
+unset APPLELOCALE FILES LOC
+
+echo "XTrackCAD: Starting $0"
+echo "XTrackCAD: XTRKCAD_BUNDLE: $XTRKCAD_BUNDLE"
+
+# Setup temporary runtime files
+# -rf "$XTRKCAD_TEMP"
+
+# Because the bundle could be located anywhere at runtime, we have to
+# create temporary copies of the Pango configuration files that
+# reflect our current location
+#mkdir -p "$XTRKCAD_ETC/gtk-2.0"
+#sed -e 's|/opt/local|'"$XTRKCAD_RESOURCES|g" "$XTRKCAD_RESOURCES/etc/gtk-2.0/gdk-pixbuf.loaders" > "$XTRKCAD_GDK_PIXBUF_MODULE_FILE"
+#sed -e 's|/opt/local|'"$XTRKCAD_RESOURCES|g" "$XTRKCAD_RESOURCES/etc/gtk-2.0/gtk.immodules" > "$XTRKCAD_GTK_IM_MODULE_FILE"
+#mkdir -p "$XTRKCAD_ETC/pango"
+#sed -e 's|/opt/local/etc|'"$XTRKCAD_ETC|g" "$XTRKCAD_RESOURCES/etc/pango/pangorc" > "$XTRKCAD_ETC/pango/pangorc"
+#sed -e 's|/opt/local|\"'"$XTRKCAD_RESOURCES|g" -e "s/\.so/.so\"/g" "$XTRKCAD_RESOURCES/etc/pango/pango.modules" > "$XTRKCAD_ETC/pango/pango.modules"
+
+#export "DYLD_LIBRARY_PATH=$XTRKCAD_RESOURCES/lib"
+#export "FONTCONFIG_PATH=$XTRKCAD_RESOURCES/etc/fonts"
+#export "GDK_PIXBUF_MODULE_FILE=$XTRKCAD_GDK_PIXBUF_MODULE_FILE"
+#export "GTK_IM_MODULE_FILE=$XTRKCAD_GTK_IM_MODULE_FILE"
+export "PANGO_RC_FILE=$XTRKCAD_PANGO_RC_FILE"
+export "PATH=$XTRKCAD_RESOURCES/bin:$PATH"
+export "XTRKCADLIB=$XTRKCAD_RESOURCES/xtrkcad"
+
+#export
+#exec "$XTRKCAD_BUNDLE/Contents/MacOS/XtrkCAD-bin"
+
+# Extra arguments can be added in environment.sh.
+EXTRA_ARGS=
+if test -f "$bundle_res/environment.sh"; then
+ source "$bundle_res/environment.sh"
+fi
+
+# Strip out the argument added by the OS.
+if /bin/expr "x$1" : '^x-psn_' > /dev/null; then
+ shift 1
+fi
+
+$EXEC "$XTRKCAD_BUNDLE/Contents/MacOS/XtrkCAD-bin" "$@"
+
+echo "XTrackCAD: Finishing $0"
+
diff --git a/distribution/osx/gtk-bundle/xtrkcad-logo.icns b/distribution/osx/gtk-bundle/xtrkcad-logo.icns
new file mode 100644
index 0000000..23213e1
--- /dev/null
+++ b/distribution/osx/gtk-bundle/xtrkcad-logo.icns
Binary files differ
diff --git a/distribution/osx/gtk-bundle/xtrkcad-template.dmg.zip b/distribution/osx/gtk-bundle/xtrkcad-template.dmg.zip
new file mode 100644
index 0000000..bb6972a
--- /dev/null
+++ b/distribution/osx/gtk-bundle/xtrkcad-template.dmg.zip
Binary files differ
diff --git a/distribution/osx/gtk-bundle/xtrkcad.bundle b/distribution/osx/gtk-bundle/xtrkcad.bundle
new file mode 100644
index 0000000..2259ea2
--- /dev/null
+++ b/distribution/osx/gtk-bundle/xtrkcad.bundle
@@ -0,0 +1,132 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<app-bundle>
+
+ <meta>
+ <!-- Where to pick up the GTK+ installation, icon themes,
+ etc. Note that "/opt/local" is evaluated to the
+ value of the environment variable JHBUILD_PREFIX. You can
+ define additional prefixes and refer to them in paths
+ throughout this file on the form "${prefix:name}". This is
+ useful for installing certain libraries or even the
+ application itself separately. Note that JHBUILD_PREFIX is
+ defined by jhbuild, so it you are not using jhbuild you can
+ either define your own or just hardcode the path here.
+ -->
+ <prefix name="default">/opt/local</prefix>
+
+ <!-- The project directory is the default location of the created
+ app. If you leave out the path, the current directory is
+ used. Note the usage of an environment variable here again.
+ -->
+
+ <destination overwrite="yes">${project}/bin</destination>
+
+
+ <!-- Comment this out to keep the install names in binaries -->
+
+ <run-install-name-tool/>
+
+
+ <!-- Optionally specify a launcher script to use. If the
+ application sets up everything needed itself, like
+ environment variable, linker paths, etc, a launcher script is
+ not needed. If the source path is left out, the default
+ script will be used.
+ -->
+
+ <launcher-script>${project}/xtrkcad-launcher.sh</launcher-script >
+
+
+ <!-- Not implemented: Optional runtime, could be python or mono
+ for example.
+ -->
+ <!-- runtime copy="yes">/usr/bin/python</runtime -->
+ <!-- Indicate the active gtk version to use. This is needed only
+ for gtk+-3.0 projects. -->
+ <gtk>gtk+-2.0</gtk>
+ </meta>
+
+ <!-- The special macro "${project}" refers to the directory where
+ this bundle file is located. The application name and bundle
+ identifier are taken from the plist file.
+ -->
+ <plist>${project}/info-xtrkcad.plist</plist>
+
+ <main-binary dest="${bundle}">${project}/bin/xtrkcad</main-binary>
+
+ <!-- Copy in the input methods. Dunno if they actually work with
+ OSX. Note the ${gtkdir} macro, which expands to the correct
+ library subdirectory for the specified gtk version. -->
+ <binary>
+ ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
+ </binary>
+
+<!-- And the print backends -->
+ <binary>
+ ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
+ </binary>
+
+<!-- Starting with 2.24, gdk-pixbuf installs into its own directory. -->
+ <binary>
+ ${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so
+ </binary>
+
+<!-- No longer needed for pango >= 1.38
+ <binary>
+ ${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
+ </binary>
+-->
+
+ <!-- Translation filenames, one for each program or library that you
+ want to copy in to the bundle. The "dest" attribute is
+ optional, as usual. Bundler will find all translations of that
+ library/program under the to the bundle. The "dest" attribute is
+ optional, as usual. Bundler indicated directory and copy them.-->
+
+
+ <!-- Data to copy in, usually Glade/UI files, images, sounds files
+ etc. The destination inside the bundle can be specified if the
+ files should end up at a different location, by using the
+ "dest" property. The destination must then start with the macro
+ "${bundle}", which refers to the bundle root directory.
+ -->
+ <!--
+ <data>
+ ${prefix}/share/gtk3-demo
+ </data>
+ -->
+
+<!-- Copy in the glib schemas - needed for Help function -->
+ <data>
+ ${prefix}/share/glib-2.0/schemas
+ </data>
+ <data>
+ ${prefix}/etc/xdg
+ </data>
+
+
+ <!-- Copy in the themes data. You may want to trim this to save space
+ in your bundle. -->
+
+ <data dest="${bundle}/Contents/Resources/xtrkcad">
+ ${project}/share/xtrkcad
+ </data>
+
+
+ <!-- Copy icons. Note that the .icns file is an Apple format which
+ contains up to 4 sizes of icon. You can use
+ /Developer/Applications/Utilities/Icon Composer.app to import
+ artwork and create the file. -->
+ <data dest="${bundle}/Contents/Resources">
+ ${project}/xtrkcad-logo.icns
+ </data>
+
+ <binary dest="${bundle}/Contents/MacOS/helphelper">
+ ${project}/bin/helphelper
+ </binary>
+
+ <data dest="${bundle}/Contents/Resources/XTrackCAD.help">
+ ${project}/share/xtrkcad/XTrackCAD.help
+ </data>
+
+ </app-bundle>
diff --git a/distribution/posix/CMakeLists.txt b/distribution/posix/CMakeLists.txt
index 8263645..7a0ee50 100644
--- a/distribution/posix/CMakeLists.txt
+++ b/distribution/posix/CMakeLists.txt
@@ -25,6 +25,8 @@ SET(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
"/usr/share/locale/*"
"/usr/local/share/locale"
"/usr/local/share/locale/*"
+ "/usr/share/applications"
+ "/usr/share/pixmaps"
)
SET(CPACK_RPM_CHANGELOG_FILE "${CMAKE_CURRENT_SOURCE_DIR}////changelog.txt")
diff --git a/distribution/posix/xtrkcad.spec b/distribution/posix/xtrkcad.spec
index 0d78736..f94976a 100644
--- a/distribution/posix/xtrkcad.spec
+++ b/distribution/posix/xtrkcad.spec
@@ -1,7 +1,7 @@
Summary: XTrkCad
Name: xtrkcad
-Version: 4.2.3
-Release: 1%{?dist}
+Version: 4.2.4a
+Release: 4%{?dist}
License: GPL
Group: Applications/Engineering
Vendor: XTrkCad Fork Project
diff --git a/docs/doxygen/Doxyfile.in b/docs/doxygen/Doxyfile.in
index c64b7d0..323f2ce 100644
--- a/docs/doxygen/Doxyfile.in
+++ b/docs/doxygen/Doxyfile.in
@@ -673,7 +673,8 @@ WARN_LOGFILE = ./doxygen.log
INPUT = "@XTrkCAD_SOURCE_DIR@/app/bin" \
"@XTrkCAD_SOURCE_DIR@/app/wlib/@XTrkCAD_WLIB_DIR@" \
- "@XTrkCAD_SOURCE_DIR@/app/wlib/include/wlib.h"
+ "@XTrkCAD_SOURCE_DIR@/app/wlib/include/wlib.h" \
+ "@XTrkCAD_SOURCE_DIR@/app/dynstring"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/notes b/notes
deleted file mode 100644
index d956946..0000000
--- a/notes
+++ /dev/null
@@ -1,12 +0,0 @@
-* All: Update help
-* Linux: Installation from self extracting archive accepts install path
-* Linux/OSX: Remove absolute path from source packages
-* All: remove all dependencies on obsolete XTRKCAD_USE_LAYOUTCONTROL conditional
-* Moved tag Release_4_2_4a to changeset 73cf3917555f (from changeset c0c1c81628cd)
-* Update release notes
-* Added tag Release_4_2_4a for changeset c0c1c81628cd
-* Update release notes
-* All: New parameter file for Micro Engineering HOn3 Turnouts
-* Windows: Fix bug 157 Crash on color change when drawing lines
-* All: Updated parameter file for Kato N scale
-* All: Fix build problem with block and switchmotor feature
diff --git a/xtrkcad-config.h.in b/xtrkcad-config.h.in
index 6ff0f57..0e8dfad 100644
--- a/xtrkcad-config.h.in
+++ b/xtrkcad-config.h.in
@@ -22,6 +22,7 @@
/* Generated file, do not edit! */
#cmakedefine XTRKCAD_USE_GETTEXT
+#cmakedefine XTRKCAD_TESTING
#define XTRKCAD_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
#define XTRKCAD_PACKAGE "@XTRKCAD_PACKAGE@"